I'm writing a CLI tool that reads JSON files and is supposed to convert the JSON object keys into camelCase.
Because this should work with any JSON file, I obviously can't just use strong typing and then #[serde(rename_all = "camelCase")]
.
I can't seem to find an obvious way in serde_json
to make it use the already existing renaming code that serde
clearly has and apply it to a serde_json::value::Value
.
Am I missing something obvious?
You'll have to write a function that recurses through the serde_json::Value
structure and replaces the keys of serde_json::Map
whenever it encounters one. That's a bit awkward to implement, as there is no Map::drain
.
fn rename_keys(json: &mut serde_json::Value) {
match json {
serde_json::Value::Array(a) => a.iter_mut().for_each(rename_keys),
serde_json::Value::Object(o) => {
let mut replace = serde_json::Map::with_capacity(o.len());
o.retain(|k, v| {
rename_keys(v);
replace.insert(
heck::ToLowerCamelCase::to_lower_camel_case(k.as_str()),
std::mem::replace(v, serde_json::Value::Null),
);
true
});
*o = replace;
}
_ => (),
}
}
use std::io::Read;
fn main() {
let mut stdin = vec![];
std::io::stdin()
.read_to_end(&mut stdin)
.expect("Read stdin");
let mut json = serde_json::from_slice::<serde_json::Value>(&stdin).expect("Parse Json");
rename_keys(&mut json);
println!("{}", serde_json::to_string_pretty(&json).unwrap());
}
(Note that rename_keys
will produce a stack overflow on deep JSON structures, but serde_json
only parses to a limited depth by default, so no need to worry. If you do need support for deeply nested structures, have a look at serde_stacker
.)
If you're not interested in the serde_json::Value
itself and just want to transform a JSON string, there's two more ways to go on about this:
serde_json::Value
. An example of such a serializer is here, but you'd have to adopt it to be recursive. (Possibly, doing it at deserialization might be easier than at serialization)serde_json::Value
structure and to the renaming on the token stream (no need to worry when working with GBs of JSON)