Десериализовать JSON, когда структура известна, но не ключи - PullRequest
0 голосов
/ 07 июля 2019

Я пытаюсь десериализовать некоторый криптообмен JSON. Структура JSON предсказуема, а ключи - нет. Каждый раз, когда сервер добавляет новую валюту, он становится новым ключом. Например, это выглядит примерно так:

{
  "timestamp":"1562405",
  "username":"1234",
  "BTC":
    {"available":"0.00","orders":"0.00000000"},
  "BCH":
    {"available":"0.0000000","orders":"0.00000000"},
  ..

  ..

  "GUSD":
    {"available":"0.00","orders":"0.00"}
}

Я пробовал обычный подход определения структуры для десериализации, но каждый раз, когда появляется новая валюта, в моей программе будет ошибка.

Я подумал, что я просто прочитал бы все это в Value, а затем просто перебрал его вручную, чтобы поместить все в структуру.

let balance_data: Value = serde_json::from_str(&String::from_utf8_lossy(&body)).unwrap();
println!("balance_data: {:?}", balance__data);

for element in balance_data.iter() {
    //push into a proper map...
}

Но я не могу:

no method named `iter` found for type `serde_json::Value`.

Я думал, что положу это в Vec<Value>, но это вызывает панику:

thread 'main' panicked at 'called ``Result::unwrap()` on an `Err` value: Error("invalid type: map, expected a sequence", line: 1, column: 0)'`

Я также экспериментировал с чтением его в HashMap, но, похоже, не смог его взломать.

Было бы замечательно, если бы мы могли сделать что-то вроде:

let balance_data: RecvBalance = serde_json::from_str(&String::from_utf8_lossy(&body)).unwrap();

#[derive(Debug, Deserialize)]
struct RecvBalance {
    timestamp: String,
    username: String,
    HashMap<String, RecvBalanceData>,
}

#[derive(Debug, Deserialize)]
struct RecvBalanceData {
    available: String,
    orders: String,
}

Кто-нибудь имел дело с этой ситуацией? Мне нужна структура с данными баланса, которую я смогу найти позже в моей программе.

1 Ответ

2 голосов
/ 07 июля 2019

У doc есть связанный пример. Вам нужно поставить HashMap и использовать атрибут flatten:

#[derive(Debug, Deserialize)]
struct RecvBalance {
    timestamp: String,
    username: String,
    #[serde(flatten)]
    moneys: HashMap<String, RecvBalanceData>,
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...