【问题标题】:Rust: Serializing a nested json stirng to a BTree<string,string>Rust:将嵌套的 json 字符串序列化为 BTree<string,string>
【发布时间】:2022-01-19 17:42:58
【问题描述】:

我正在尝试将嵌套的 json 序列化为 BTree。 我将根据需要使用此集合的特定元素绑定到不同的结构。

JSON

{
    "data": "some_data",
    "key": "some_key",
    "nestedValue": {
        "timestamp": "0",
        "d1": "d1",
        "d2": "d2",
        "time": 0,
        "secindaryNestedValue": [{
                "d3": "test1",
                "d4": "test2"
            },
            {
                "d3": "test3",
                "d4": "test4"
            }
        ]
    },
    "timestamp": 0
}

我正在尝试将其序列化如下:

    let input: BTreeMap<String, String> = serde_json::from_str(INPUT).unwrap();
    println!("input -> {:?}",input);

我想得到如下输出:

BTree 项目

Key             Value
data            some_data
key             some_key
nested_value    "{\"d1\":\"d1\",\"d2\":\"d2\",\"time\":0,\"secindaryNestedValue\":[{\"d3\":\"test1\",\"d4\":\"test2\"},{\"d3\":\"test3\",\"d4\":\"test4\"}]}"  
timestamp        0

我这样做是为了让我的嵌套 json 尽可能通用。

在随后的操作中,我将使用 serde 将嵌套的 json 绑定到一个结构,如下所示:

use serde_derive::Deserialize;
use serde_derive::Serialize;

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Root {
    pub data: String,
    pub key: String,
    pub nested_value: NestedValue,
    pub timestamp: i64,
}

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct NestedValue {
    pub timestamp: String,
    pub d1: String,
    pub d2: String,
    pub time: i64,
    pub secindary_nested_value: Vec<SecindaryNestedValue>,
}

#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SecindaryNestedValue {
    pub d3: String,
    pub d4: String,
}

我想稍后使用嵌套值, 将 json 字符串转换为 json 并绑定到类似的结构体上。

对不使用 BTree 和更好的东西的建议持开放态度,但我的用例要求我将内部嵌套的 json 作为字符串,以后可以绑定。

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=4afbad3da5584bc67c9e70ae08f41cee

【问题讨论】:

  • 你在找serde_json::value::RawValue吗?

标签: json parsing rust hashmap serde


【解决方案1】:

(可能在 2 个月后对 OP 没有用,但为其他读者提供了一些意见。)

我强烈怀疑你不想要BTreeMap。这些主要用于排序,但这些 JSON 键值对不是您希望按键排序的东西。您可以尝试HashMap&lt;String, String&gt;,但我再次怀疑这不是您真正想要的。最接近您的问题的合理答案可能是使用serde_json::Value,它是一种可以匹配任何有效 JSON 的泛型类型。它被实现为

pub enum Value {
    Null,
    Bool(bool),
    Number(Number),
    String(String),
    Array(Vec<Value>),
    Object(Map<String, Value>),
}

因此,此 JSON 将反序列化为 Object,您可以使用包含的地图来执行您需要的任何操作。如果您真的想将嵌套值放回字符串,请使用serde_json::to_string 在任何必要的位置将其转换回。随后,您可以使用serde_json::from_valueValue 转换为更具体的类型,例如Root

但是我会注意到,根据我的经验,使用Value 很少是最好的方法。我只在与我集成的 API 发送一些任意 JSON 作为某些数据的一部分时才使用它,并且随后要求将相同的 JSON 作为另一个请求的一部分发回。您的确切要求并不完全清楚,但我会尽力猜测您真正想要什么:

  • 要序列化(Rust 到 JSON,在问题中指定但可能不是你的意思),你显示的结构应该很好地转换为 serde_json::to_string 指定的 JSON 格式。根据问题的其余部分,您似乎有一些更复杂的要求,这可能意味着需要更改这些要求,但原则是正确的。

  • 要反序列化(JSON 到 Rust),这取决于您获取的数据。如果您知道数据以给定的格式出现,则可以将其直接反序列化为您定义的 Root 类型,并且嵌套值将正确构建为适当的类型。如果您需要以某种方式修改数据,我强烈建议您在反序列化类型而不是字符串上这样做。即使您想用 JSON 字符串形式的其他数据替换其中的某些部分,最好反序列化该数据(可能为 NestedValue 或其他类型)并使用这些 Rust 类型。这比尝试编辑 JSON 字符串要可靠得多。如果您需要将部分数据作为 JSON 呈现给外部用户或服务,您可以再次序列化。

  • 如果您不确定数据是否会采用您编写的格式(您的部分问题表明您需要更多通用类型,也许是因为这个原因?),您有几个选项基于它可能是。如果某些值可能丢失,您可以使用 Option 作为反序列化类型:例如。如果nestedValue 可能丢失,请在Root 结构中使用pub nested_value: Option&lt;NestedValue&gt;。如果它可以遵循其他一些已知模式,您可以使用enum 来匹配它们:例如。

#[derive(Debug, Deserialize)]
#[serde(untagged)] // This tells serde to figure out from the type structure rather than the name.
pub enum RootEnum {
    Root {
        data: String,
        key: String,
        nested_value: NestedValue, // This can be used as it was.
        timestamp: i64,
    }
    SomeOtherType {
        foo: Bar
    }
}

如果您这样做,您可能需要一个match 块来确定如何使用数据。如果您真的不知道这些数据可能是什么样子,则需要使用Value 对其进行反序列化。但是,那时我怀疑您无论如何都无法使用数据,因此您可能应该尝试反序列化为您知道的类型,并针对不匹配的错误执行适当的操作。无论如何,您都需要一些错误处理,因为 JSON 可能无效。

无论如何,这已经成为一个很长的答案,希望它对某人有用。

【讨论】:

    猜你喜欢
    • 2014-01-10
    • 1970-01-01
    • 2016-01-25
    • 2017-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多