如何在将 json 解组为结构时过滤掉重复项?

How to filter out duplicates while unmarshalling json into struct?

我有这个 json,我正在尝试将其解组到我的结构中。

{
  "clientMetrics": [
    {
      "clientId": 951231,
      "customerData": {
        "Process": [
          "ABC"
        ],
        "Mat": [
          "KKK"
        ]
      },
      "legCustomer": [
        8773
      ]
    },
    {
      "clientId": 1234,
      "legCustomer": [
        8789
      ]
    },
    {
      "clientId": 3435,
      "otherIds": [
        4,
        32,
        19
      ],
      "legCustomer": [
        10005
      ]
    },
    {
      "clientId": 9981,
      "catId": 8,
      "legCustomer": [
        13769
      ]
    },
    {
      "clientId": 12124,
      "otherIds": [
        33,
        29
      ],
      "legCustomer": [
        12815
      ]
    },
    {
      "clientId": 8712,
      "customerData": {
        "Process": [
          "College"
        ]
      },
      "legCustomer": [
        951
      ]
    },
    {
      "clientId": 23214,
      "legCustomer": [
        12724,
        12727
      ]
    },
    {
      "clientId": 119812,
      "catId": 8,
      "legCustomer": [
        14519
      ]
    },
    {
      "clientId": 22315,
      "otherIds": [
        32
      ],
      "legCustomer": [
        12725,
        13993
      ]
    },
    {
      "clientId": 765121,
      "catId": 8,
      "legCustomer": [
        14523
      ]
    }
  ]
}

我用这个tool生成结构如下所示-

type AutoGenerated struct {
    ClientMetrics []ClientMetrics `json:"clientMetrics"`
}
type CustomerData struct {
    Process []string `json:"Process"`
    Mat     []string `json:"Mat"`
}
type ClientMetrics struct {
    ClientID     int          `json:"clientId"`
    CustomerData CustomerData `json:"customerData,omitempty"`
    LegCustomer  []int        `json:"legCustomer"`
    OtherIds     []int        `json:"otherIds,omitempty"`
    CatID        int          `json:"catId,omitempty"`
    CustomerData CustomerData `json:"customerData,omitempty"`
}

现在我的困惑是,我有很多字符串或整数数组,那么如何过滤掉重复项?我相信 golang 中没有设置数据类型,所以我怎么能在这里实现同样的事情呢?基本上,当我将 json 解组到我的结构中时,我需要确保根本不存在重复项。有什么办法可以做到这一点?如果是,有人可以提供一个示例,说明如何为我的上述 json 实现这一点,以及我应该如何为此设计我的结构。

更新

所以基本上只是像这样使用并更改我的结构定义,仅此而已?在内部它会调用 UnmarshalJSON 并处理重复项?我会将 json 字符串和结构传递给 JSONStringToStructure 方法。

func JSONStringToStructure(jsonString string, structure interface{}) error {
    jsonBytes := []byte(jsonString)
    return json.Unmarshal(jsonBytes, structure)
}

type UniqueStrings []string

func (u *UniqueStrings) UnmarshalJSON(in []byte) error {
    var arr []string
    if err := json.Unmarshal(in, arr); err != nil {
        return err
    }
    *u = UniqueStrings(dedupStr(arr))
    return nil
}

func dedupStr(in []string) []string {
    seen:=make(map[string]struct{})
    w:=0
    for i:=range in {
        if _,s:=seen[in[i]]; !s {
            seen[in[i]]=struct{}{}
            in[w]=in[i]
            w++
        }
    }
    return in[:w]
}

理想情况下,您应该 post 处理这些数组以删除重复项。但是,您可以在使用带有解组器的自定义类型进行解组期间实现此目的:

type UniqueStrings []string

func (u *UniqueStrings) UnmarshalJSON(in []byte) error {
  var arr []string
  if err:=json.Unmarshal(in,arr); err!=nil {
     return err
  }
  *u=UniqueStrings(dedupStr(arr))
  return nil
}

哪里

func dedupStr(in []string) []string {
   seen:=make(map[string]struct{})
   w:=0
   for i:=range in {
      if _,s:=seen[in[i]]; !s {
         seen[in[i]]=struct{}{}
         in[w]=in[i]
         w++
      } 
   }
   return in[:w]
}

您可以对 []ints 使用类似的方法。

您在结构中使用自定义类型:

type CustomerData struct {
    Process UniqueStrings `json:"Process"`
    Mat     UniqueStrings `json:"Mat"`
}