将 JSON 的一部分映射到结构

Map part of the JSON to struct

我有天气数据API调用和一些json基本转换:

use serde_json::{Value};

...

let resp = reqwest::get(WEATHER_API_URL).await?.text().await?;
let json: Value = serde_json::from_str(&resp)?;

产生 Object 结果:

Object({
    ...
    "clouds": Object({
        "all": Number(
            0,
        ),
    }),
    "id": Number(
        2950159,
    ),
    "main": Object({
        "feels_like": Number(
            287.04,
        ),
        "humidity": Number(
            34,
        ),
        "pressure": Number(
            1015,
        ),
        "temp": Number(
            288.56,
        ),
        "temp_max": Number(
            290.38,
        ),
        "temp_min": Number(
            287.03,
        ),
    })
    ...

我只想要 main 来自给定形状^的数据。 我有一个结构:

use serde::{Deserialize, Serialize};

...

#[derive(Debug, Serialize, Deserialize)]
struct Main {
  temp: f32,
  feels_like: f32,
  temp_min: f32,
  temp_max: f32,
  pressure: f32,
  humidity: f32
}

如何将 json 的某些部分(main 对象部分)映射到我的 Main 结构?也许有更好的方法来完成这种情况?基本上我需要的是从 JSON 获取一些数据,然后能够在我的代码中使用它。在我的案例中,关键是我的 json 具有包含嵌套实体的复杂结构,我无法将其一对一映射。

你可以有这样的结构:

#[derive(Debug, Serialize, Deserialize)]
struct MainWrapper {
  main: Main,
}

#[derive(Debug, Serialize, Deserialize)]
struct Main {
  temp: f32,
  feels_like: f32,
  temp_min: f32,
  temp_max: f32,
  pressure: f32,
  humidity: f32
}

let deserialized: MainWrapper = serde_json::from_str(&json)?;

或者如果您不想在代码中处理 MainWrapper

impl<'de> Deserialize<'de> for Main {
    fn deserialize<D>(deserializer: D) -> Result<Main, D::Error>
    where
        D: Deserializer<'de>,
    {
        #[derive(Debug, Serialize, Deserialize)]
        struct MainWrapper {
           main: MainInner,
        }

        // You can generally generate such copies with macros

        #[derive(Debug, Serialize, Deserialize)]
        struct MainInner {
           temp: f32,
           feels_like: f32,
           temp_min: f32,
           temp_max: f32,
           pressure: f32,
           humidity: f32
        }
        impl From<MapInner> for Main {
           // ...
        }

        let deserialized: MainWrapper = Deserialize::deserialize(deserializer)?;
        Ok(deserialized.main.into())
    }