如何在另一个字段中指定值类型的地方反序列化JSON?

时间:2019-01-21 17:32:40

标签: json rust serde

我不确定如何尝试反序列化如下所示的JSON:

{
    "columns": [
        {
            "name": "stringColumn",
            "type": "string"
        },
        {
            "name": "DateColumn",
            "type": "date"
        },
        {
            "name": "NumberColumn",
            "type": "number"
        }
    ],
    "data": [
        [
            "This is a string",
            1548091093000,
            123
        ]
    ]
}

columns向量描述data向量的元素内条目的类型和数量。上面的示例可以这样转换为CSV(忽略类型):

stringColumn,DateColumn,NumberColumn
"This is a string",1548091093000,123

一些额外的挑战:

  1. number可以是整数或浮点数。我应该将其表示为枚举吗?
  2. 大数1548091093000是自UNIX时代以来的毫秒数(等于Monday, January 21, 2019 5:18:13 PM)。因为我有日期(使用纪元)和数字,所以如果不访问“标题”说明,就无法轻松区分它们。
  3. 我正在使用restson来调用REST API,该API返回上面的JSON。 restson将使用最终类型调用serde_json::from_str()。这意味着该类型必须实现Deserialize

我该如何反序列化?

1 个答案:

答案 0 :(得分:2)

您的数据是完全,毫无希望的动态数据,这意味着您无需使用任何不错的工具,例如推导Deserialize

您需要使用serde_json::Value,该数据是所有可能的JSON类型的枚举。不过,您可以为固定结构派生一个结构:

use serde_derive; // 1.0.84
use serde_json::{self, Value}; // 1.0.34 

static INPUT: &str = r#"
{
    "columns": [
        {
            "name": "stringColumn",
            "type": "string"
        },
        {
            "name": "DateColumn",
            "type": "date"
        },
        {
            "name": "NumberColumn",
            "type": "number"
        }
    ],
    "data": [
        [
            "This is a string",
            1548091093000,
            123
        ]
    ]
}
"#;

#[derive(Debug, serde_derive::Deserialize)]
struct Thing {
    columns: Vec<Column>,
    data: Vec<Vec<Value>>,
}

#[derive(Debug, serde_derive::Deserialize)]
struct Column {
    name: String,
    r#type: String,
}

fn main() {
    let data = serde_json::from_str::<Thing>(INPUT);
    println!("{:#?}", data)
}
  

数字可以是整数或浮点数

这已经由serde_json::Number

处理

另请参阅: