当已知结构但不知道密钥时,反序列化JSON

时间:2019-07-07 07:10:41

标签: json rust

我正在尝试反序列化一些加密货币交换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 个答案:

答案 0 :(得分:2)

doc有一个相关示例。您需要放置HashMap并使用flatten属性:

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