2017-11-28 17 views
1

マップ内の値に直接移動したいと思います。直接私に「ウォルター」の値を与える必要があり、次に行くのコード例をより具体的にすることができます:(https://play.golang.org/p/tYJsvp39hngolangの文字列パス変数を使用したマップへの移動

type Signature struct{ 
    Name string 
    Signed bool 
}  

path := "Document.Signatures.1.Name" 
map := map[string]interface{}{ 
    "Document": map[string]interface{}{ 
     "Signatures": []interface{}{ 
      Signature{ Name: "Hugo", Signed: false }, 
      Signature{ Name: "Walter", Signed: false }, 
     }, 
     "Otherstuff": "asadwa", 
    }, 
    "AlsoOtherStuff": "adwaw", 
} 

// map.giveMe(path) 
// even better (if possible:) map.change(path,"ToThisNewValue") 

私は解決策で検索しましたが、私は、インターネット上の任意のを見つけることができません。たぶんあなたの誰かがこれを行う方法を知っているか、私のために使用するライブラリを知っています。

ありがとうございました!

+1

あなたはこの答えではパスで指定した要素を取得および設定の例を参照することができます:[、JSON文字列を取るマップにそれをマーシャリング解除、編集、およびバイトにそれをマーシャリングしますもっと複雑に思える](https://stackoverflow.com/questions/28877512/taking-a-json-string-unmarshaling-it-into-a-mapstringinterface-editing-an#28878037)(違いはそれだけですパスは文字列スライスとして与えられますが、概念は同じです)。 – icza

+0

クイック返信ありがとう。私の値を非整列化するためにあらかじめ定義された構造体がある場合。 Selectors(構造体型の場合)とIndex式(マップやスライスの場合)でナビゲートすることは可能ですか?複数のレベルに移動したい場合でも可能ですか?私はあなたが私の質問を理解してくれることを願っています –

+0

しかし、そのためにはリフレクション( 'reflect'パッケージ)が必要です。エクスポートされたフィールドに対してのみ機能します。 – icza

答えて

2

事前定義された構造体がない場合は、かなり多くのリフレクションコールが必要になります。

言われているように、すべての反復でタイプチェックを行い、それに応じてケースを処理してマップを反復することで、それを行うことができます。

// Splitting the path into keys 
keys := strings.Split(path, ".") 

var value interface{} = map1 
for _, key := range keys { 
    if value, err = Get(key, value); err != nil { 
     break 
    } 
} 
if err == nil { 
    fmt.Println("Value:", value) 
} else { 
    fmt.Println("Error:", err) 
} 


func Get(key string, s interface{}) (v interface{}, err error) { 
    var (
     i int64 
     ok bool 
    ) 
    switch s.(type) { 
    case map[string]interface{}: 
     if v, ok = s.(map[string]interface{})[key]; !ok { 
      err = fmt.Errorf("Key not present. [Key:%s]", key) 
     } 
    case []interface{}: 
     if i, err = strconv.ParseInt(key, 10, 64); err == nil { 
      array := s.([]interface{}) 
      if int(i) < len(array) { 
       v = array[i] 
      } else { 
       err = fmt.Errorf("Index out of bounds. [Index:%d] [Array:%v]", i, array) 
      } 
     } 
    case Signature: 
     r := reflect.ValueOf(s) 
     v = reflect.Indirect(r).FieldByName(key) 
    } 
    //fmt.Println("Value:", v, " Key:", key, "Error:", err) 
    return v, err 
} 

Playground code

関連する問題