将json中的所有snake_case密钥转换为camel [英] converting all snake_case keys in a json to camelCase keys in golang

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

问题描述

在Golang中,如何将JSON中的snake_case密钥递归转换为camelCase密钥?

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

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

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

情况是,数据存储区(elasticsearch)中的JSON文档带有snake_case键,而API响应应基于camelCase(这只是为了与项目中的其他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.但是,如何在golang中将密钥转换为camlelCase?

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

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

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 
     }
   }
}

TO

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

关于如何在golang中执行此操作的任何指针?

Any pointers on how to do this in golang?

谢谢.

结构:

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 generically, 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密钥转换为camel的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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