解组到地图中

时间:2014-04-02 17:00:11

标签: map go unmarshalling

如何将数据解组到地图中?

JSON是一个对象列表,我想在解编期间将其转换为地图。但是,初始化地图似乎会创建一个未正确返回的新对象。

type foo struct {
    Id string `json:"id"`
    Name string `json:"name"`
}

type fooList []*foo
type fooMap map[string]*foo

func (f fooMap) UnmarshalJSON(data []byte) error {
    f := fooMap{} // required since map is not initialized

    var results fooList
    if err := json.Unmarshal(data, &results); err != nil {
        return err
    }

    for i := 0; i < len(results); i++ {
        result := results[i]
        f[result.Id] = result
    }

    return nil
}

我已经检查过以确保没有错误,并且地图在Unmarshal函数结束时包含正确的值,但是当我查看结果应该被解组的对象时,它是空的。这是我如何解组父对象,这是一个包含fooMaps的结构片段。

type bar struct {
    Foos fooMap `json:"foos"`
}

type bars []*bar

...

var results bars
if err := json.Unmarshal(data, &results); err != nil {
    return err
}

// here results contains a single bar item (which is correct) but the Foos
// property does not exist at all

我还尝试将Foos更改为*fooMap类型,然后将unmarshal函数更新为func (f *fooMap) UnmarshalJSON(...),但从未调用unmarshal函数。

1 个答案:

答案 0 :(得分:1)

这看起来非常复杂,而且这里有一些令人困惑的部分。

  • 在UnmarshalJSON期间你真的需要中介fooList吗?这使得json表示看起来与你定义的类型不同,这一开始肯定让我很困惑。
  • 至少在这里,没有理由为所有内容定义自己的类型,并且它使代码非常难以阅读,因为它隐藏了另一层间接的结构。

所以问题的关键在于fooMap方法没有指针接收器。这使得无法从方法中为接收器分配非零映射。您需要一个指针接收器,您需要在每个索引操作上取消引用。在您的代码中,您只需将地图数据结构分配给接收方的临时副本(以我可能添加的无效方式)。

func (f *fooMap) UnmarshalJSON(data []byte) error {
    *f = make(map[string]*foo) // required since map is not initialized

    var results fooList
    if err := json.Unmarshal(data, &results); err != nil {
        return err
    }

    for i := 0; i < len(results); i++ {
        result := results[i]
        (*f)[result.Id] = result
    }

    return nil
}

我最好猜测你的json:http://play.golang.org/p/WbwZJxphTj