serder_json heserialize map со значением Number, boolean или String

Я пытался десериализовать JSON, содержащий объект, значения которого могут быть только String, Boolean или Number.

Вот код, который я использую для этого:

use serde::{Deserialize, Serialize};
use serde_json::Number;
use std::collections::HashMap;

#[derive(Deserialize, Debug, Serialize, Clone)]
pub enum OtherValue {
  Bool(bool),
  Number(Number),
  Text(String),
}

#[derive(Deserialize, Debug, Serialize)]
pub struct Item {
  numbers: HashMap<String, Number>,
  others: HashMap<String, OtherValue>,
}

Вот тесты, которые я поставил, если вы хотите попробовать

#[cfg(test)]
mod tests {
  use super::*;

  #[test]
  fn test_deserialize_with_numbers() {
    let input_str = r#"
      {
        "numbers": {
          "key": 12.34
        },
        "others": {}
      }
    "#;
    let output = serde_json::from_str::<Item>(input_str).unwrap();
    assert_eq!(output.numbers.keys().len(), 1);
    assert_eq!(output.others.keys().len(), 0);
  }

  #[test]
  fn test_deserialize_with_strings() {
    let input_str = r#"
      {
        "numbers": {
          "key": "trololo"
        },
        "others": {}
      }
    "#;
    let output = serde_json::from_str::<Item>(input_str);
    assert_eq!(output.is_err(), true);
  }

  #[test]
  fn test_deserialize_with_boolean_field() {
    let input_str = r#"
      {
        "numbers": {
          "key": true
        },
        "others": {}
      }
    "#;
    let output = serde_json::from_str::<Item>(input_str);
    assert_eq!(output.is_err(), true);
  }

  #[test]
  fn test_deserialize_with_array_field() {
    let input_str = r#"
      {
        "numbers": {
          "key": ["trollo", true, 42]
        },
        "others": {}
      }
    "#;
    let output = serde_json::from_str::<Item>(input_str);
    assert_eq!(output.is_err(), true);
  }

  #[test]
  fn test_deserialize_with_number_tag() {
    let input_str = r#"
      {
        "others": {
          "key": 42
        },
        "numbers": {}
      }
    "#;
    let output = serde_json::from_str::<Item>(input_str).unwrap();
    assert_eq!(output.others.contains_key("key"), true);
  }

  #[test]
  fn test_deserialize_with_string_tag() {
    let input_str = r#"
      {
        "others": {
          "key": "trololo"
        },
        "numbers": {}
      }
    "#;
    let output = serde_json::from_str::<Item>(input_str).unwrap();
    assert_eq!(output.others.contains_key("key"), true);
  }

  #[test]
  fn test_deserialize_with_boolean_tag() {
    let input_str = r#"
      {
        "others": {
          "key": true
        },
        "numbers": {}
      }
    "#;
    let output = serde_json::from_str::<Item>(input_str).unwrap();
    assert_eq!(output.others.contains_key("key"), true);
  }
}

Но, видимо, это не работает должным образом, я не могу десериализовать OtherValue.

Ты хоть представляешь, как я мог это сделать?

Вот детская площадка, если вы хотите попробовать https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=67b43cfd4d12efc6641f5b7fba02889a.


person Jeremie    schedule 02.04.2020    source источник
comment
Отвечает ли это на ваш вопрос? Rust: десериализуйте массив JSON в очень простой настраиваемая таблица   -  person Jmb    schedule 02.04.2020
comment
Вы хотите добавить тег #[serde(transparent)] в OtherValue.   -  person Jmb    schedule 02.04.2020
comment
@Jmb это не помогает. У меня сейчас другие проблемы ...   -  person Jeremie    schedule 02.04.2020
comment
@Jmb явно прозрачный недопустим на enums   -  person Jeremie    schedule 02.04.2020
comment
Извините, это правильный дубликат: stackoverflow.com/questions/52034764/   -  person Jmb    schedule 02.04.2020
comment
@Jmb кроме ссылки ничего не говорит о десериализации, только о сериализации. Конечно, untagged действительно работает, но похоже, что это слишком нетерпеливое решение для дублирования.   -  person Masklinn    schedule 02.04.2020


Ответы (1)