[英]create a map of string from a JSON with unknow key-values in Go
我嘗試使用未定義數量的未知鍵值從JSON創建字符串映射。
這是我的示例JSON文件:
{
"localhost":
{
"tag": "dev_latest",
"vhost": "localhost.com"
},
"development":
{
"tag": "dev_latest",
"vhost": "dev.com"
}
}
我想創建一個map[string]string
,其值如下:
config := map[string]string{
"localhost-tag": "dev_latest",
"localhost-vhost": "localhost.com,
"development-tag": "dev_latest,
...
}
用已知值的"github.com/jmoiron/jsonq"
解析JSON是很容易的,但是在這種情況下, localhost
可以是任何東西,而tag
可以是任何其他東西。
我在Go代碼中的入口點是這樣的:
func ParseJson(){
configPath := GetConfigPath()
b, err := ioutil.ReadFile(configPath)
// Here, I need to create my map of strings..
return configKeyStr
}
任何幫助將不勝感激。
謝謝!
容易做。 簡單地轉換。
package main
import (
"encoding/json"
"fmt"
"log"
)
const s = `
{
"localhost":
{
"tag": "dev_latest",
"vhost": "localhost.com"
},
"development":
{
"tag": "dev_latest",
"vhost": "dev.com"
}
}
`
func main() {
var m map[string]interface{}
err := json.Unmarshal([]byte(s), &m)
if err != nil {
log.Fatal(err)
}
mm := make(map[string]string)
for k, v := range m {
mm[k] = fmt.Sprint(v)
}
fmt.Println(mm)
}
寫扁平化(也許可以作為魅力)
package main
import (
"encoding/json"
"fmt"
"log"
"reflect"
)
const s = `
{
"localhost":
{
"tag": "dev_latest",
"vhost": "localhost.com"
},
"development":
{
"tag": "dev_latest",
"vhost": "dev.com"
}
}
`
func flatten(m map[string]interface{}) map[string]string {
mm := make(map[string]string)
for k, v := range m {
switch reflect.TypeOf(v).Kind() {
case reflect.Map:
mv := flatten(v.(map[string]interface{}))
for kk, vv := range mv {
mm[k+"-"+kk] = vv
}
case reflect.Array, reflect.Slice:
for kk, vv := range m {
if reflect.TypeOf(vv).Kind() == reflect.Map {
mv := flatten(vv.(map[string]interface{}))
for kkk, vvv := range mv {
mm[k+"-"+kkk] = vvv
}
} else {
mm[k+"-"+kk] = fmt.Sprint(vv)
}
}
default:
mm[k] = fmt.Sprint(v)
}
}
return mm
}
func main() {
var m map[string]interface{}
err := json.Unmarshal([]byte(s), &m)
if err != nil {
log.Fatal(err)
}
b, _ := json.MarshalIndent(flatten(m), "", " ")
println(string(b))
}
您不能自動使用此功能,但是可以在“內部”映射上進行調整,並使用簡單的字符串連接( +
運算符)將外部鍵與內部鍵組合在一起。 另外,建議直接解組為map[string]map[string]string
的值,這樣就不必使用類型斷言。 同樣,也不需要為此使用任何外部庫,為此,標准的encoding/json
包就足夠了。
例:
var mm map[string]map[string]string
if err := json.Unmarshal([]byte(src), &mm); err != nil {
panic(err)
}
config := map[string]string{}
for mk, m := range mm {
for k, v := range m {
config[mk+"-"+k] = v
}
}
fmt.Println(config)
輸出是預期的(在Go Playground上嘗試):
map[localhost-tag:dev_latest localhost-vhost:localhost.com
development-tag:dev_latest development-vhost:dev.com]
由於在問題中您提到了不確定數量的未知鍵值 ,因此您可能需要處理嵌套數量未知且具有string
以外的值的JSON文檔。 在這種情況下,您需要Unmarshal
json到map[string]interface{}
,然后使用遞歸制作平面地圖。 將json文檔完整地map[string]interface{}
到map[string]interface{}
,請使用以下功能:
func flatMap(src map[string]interface{}, baseKey, sep string, dest map[string]string) {
for key, val := range src {
if len(baseKey) != 0 {
key = baseKey + sep + key
}
switch val := val.(type) {
case map[string]interface{}:
flatMap(val, key, sep, dest)
case string:
dest[key] = val
case fmt.Stringer:
dest[key] = val.String()
default:
//TODO: You may need to handle ARRAY/SLICE
//simply convert to string using `Sprintf`
//NOTE: modify as needed.
dest[key] = fmt.Sprintf("%v", val)
}
}
}
工作解決方案改編自https://play.golang.org/p/9SQsbAUFdY上的 mattn答案
正如mattn指出的那樣,當您想回寫配置值時可能會遇到問題。 在這種情況下,請使用現有的庫/框架。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.