如何解码json字符串到sync.Map而不是Go1.9中的普通地图?

时间:2017-09-24 13:12:43

标签: json go

我可以使用go语言将json字符串解码为地图:

func main(){
  date := []byte(`{"127.1":{"host":"host1","list":["list123","list456"]},"127.2":{"host":"host2","list":["list223","list256"]}}`)
  var x interface{}
  json.Unmarshal(date, &x)
  t := x.(map[string]interface{})
  var aa []interface{}
  aa = (t["127.2"].(map[string]interface{})["list"])
  for _, v := range aa {
     fmt.Println(v.(string))
  }
}

但我想知道如何将它解码为Go1.9中的sync.Map。我尝试了许多方法但失败了,任何人都可以帮助我吗?

我试过这样:

    func main(){
      date := []byte(`{"127.1":{"host":"host1","list":["list123","list456"]},"127.2":{"host":"host2","list":["list223","list256"]}}`)
      var x interface{}
      json.Unmarshal(date, &x)
      t := x.((sync.Map)[string]interface{})  //compile error
}

我也是这样尝试的:

    func main(){
      date := []byte(`{"127.1":{"host":"host1","list":["list123","list456"]},"127.2":{"host":"host2","list":["list223","list256"]}}`)
      var x sync.Map
      json.Unmarshal(date, &x)
      fmt.Println(x) // but the map has nothing
}

3 个答案:

答案 0 :(得分:5)

您不能直接解组为sync.Map,因为sync.Map没有导出的字段(因此Unmarshaler没有任何方法可以在其中存储数据),并且它没有实现{ {1}}界面。

所以你必须自己处理这个问题,可能是在你自己的类型中包含json.Unmarshaler,并在该类型上实现sync.Map

json.Unmarshaler

答案 1 :(得分:3)

只需向@jakub 添加关于 MarshalJSON 的好答案,您还可以拥有一个不检查类型的通用函数(因为 json 也不在乎)

func MarshalJSON(m *sync.Map) ([]byte, error) {
    tmpMap := make(map[interface{}]interface{})
    m.Range(func(k, v interface{}) bool {
        tmpMap[k] = v
        return true
    })
    return json.Marshal(tmpMap)
}

这可能需要任何类型的 sync.Map 并对其进行编组。

要添加到@Flimzy 的答案中的 UnMarshal 函数,您可以通过省略字符串部分来对类型进行一些处理,使其更通用(双关语,在角落里哭泣):

func UnmarshalJSON(data []byte) (*sync.Map, error) {
    var tmpMap map[interface{}]interface{}
    m := &sync.Map{}

    if err := json.Unmarshal(data, &tmpMap); err != nil {
        return m, err
    }

    for key, value := range tmpMap {
        m.Store(key, value)
    }
    return m, nil
}

一般来说,在进行这种操作时最好使用相同的类型,因为我们很懒惰,不想重写函数;)

答案 2 :(得分:2)

如果你需要一个代码片段来做另一种方式

export const initializeApp = () => {
    return new Promise((resolve, reject) => {

      // an "inner" function that creates a closure over resolve
      // and which does the check if window.AppApi is set
      function checkIfApiLoaded() {
        if (window.AppApi) {
          console.log('App initialized.');
          resolve(true);
        } else {
          console.log('waiting for App to initialize...');

          // if window.AppApi was not set call checkIfApiLoaded with a delay,
          // because of the closure it will still know the 'resolve' function
          setTimeout(checkIfApiLoaded, 250);
        }
      }

      // initially call this inner function
      checkIfApiLoaded()
    });