如何更改json对象数组的字段名称

时间:2018-02-24 00:24:53

标签: json go

所以我有一个包含大量15个来源的传入数据的项目,当然,每个标签的数据在其余的api中都有不一致的地方。我需要更改一些字段名称以与其他字段名称保持一致,但是当数据源是json对象数组时,我对如何执行此操作感到茫然。我正在尝试做的一个工作示例可以在playground及以下

找到

然而,当数据不是单个json对象时,我似乎缺乏如何使这个工作的知识,而是我解组的对象数组。

另一种方法是在这个example中使用地图,但结果是一样的,与单个对象一样好用,但我似乎无法使用json对象数组。由于我每隔几分钟收集大约8,000条记录,因此不可能通过数组进行迭代。

package main

import (
    "encoding/json"
    "os"
)

type omit bool

type Value interface{}

type CacheItem struct {
    Key    string `json:"key"`
    MaxAge int    `json:"cacheAge"`
    Value  Value  `json:"cacheValue"`
}

func NewCacheItem() (*CacheItem, error) {
    i := &CacheItem{}
    return i, json.Unmarshal([]byte(`{
      "key": "foo",
      "cacheAge": 1234,
      "cacheValue": {
        "nested": true
      }
    }`), i)
}

func main() {
    item, _ := NewCacheItem()

    json.NewEncoder(os.Stdout).Encode(struct {
        *CacheItem

        // Omit bad keys
        OmitMaxAge omit `json:"cacheAge,omitempty"`
        OmitValue  omit `json:"cacheValue,omitempty"`

        // Add nice keys
        MaxAge int    `json:"max_age"`
        Value  *Value `json:"value"`
    }{
        CacheItem: item,

        // Set the int by value:
        MaxAge: item.MaxAge,

        // Set the nested struct by reference, avoid making a copy:
        Value: &item.Value,
    })
}

1 个答案:

答案 0 :(得分:0)

看来您所需的输出是JSON。您可以通过解组成一个结构片来完成转换,然后遍历每个结构以将它们转换为第二个结构类型(上面的匿名结构),将它们附加到切片中,然后将切片封送回JSON:< / p>

package main

import (
    "fmt"
    "encoding/json"
)

type omit bool

type Value interface{}

type CacheItem struct {
    Key    string `json:"key"`
    MaxAge int    `json:"cacheAge"`
    Value  Value  `json:"cacheValue"`
}

type OutGoing struct {
    // Omit bad keys
    OmitMaxAge omit `json:"cacheAge,omitempty"`
    OmitValue  omit `json:"cacheValue,omitempty"`

    // Add nice keys
    Key    string `json:"key"`
    MaxAge int    `json:"max_age"`
    Value  *Value `json:"value"`
}

func main() {
    objects := make([]CacheItem, 0)
    sample := []byte(`[
    {
      "key": "foo",
      "cacheAge": 1234,
      "cacheValue": {
        "nested": true
      }},
    {
      "key": "baz",
      "cacheAge": 123,
      "cacheValue": {
        "nested": true
    }}]`)

    json.Unmarshal(sample, &objects)

    out := make([]OutGoing, 0, len(objects))
    for _, o := range objects {
        out = append(out, OutGoing{Key:o.Key, MaxAge:o.MaxAge, Value:&o.Value})
    }
    s, _ := json.Marshal(out)
    fmt.Println(string(s))
}

此输出

[{"key":"foo","max_age":1234,"value":{"nested":true}},{"key":"baz","max_age":123,"value":{"nested":true}}]

如果为CacheItem类型编写自定义MarshalJSON和UnmarshalJSON方法,而不是依赖struct field标记,则可以跳过此迭代和转换代码。然后你可以将同一个切片传递给Unmarshal和Marshal。

对我来说,使用这些方法没有明显的性能错误 - 与使用+运算符在循环中构建字符串形成鲜明对比 - 如果是这样的情况,那么&#39;通常最好让软件运行然后测试性能,而不是基于对性能问题的担心排除解决方案而不进行实际测试。

如果上述方法存在性能问题,并且您确实希望完全避免编组和解组,则可以查看JSON数据中的字节替换(例如regexp)。我不推荐这种方法,但如果您的更改非常简单且输入非常一致,那么它可以工作,并且它会提供另一种可以进行性能测试的方法,然后您可以比较性能测试结果。