Как десериализовать JSON, где типы значений указаны в другом поле? - PullRequest
0 голосов
/ 21 января 2019

Я не уверен, как мне следует попытаться десериализовать некоторый 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. A number может быть целым числом или числом с плавающей точкой. Должен ли я представлять его как перечисление?
  2. Большое число 1548091093000 - это число миллисекунд , начиная с эпохи UNIX (эквивалентно Monday, January 21, 2019 5:18:13 PM). Поскольку у меня есть даты (используя эпоху) и числа, я не могу их легко отличить, не имея доступа к описанию «заголовка» ...
  3. Я использую restson для вызова REST API, который возвращает JSON выше. Restson вызовет serde_json::from_str() с окончательным типом. Это означает, что этот тип должен реализовывать Deserialize.

Как я могу десериализовать это?

1 Ответ

0 голосов
/ 21 января 2019

Ваши данные полностью, безнадежно динамичны, что означает, что вы не можете использовать какие-либо полезные инструменты, такие как получение 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

Смотри также:

...