2014-08-30 57 views
3

我正在解組JSON中,轉到map[string]interface{}並使用接口的混合字符串,浮點數和切片值來填充PlaceNode結構的字段值。如何在Go中設置動態結構字段?

我需要類似「默認值」的東西,因爲並非所有的JSON對象都具有所有的Struct字段。來自其他語言背景的Structs可編程索引我會習慣於這樣做,在n Placenode變量上設置一個值(例如,如果它是JavaScript中的selfthis關鍵字)。

n[key] = value; 

相反,我有我的PlaceNode結構的方法來讀取interface{},使用reflect和可選分配一個值,如果字段可以設置。我的interfaces{}沒有實現所有的值,所以我有麻煩直接進入我的結構。

顯然沒有一個字段通過這個s.CanSet()檢查。所以我必須要解決這個錯誤。

如何在Go中設置動態結構字段?

func (n PlaceNode) New(data map[string]interface{}) PlaceNode { 
    for key, val := range data { 
     n.Id = key 
     for k, v := range val.(map[string]interface{}) { 
      f := reflect.ValueOf(v) 
      st := reflect.ValueOf(n) 
      if (st.Kind() == reflect.Struct) { 
       s := st.FieldByName(k) 
       if f.Kind() == reflect.String && true == s.CanSet() { 
         s.SetString(f.String()); 
       } else if f.Kind() == reflect.Float64 && true == s.CanSet() { 
         s.SetFloat(f.Float()); 
       } else if f.Kind() == reflect.Slice && true == s.CanSet() { 
         s.Set(f.Slice(0, f.Len())); 
       } 
      } 
     } 
    } 
    return n 
} 

data參數map[string]interface{}有一個接口,這也是一個map[string]interface{},看起來像這樣:

{ 
    "XV.12A": { 
    "Area": 1189.132667, 
    "CensusBlock": 2032, 
    "CensusBlockGroup": 2, 
    "CensusCbsaFips": 40900, 
    "CensusCountyFips": 61, 
    "CensusMcdFips": 90160, 
    "CensusMsaFips": 6922, 
    "CensusPlaceFips": 3204, 
    "CensusStateFips": 6, 
    "CensusTract": 203, 
    "CensusYear": 2010, 
    "Radius": 19.455402434548, 
    "RegionSize": 1189.132667 
    } 
} 

回答

7

當您進行以下電話:

st := reflect.ValueOf(n) 

ValueOf傳遞副本PlaceNode結構。因此,對st所做的任何更改都不會在n中看到。出於這個原因,該包將這種情況視爲不可尋址的值。如果你想有一個reflect.Value是represernts n,請嘗試使用這樣的:

st := reflect.ValueOf(&n).Elem() 

現在stn直接合作,而不是一個副本,並且是可尋址。您現在應該可以在其上及其字段中使用各種Set*方法。

+0

不可尋址的值是我的錯誤。我應該包括它。感謝你的洞察力。 – buley 2014-08-30 01:35:42

相關問題