json - 在同一属性中解析具有多种表示形式的 JSON

标签 json rust serde

我对 Rust 比较陌生,对 Serde 更是如此,所以我很难确定这是否可行。我有一个 JSON 文件,它对同一个键有两种不同的表示形式:

"coordinates": [
  [
    [
      121.423364,
      24.9913596
    ],
    [
      121.4233327,
      24.9912977
    ],
  ]
]

还有这个:

"coordinates": [
  [
    121.4472492,
    25.0052053
  ],
  [
    121.4466457,
    25.0028547
  ]
]

同一个属性中有一个二维数组和一个三维数组表示方式。这使得文件难以序列化。

这是我实现的代码:

#[derive(Serialize, Deserialize, Debug)]
struct Geometry {
    #[serde(deserialize_with = "string_or_number", rename = "type")]
    geometry_type: Value,
    #[serde(default, skip_serializing_if = "Vec::is_empty", rename = "coordinates")]
    geometry_coor: Vec<Coordinates>,
    #[serde(default, skip_serializing_if = "Vec::is_empty", rename = "coordinates")]
    geometry_coor2: Vec<Vec<Coordinates>>,
}

#[derive(Serialize, Deserialize, Debug)]
struct Coordinates {
    #[serde(deserialize_with = "string_or_number")]
    longitude: Value,
    #[serde(deserialize_with = "string_or_number")]
    latitude: Value,
}

fn string_or_number<'de, D>(de: D) -> Result<Value, D::Error>
where
    D: serde::Deserializer<'de>,
{
    let helper: Value = Deserialize::deserialize(de)?;

    match helper {
        Value::Number(n) => {
            println!("{:#?}", n.as_f64().unwrap().to_string());
            Ok(Value::Number(n))
        }
        Value::String(s) => Ok(json!(s)),
        _ => Ok(json!(null)),
    }
}

我在序列化坐标文件的 struct Geometry 中遇到了麻烦。

有什么方法可以处理这种形式吗?

最佳答案

我得到了 help from the serde-rs developer :

I would recommend using an untagged enum to represent a coordinate array that can be 2d or 3d. Playground link

修改后的代码如下:

#[derive(Serialize, Deserialize, Debug)]
struct Geometry {
    #[serde(deserialize_with = "string_or_number", rename = "type")]
    geometry_type: Value,
    #[serde(default, skip_serializing_if = "Vec::is_empty", rename = "coordinates")]
    geometry_coor: Vec<Coordinates_form>,
}

#[derive(Serialize, Deserialize, Debug)]
#[serde(untagged)]
enum Coordinates_form {
    #[serde(skip_serializing)]
    OneD(Coordinates),
    #[serde(skip_serializing)]
    TwoD(Vec<Coordinates>),
    #[serde(skip_serializing)]
    ThreeD(Vec<Vec<Coordinates>>),
}

#[derive(Deserialize, Debug)]
struct Coordinates {
    #[serde(deserialize_with = "string_or_number")]
    longitude: Value, 
    #[serde(deserialize_with = "string_or_number")]
    latitude: Value,
}

fn string_or_number<'de, D>(de: D) -> Result<Value, D::Error>
where
    D: serde::Deserializer<'de>,
{
    let helper: Value = Deserialize::deserialize(de)?;

    match helper {
        Value::Number(n) => {
            println!("{:#?}", n.as_f64().unwrap().to_string());
            Ok(Value::Number(n))
        }
        Value::String(s) => Ok(json!(s)),
        _ => Ok(json!(null)),
    }
}

关于json - 在同一属性中解析具有多种表示形式的 JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51890312/

相关文章:

http - Rust/Serde/HTTP : Serialize `Option<http::Method>`

javascript - 如何使用 ajax 发布一些内容然后检索它?

javascript - 如何将 JSON 记录作为单个元素推送到空数组中 [Angular]

c - 由于stdint.h,Bindgen不会交叉编译到ARM

c++ - Rust 中从 extern "C"方法返回动态字符串以供 C 或 C++ 使用的最佳方法

linux - 我如何使用 Cargo 构建目标文件?

url - `url_serde`要求不相关的特征范围

wcf - JSONP 对您的 API 来说是必须的吗?

java - 升级到 Java8 和端点 V2 后 AppEngine 出现错误

rust - 如何在返回 Result<() , Error> 的函数中从 Serde 返回错误