将 JSON 解组为具有独特元素的地图切片

Unmarshal JSON into slice of maps with unique elements

提问人:George Livanoss 提问时间:11/11/2022 最后编辑:blackgreenGeorge Livanoss 更新时间:11/11/2022 访问量:107

问:

我正在将一些 json 文件解组到其中,但很多时候源代码是脏的,有许多重复的相等对象。[]map[string]string{}

输入如下所示:

[{"sa1":"8172"},{"sa3":"8175"},{"sa1":"8172"},{"sa3":"8175"},{"sa3":"8175"},{"sa3":"8175"},{"sa1":"8172"},{"sa3":"8175"},{"sa3":"8175"}]

结果是:

map[sa1:8172]
([]map[string]string) (len=9 cap=9) {
 (map[string]string) (len=1) {
  (string) (len=3) "sa1": (string) (len=4) "8172"
 },
 (map[string]string) (len=1) {
  (string) (len=3) "sa3": (string) (len=4) "8175"
 },
 (map[string]string) (len=1) {
  (string) (len=3) "sa1": (string) (len=4) "8172"
 },
 (map[string]string) (len=1) {
  (string) (len=3) "sa3": (string) (len=4) "8175"
 },
 (map[string]string) (len=1) {
  (string) (len=3) "sa3": (string) (len=4) "8175"
 },
 (map[string]string) (len=1) {
  (string) (len=3) "sa3": (string) (len=4) "8175"
 },
 (map[string]string) (len=1) {
  (string) (len=3) "sa1": (string) (len=4) "8172"
 },
 (map[string]string) (len=1) {
  (string) (len=3) "sa3": (string) (len=4) "8175"
 },
 (map[string]string) (len=1) {
  (string) (len=3) "sa3": (string) (len=4) "8175"
 }
}

如何清理地图切片以仅包含唯一元素?

json go 重复 切片

评论


答:

3赞 JimB 11/11/2022 #1

一种选择是将键值对直接解组为可比较的类型,如结构体:

type Elem struct {
    k string
    v string
}

func (e *Elem) UnmarshalJSON(d []byte) error {
    m := map[string]string{}
    if err := json.Unmarshal(d, &m); err != nil {
        return err
    }

    for k, v := range m {
        e.k = k
        e.v = v
        return nil
    }
    return nil
}

一旦您可以单独比较元素,您还可以将其包装在一个集合中,该集合在解组时过滤元素。是在这里隐含地这样做,还是在事后这样做是一个见仁见智的问题。将过滤作为自己的方法可能是一种更好的关注点分离,但为了简洁起见,我将其包括在内。UnmarshalJSON

type Elems []Elem

func (e *Elems) UnmarshalJSON(d []byte) error {
    tmp := []Elem{}
    err := json.Unmarshal(d, &tmp)
    if err != nil {
        return err
    }

    seen := map[Elem]bool{}
    for _, elem := range tmp {
        if seen[elem] {
            continue
        }
        seen[elem] = true
        *e = append(*e, elem)
    }
    return nil
}

然后,您可以解组为:Elems

    elems := Elems{}

    err := json.Unmarshal(js, &elems)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(elems)

这将为您提供两个独特的对:[{sa1 8172} {sa3 8175}]

https://go.dev/play/p/U0iqBAjvz-1