arcnmx / serde-value

Serialization value trees
http://arcnmx.github.io/serde-value/serde_value/
MIT License
43 stars 30 forks source link

Traversing a nested Value #17

Closed sevagh closed 6 years ago

sevagh commented 7 years ago

Hello,

I use Value to get JSON structs from protobuf: https://github.com/sevagh/pq/blob/master/src/decode.rs#L45

I need to go into this structure, find any map with a String key, and modify that key. Here's an example of serde::Value that I need to work with:

Map(
    {
        String(
            "my_child"
        ): Option(
            Some(
                Map(
                    {
                        String(
                            "foo_bar"
                        ): Option(
                            Some(
                                String(
                                    "baz"
                                )
                            )
                        )
                    }
                )
            )
        )
    }
)

Here I need to get the strings "my_child" and "foo_bar".

I'm kinda stuck writing a match statement that can recursively find all the Map(String, _)s in this object. Any suggestions?

sevagh commented 7 years ago

Here's my tentative solution:

fn spec_compliance(json: Value) -> Value {
    match json {
        Value::Map(ref map) => {
            Value::Map(
                map.iter()
                    .map(|(key, value)| match *key {
                        Value::String(ref contents) => (
                            Value::String(to_camel_case(contents)),
                            spec_compliance(value.clone())
                        ),
                        _ => (spec_compliance(key.clone()),
                              spec_compliance(value.clone())),
                    })
                    .collect::<BTreeMap<Value, Value>>(),
            )
        }
        Value::Option(Some(box x)) => spec_compliance(x),
        Value::Seq(x) => Value::Seq(x.into_iter().map(|y| spec_compliance(y)).collect::<Vec<_>>()),
        Value::Newtype(box x) => spec_compliance(x),
        x => x,
    }
}
sevagh commented 6 years ago

No longer need this.