2017-07-01 9 views
2

未定義数のunknowキー値を使用してJSONから文字列のマップを作成しようとしています。 、JSONからの文字列のマップを作成します。

config := map[string]string{ 
    "localhost-tag":  "dev_latest", 
    "localhost-vhost": "localhost.com, 
    "development-tag": "dev_latest, 
    ... 
} 

は、既知の値を持つ"github.com/jmoiron/jsonq"でJSONを解析するために、非常に簡単です:

{ 
     "localhost": 
     { 
       "tag": "dev_latest", 
       "vhost": "localhost.com" 
     }, 
     "development": 
     { 
       "tag": "dev_latest", 
       "vhost": "dev.com" 
     } 
} 

私はこのような値でmap[string]stringを作成したい:

はここに私の例のJSONファイルでありますこの場合、localhostは何でもかまいません。tagは他のものでもかまいません。

私の囲碁コードで私のエントリポイントは、このようなものです:

func ParseJson(){ 
    configPath := GetConfigPath() 
    b, err := ioutil.ReadFile(configPath) 

    // Here, I need to create my map of strings.. 

    return configKeyStr 

} 

すべてのヘルプは本当に感謝します。

ありがとうございます!

答えて

2

簡単に行うことができます。単に変換する。

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

UPDATE

は、あなたがこれを自動的に持つことはできませんが、あなたは「内部」のマップ範囲に及ぶことができ、かつ外側を組み合わせ

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)) 
} 
+0

どうもありがとう、それは動作しますが、それは は、どのように私はこのようなマップを持つことができ、私が欲しいものを正確ではありません。 はhttps://pastebin.com/6EJX01D6 –

+0

'mm'があなたの期待されていますか? – mattn

+1

マップ*を平坦化したい、つまり、JSONキーが区切り文字として " - "で再帰的に*結合されたものと思っています。 – putu

1

(多分お守りとして動作します)平らに書きました単純な文字列連結(+演算子)を使用して内部キーを持つキー。タイプアサーションを使用する必要がないように、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] 
+0

ありがとう、それは完璧です! –

0

質問にあなたは未知のキー値の未定義の数を言及しているので、あなたは可能入れ子レベルが不明で、値がstring以外のJSONドキュメントを処理する必要があります。この場合、Unmarshal jsonからmap[string]interface{}に移動し、再帰を使用してフラットマップにする必要があります。 mattnで指摘したように、あなたが設定値をライトバックしたい場合、あなたは問題がある可能性がありhttps://play.golang.org/p/9SQsbAUFdY

でmattnの答えから適応

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

作業溶液:JSON文書がmap[string]interface{}にunmrashaledたら、次の関数を使用します。その場合は、既存のライブラリ/フレームワークを使用してください。

関連する問題