【问题标题】:Converting all snake_case keys in a json to camelCase keys将json中的所有snake_case键转换为camelCase键
【发布时间】:2017-10-27 15:53:23
【问题描述】:

在 Go 中,我们如何将 JSON 中的 snake_case 键递归转换为 camelCase 键?

我正在用 Go 编写一个 http api。此 api 从数据存储中获取数据,进行一些计算并以 JSON 形式返回响应。

情况是数据存储区 (elasticsearch) 中的 JSON 文档带有 snake_case 键,而 API 响应应该基于 camelCase(这只是为了与项目中的其他 api 标准保持一致)。插入到 ES 中的源不能修改。所以它只需要在 api 级别进行键转换。

我编写了一个结构,它可以很好地从数据存储中读取 JSON。但是如何在 Go 中将密钥转换为 camlelCase?

JSON 可以嵌套,所有键都必须转换。 JSON 任意大。即一些键只是映射到类型 interface{}

我也在使用 go 的 echo 框架来编写 api。

例如

{
"is_modified" : true,
   { attribute": 
     {
      "legacy_id" : 12345 
     }
   }
}

{
"isModified" : true,
   { attribute": 
     {
      "legacyId" : 12345 
     }
   }
}

关于如何在 Go 中执行此操作的任何指示?

结构:

type data_in_es struct {
IsModified bool `json:"is_modified,omitempty"`
Attribute *attribute `json:"attribute,omitempty"`
}

type attribute struct {
    LegacyId int `json:"legacy_id,omitempty"`
}

【问题讨论】:

  • 只需修改你的 json 结构标签。 goplay.space/#PQxts3yhLi
  • @reticentroot 我认为问题在于他需要保留他当前的 JSON 结构标签来解组来自数据源的 JSON,然后需要用新的 JSON 标签编组相同的数据,在这种情况下他' d 需要做一些自定义编组。
  • 然后创建两个结构体。一个用于解组snake_case并转换为编组CamelCase的那个
  • 好问题 +1。首选的 Go 术语是 MixedCaps 或 mixedCaps 而不是 CamelCase。见golang.org/doc/effective_go.html#mixed-caps
  • @badjan 您能否与我们分享您如何解决此问题的信息?

标签: json api go


【解决方案1】:

从 Go 1.8 开始,您可以定义两个仅在标签上有所不同的结构,并在两者之间进行简单的转换:

package main

import (
    "encoding/json"
    "fmt"
)

type ESModel struct {
    AB string `json:"a_b"`
}

type APIModel struct {
    AB string `json:"aB"`
}

func main() {
    b := []byte(`{
            "a_b": "c"
    }`)

    var x ESModel
    json.Unmarshal(b, &x)

    b, _ = json.MarshalIndent(APIModel(x), "", "  ")
    fmt.Println(string(b))
}

https://play.golang.org/p/dcBkkX9zQR

一般而言,要执行此操作,请尝试将 JSON 文档解组为地图。如果成功,请修复所有键并为地图中的每个值递归调用您的函数。下面的示例显示了如何将所有键转换为大写。将fixKey替换为snake_case转换函数。

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "strings"
)

func main() {
    // Document source as returned by Elasticsearch
    b := json.RawMessage(`{
            "a_b": "c",
            "d_e": ["d"],
            "e_f": {
                    "g_h": {
                            "i_j": "k",
                            "l_m": {}
                    }
            }
    }`)

    x := convertKeys(b)

    buf := &bytes.Buffer{}
    json.Indent(buf, []byte(x), "", "  ")
    fmt.Println(buf.String())
}

func convertKeys(j json.RawMessage) json.RawMessage {
    m := make(map[string]json.RawMessage)
    if err := json.Unmarshal([]byte(j), &m); err != nil {
            // Not a JSON object
            return j
    }

    for k, v := range m {
            fixed := fixKey(k)
            delete(m, k)
            m[fixed] = convertKeys(v)
    }

    b, err := json.Marshal(m)
    if err != nil {
            return j
    }

    return json.RawMessage(b)
}

func fixKey(key string) string {
    return strings.ToUpper(key)
}

https://play.golang.org/p/QQZPMGKrlg

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2012-02-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-29
  • 2022-01-25
  • 2017-11-28
  • 1970-01-01
  • 2010-11-13
相关资源
最近更新 更多