Я пытался десериализовать 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.
#[serde(transparent)]
вOtherValue
. - person Jmb   schedule 02.04.2020enums
- person Jeremie   schedule 02.04.2020untagged
действительно работает, но похоже, что это слишком нетерпеливое решение для дублирования. - person Masklinn   schedule 02.04.2020