将json中的所有snake_case键转换为camelCase键 [英] Converting all snake_case keys in a json to camelCase keys

查看:68
本文介绍了将json中的所有snake_case键转换为camelCase键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In Go, how can we convert snake_case keys in a JSON to camelCase ones recursively?

我正在用 Go 编写一个 http api.这个 api 从数据存储中获取数据,进行一些计算并将响应作为 JSON 返回.

I am writing one http api in Go. This api fetches data from datastore, does some computation and return the response as JSON.

情况是数据存储 (elasticsearch) 中的 JSON 文档带有 snake_case 键,而 API 响应应该是基于驼峰命名的(这只是为了与项目中的其他 api 标准保持一致).插入 ES 的源代码无法修改.所以它只需要在 api 级别进行密钥转换.

Situation is that the JSON document in the datastore (elasticsearch) is present with snake_case keys while the API response should be camelCase based (this is just to align with other api standard within project). The source which inserts into ES can't be modified. So its only at the api level keys conversion has to take place.

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

I have written a struct which is reading JSON from datastore nicely. But how can I convert the keys to camlelCase in Go?

JSON 可以嵌套并且所有键都必须转换.JSON 是任意大的.即一些键只是映射到类型接口{}

The JSON is can be nested and all keys has to be converted. The JSON is arbitrarily large. i.e. some keys are just mapped to type interface{}

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

I am also using go's echo framework for writing the api.

例如

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

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

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

Any pointers on how to do this in 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"`
}

推荐答案

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

Since Go 1.8 you can define two structs that only differ in their tags and trivially convert between the two:

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 转换函数.

To do this in general, attempt to unmarshal the JSON document into a map. If it succeeds, fix all the keys and recursively call your function for each value in the map. The example below shows how to convert all keys to upper case. Replace fixKey with the snake_case conversion function.

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

这篇关于将json中的所有snake_case键转换为camelCase键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆