Serde: How to parse JSON partially. 7 years later?

(This was asked back in 2016. Back then the answer was that it didn't work yet. Progress?)

I'd like to parse structures which contain substructures of unknown form. I can't write

   struct Item {
       name: String,
       value: JsonValue
   }

   struct Msg {
       items: Vec<Item>
   }

because JsonValue is not accepted by serde as a deseralization target. I'd like to get the content parsed into the usual JsonValue tree, from which I can then extract fields.

On a related note, is it possible to deserialize key-value pairs into an array of enums?

serde_json::Value works in that way and it has existed since the initial release of serde to the crates.io at 2015.

4 Likes

There's probably a simpler way, but you can always write your own implementation of Deserialize instead of deriving it: there's a bit of busy work with implementing a serde::de:: Visitor because serde needs to handle formats that aren't self-describing. For JSON, just use deserialize_any in the Deserialize impl, passing a Visitor impl with a visit_map() where you can read and switch on the keys and values in order.

You may also want to look into the optional raw_value feature, which lets you defer parsing part of the JSON tree until later.

Which public visible project has an example of such partial parse?

Within the serde architecture it's actually harder to not allow partial parse. It it bans partial parse it should document why it does so with extra effort. For example serde_urlencoded crate doesn't allow nested fields as documented, since x-www-form-urlencoded format doesn't have such concept.

1 Like

How do you do the second part of this? I have have a JsonValue, and want to parse that into a struct for which Deserialize has been derived. There's "from_str", but not "from_value". I suppose I could serialize the JsonValue into a string and then deserialize from the string, but that's silly.

There literally is "from_value". from_value in serde_json - Rust

3 Likes

Ah, thanks.