[英]How to deserialize in Rust (using serde) optional json parameter that can be either string or string array
我是 Rust 的新手,我正在嘗試使用 serde 庫反序列化 JSON 數據。 我有以下 JSON 結構:
{
“foo”: “bar”,
“speech”: “something”
}
或者
{
“foo”: “bar”,
“speech”: [“something”, “something else”]
}
或者
{
“foo”: “bar”,
}
即語音是可選的,它可以是字符串或字符串數組。
我可以使用以下方法處理反序列化字符串/字符串數組:
#[derive(Debug, Serialize, Deserialize)]
struct foo {
pub foo: String,
#[serde(deserialize_with = "deserialize_message_speech")]
speech: Vec<String>
}
我還可以使用以下方法處理反序列化可選字符串/字符串數組屬性:
#[derive(Debug, Serialize, Deserialize)]
struct foo {
pub foo: String,
#[serde(skip_serializing_if = "Option::is_none")]
speech: Option<Vec<String>>
}
或者
struct foo {
pub foo: String,
#[serde(skip_serializing_if = "Option::is_none")]
speech: Option<String>
}
但是將它們組合在一起根本行不通。 似乎deserialize_with不適用於Option類型。 有人可以建議最直接和最簡單的方法來實現這個(serde 可能非常復雜,我見過一些瘋狂的東西:))?
嘗試對speech
字段使用 Enum 類型:
#[derive(Serialize, Deserialize)]
#[serde(untagged)]
enum Speech {
Str(String),
StrArray(Vec<String>),
}
#[derive(Debug, Serialize, Deserialize)]
struct foo {
pub foo: String,
speech: Option<Speech>,
}
枚舉是在 Rust 中表示變體類型的首選方式。 有關詳細信息,請參閱https://serde.rs/enum-representations.html 。
與#[serde(untagged)] 一起工作!
use serde_json;
use std::result::Result;
use std::error::Error;
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
#[serde(untagged)]
enum Speech {
Str(String),
StrArray(Vec<String>),
}
#[derive(Debug, Serialize, Deserialize)]
struct Foo {
pub foo: String,
#[serde(skip_serializing_if = "Option::is_none")]
speech: Option<Speech>,
}
fn main() -> Result<(), Box<dyn Error>> {
let json1 = r#"
{
"foo": "bar",
"speech": "something"
}
"#;
let json2 = r#"
{
"foo": "bar",
"speech": ["something", "something else"]
}
"#;
let json3 = r#"
{
"foo": "bar"
}
"#;
let foo1: Foo = serde_json::from_str(json1)?;
let back_to_str_foo1 = serde_json::to_string(&foo1).unwrap();
println!("foo1 {:#?}", foo1);
println!("back_to_str_foo1 {}", back_to_str_foo1);
let foo2: Foo = serde_json::from_str(json2)?;
let back_to_str_foo2 = serde_json::to_string(&foo2).unwrap();
println!("foo1 {:#?}", foo2);
println!("back_to_str_foo2 {}", back_to_str_foo2);
let foo3: Foo = serde_json::from_str(json3)?;
let back_to_str_foo3 = serde_json::to_string(&foo3).unwrap();
println!("foo1 {:#?}", foo3);
println!("back_to_str_foo3 {}", back_to_str_foo3);
Ok(())
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.