繁体   English   中英

将 serde_json 值键转换为驼峰式

[英]Convert serde_json Value keys to camelCase

我正在编写一个读取 JSON 文件的 CLI 工具,应该将 JSON object 键转换为驼峰命名法。

因为这应该适用于任何 JSON 文件,所以我显然不能只使用强类型然后使用#[serde(rename_all = "camelCase")]

我似乎无法在serde_json中找到一种明显的方法来使其使用serde显然已经存在的重命名代码并将其应用于serde_json::value::Value

我错过了一些明显的东西吗?

您必须编写一个 function 递归通过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());
}

(请注意, rename_keys会在深度 JSON 结构上产生堆栈溢出,但serde_json默认情况下仅解析到有限的深度,因此无需担心。如果您确实需要支持深层嵌套结构,请查看serde_stacker 。)


如果您对serde_json::Value本身不感兴趣,只想转换 JSON 字符串,那么还有两种方法可以转换为 go:

  • 您可以通过为围绕serde_json::Value的包装器结构编写自定义序列化程序来对序列化进行重命名。 此处提供了此类序列化程序的示例,但您必须采用它才能递归。 (可能在反序列化时比在序列化时更容易)
  • 编写一个 JSON 分词器(或获取一个包含分词器的箱子)以跳过创建实际的serde_json::Value结构和对令牌 stream 的重命名(使用 GB 的 JSON 时无需担心)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM