Как десериализовать JSON, где типы значений указаны в другом поле?

Я не уверен, как я должен пытаться десериализовать некоторый 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 вызвать API REST, который возвращает JSON выше. Рестсон позвонит serde_json::from_str() с окончательным типом. Это означает, что этот тип должен реализовывать Deserialize,

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

1 ответ

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

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

Другие вопросы по тегам