我正在编写一个CLI工具,它读取JSON文件,并将JSON对象键转换为camelCase。因为这应该适用于任何JSON文件,所以我显然不能只使用强类型,然后再使用#[serde(rename_all = "camelCase")]。在serde_json中,我似乎找不到一种明显的方法来使它使用serde显然已经存在的重命名代码,并将其应用于serde_json::value::Value。我是不是漏掉了什么明显的东西?
#[serde(rename_all = "camelCase")]
serde_json
serde
serde_json::value::Value
v09wglhw1#
你必须写一个函数,递归通过serde_json::Value结构,并在遇到serde_json::Map时替换它的键。这有点难以实现,因为没有Map::drain。
serde_json::Value
serde_json::Map
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 rename_keys将在深度JSON结构上产生堆栈溢出,但是serde_json默认情况下只解析到有限的深度,所以不必担心。如果确实需要对深度嵌套结构的支持,请查看serde_stacker。)如果您对serde_json::Value本身不感兴趣,只想转换JSON字符串,还有两种方法可以继续:
rename_keys
serde_stacker
1条答案
按热度按时间v09wglhw1#
你必须写一个函数,递归通过
serde_json::Value
结构,并在遇到serde_json::Map
时替换它的键。这有点难以实现,因为没有Map::drain
。(Note
rename_keys
将在深度JSON结构上产生堆栈溢出,但是serde_json
默认情况下只解析到有限的深度,所以不必担心。如果确实需要对深度嵌套结构的支持,请查看serde_stacker
。)如果您对
serde_json::Value
本身不感兴趣,只想转换JSON字符串,还有两种方法可以继续:serde_json::Value
的 Package 结构编写一个自定义序列化程序。这里有一个这样的序列化程序的示例,但您必须采用它来实现递归。(可能在反序列化时进行重命名比在序列化时更容易)serde_json::Value
结构和对令牌流的重命名(使用JSON的GB时无需担心)