簡體   English   中英

如何使用 serde 將 JSON 數組反序列化為結構?

[英]How to deserialize a JSON array into a struct using serde?

我正在嘗試將以下 JSON 片段反序列化為 struct ShapeVec

use serde::{Deserialize, Serialize};
use serde_json::{Result, Value};

#[derive(Debug, Serialize, Deserialize)]
struct Shape {  // this struct is not working, for display purpose only
    shape_type: String,
    d0: f64,
    d1: f64,
    d2: f64, //optional, like the case of "dot"
    d3: f64, //optional, like the case of "circle"
}

let json = r#"
  {[
    ["line", 1.0, 1.0, 2.0, 2.0],
    ["circle", 3.0, 3.0, 1.0],
    ["dot", 4.0, 4.0]
  ]}"#;

let data: Vec<Shape> = match serde_json::from_str(json)?;

顯然,每種類型的Shape都需要一個String和不同數量的f64來描述它。 我應該如何定義Shape的結構來反序列化 JSON 數據如上所述?

假設您可以控制 JSON 格式,我強烈建議將Shape類型設置為可以表示多個形狀的enum ,並使用 serde 的派生宏來自動實現ShapeSerializeDeserialize序列化。 例子:

use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
struct Point {
    x: f64,
    y: f64,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "type")]
enum Shape {
    Dot { position: Point },
    Line { start: Point, end: Point },
    Circle { center: Point, radius: f64 },
}

fn main() {
    let shapes = vec![
        Shape::Dot {
            position: Point { x: 3.0, y: 4.0 },
        },
        Shape::Line {
            start: Point { x: -2.0, y: 1.0 },
            end: Point { x: 5.0, y: -3.0 },
        },
        Shape::Circle {
            center: Point { x: 0.0, y: 0.0 },
            radius: 7.0,
        },
    ];

    let serialized = serde_json::to_string(&shapes).unwrap();
    println!("serialized = {}", serialized);

    let deserialized: Vec<Shape> = serde_json::from_str(&serialized).unwrap();
    println!("deserialized = {:?}", deserialized);
}

操場

如果您絕對無法更改 JSON 格式,那么 serde 無法幫助您。 將形狀序列化為字符串和浮點數的異構數組是一個非常奇怪的選擇。 您必須自己手動解析它(或至少使用一些解析器板條箱來幫助您),然后手動實現 Deserializer 特征以將其轉換為Shape

我應該如何定義 Shape 的結構來反序列化 JSON 數據如上所述?

您不會,因為您想要的序列化方案對 rust 沒有真正意義,並且 AFAIK serde 不支持它(即使您使用元組變量的enum ,也不支持tag="type" )。

如果您真的不能或不想使用另一個答案中描述的更簡單的結構和序列化方案,我能看到的唯一選擇是實現自定義(反)序列化方案。

特別是因為每個“類型”的數量都會發生變化,否則https://crates.io/crates/serde_tuple會起作用(盡管您總是可以看到skip_serializing_if是否與 serde_tuple 一起使用,這會讓您抑制“額外”字段)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM