< 返回版块

sunnyregion 发表于 2021-07-26 21:04

请问这个json怎么转换为serde的struct

{
    "code": 200,
    "msg": "success",
    "data": {
        "1": {
            "aaa": {
                "num": 0,
                "weight": 0,
                "sku_name": ""
            },
            "bbb": {
                "num": 0,
                "weight": 0,
                "sku_name": ""
            }
        },
        "2": {
            "aaa": {
                "num": 0,
                "weight": 0,
                "sku_name": ""
            },
            "bbb": {
                "num": 0,
                "weight": 0,
                "sku_name": ""
            }
        },
        "3": {
            "aaa": {
                "num": 0,
                "weight": 0,
                "sku_name": ""
            },
            "bbb": {
                "num": 0,
                "weight": 0,
                "sku_name": ""
            },
            "ccc": {
                "num": 0,
                "weight": 0,
                "sku_name": ""
            }
        },
        "4": {
            "aaa": {
                "num": 0,
                "weight": 0,
                "sku_name": ""
            },
            "bbb": {
                "num": 0,
                "weight": 0,
                "sku_name": ""
            }
        }
    }
}

评论区

写评论
aariety 2021-07-27 21:30

如果是直接实现倒是挺简单的:

use std::collections::HashMap;
use serde::{Deserialize};

type DataMap = HashMap<String, Data>;

#[derive(Deserialize, Debug)]
struct Root {
    code: u32,
    msg: String,
    data: HashMap<String, DataMap>,
}

#[derive(Deserialize, Debug)]
struct Data {
    num: u32,
    weight: u32,
    sku_name: String,
}

如果这个 json 中的数字顺序无关紧要,或者你能保证顺序正确的话可以像这样反序列化成列表:

use std::collections::HashMap;
use std::fmt;
use serde::Deserialize;
use serde::Deserializer;
use serde::de::Visitor;
use serde::de::MapAccess;
use serde::de::IgnoredAny;

type DataMap = HashMap<String, Data>;

#[derive(Deserialize, Debug)]
struct Root {
    code: u32,
    msg: String,
    #[serde(deserialize_with = "deserialize_datas")]
    data: Vec<DataMap>,
}

#[derive(Deserialize, Debug)]
struct Data {
    num: u32,
    weight: u32,
    sku_name: String,
}

fn deserialize_datas<'de, D>(deserializer: D) -> Result<Vec<DataMap>, D::Error>
where 
    D: Deserializer<'de> 
{
    struct DatasVisitor;

    impl<'de> Visitor<'de> for DatasVisitor {
        type Value = Vec<DataMap>;

        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
            write!(formatter, "a map")
        }

        fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
        where
            A: MapAccess<'de>
        {
            let mut vec = Vec::new();
            while let Some(IgnoredAny) = map.next_key()? {
                vec.push(map.next_value()?);
            }
            Ok(vec)
        }
    }

    deserializer.deserialize_map(DatasVisitor)
}

当然,如果顺序不能保证也能反序列化成列表。实现方式是类似的。可以参照学习 serde 官方文档。

作者 sunnyregion 2021-07-27 08:39

确实是这个方法。我的问题是我建立了中间的struct,而且随便给了一个名字,这个名字找不到。

谢谢

--
👇
Mike Tang: 那其实就是 HashMap<String, HashMap<String, Item>>

不过这种效率极低,不信可以写个评测代码试试。

Mike Tang 2021-07-27 08:16

那其实就是 HashMap<String, HashMap<String, Item>>

不过这种效率极低,不信可以写个评测代码试试。

munpf 2021-07-26 23:05

除非你的键不全是字符串形式的数字,包含字母等其他字符,那就只能用map了

--
👇
sunnyregion: 使用map效率要比数组高,因为直接定位到,而不是做循环

--
👇
sunnyregion: 这个是go生成的[]map(string,[]map(string,string))

--
👇
Mike Tang: 这种json就是不规范的json,数组就应该用数组。弄成这种1,2,3,4 key没办法优化。性能很低。

munpf 2021-07-26 23:03

?为什么数组要循环?根据你的例子,应该是按照下标来找元素,那么数组直接索引就可以找到了,又不是查找元素在数组中的位置,那才要循环遍历数组。用map可以用字符串等数据结构作为键,然后根据键来直接定位值,如果用数组来存储,那么需要遍历数组,比较键是否相等。可是你这里的键是字符串形式的数字啊,完全可以转换成数字然后用来作为数组的下标。

--
👇
sunnyregion: 使用map效率要比数组高,因为直接定位到,而不是做循环

--
👇
sunnyregion: 这个是go生成的[]map(string,[]map(string,string))

--
👇
Mike Tang: 这种json就是不规范的json,数组就应该用数组。弄成这种1,2,3,4 key没办法优化。性能很低。

johnmave126 2021-07-26 22:48

数组直接寻址,不需要像map一样处理哈希和解决冲突,肯定是数组性能更好

--
👇
sunnyregion: 使用map效率要比数组高,因为直接定位到,而不是做循环

--
👇
sunnyregion: 这个是go生成的[]map(string,[]map(string,string))

--
👇
Mike Tang: 这种json就是不规范的json,数组就应该用数组。弄成这种1,2,3,4 key没办法优化。性能很低。

作者 sunnyregion 2021-07-26 22:10

使用map效率要比数组高,因为直接定位到,而不是做循环

--
👇
sunnyregion: 这个是go生成的[]map(string,[]map(string,string))

--
👇
Mike Tang: 这种json就是不规范的json,数组就应该用数组。弄成这种1,2,3,4 key没办法优化。性能很低。

作者 sunnyregion 2021-07-26 22:08

这个是go生成的[]map(string,[]map(string,string))

--
👇
Mike Tang: 这种json就是不规范的json,数组就应该用数组。弄成这种1,2,3,4 key没办法优化。性能很低。

Mike Tang 2021-07-26 22:07

每个叶子元素都是相同的,在结构组织上就是一个二维数组。

Mike Tang 2021-07-26 22:05

这种json就是不规范的json,数组就应该用数组。弄成这种1,2,3,4 key没办法优化。性能很低。

作者 sunnyregion 2021-07-26 21:33

不是aaa,改了

--
👇
Mike Tang: 你确定同名aaa是正确的?

Mike Tang 2021-07-26 21:23

你确定同名aaa是正确的?

1 共 12 条评论, 1 页