英文:
Unmarshal into map
问题
如何将数据解组成一个映射(map)?
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{} // 因为映射未初始化,所以需要这样做
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
}
// 这里 results 包含一个 bar 项(正确的),但是 Foos 属性根本不存在
我还尝试将 Foos
更改为 *fooMap
类型,并将解组函数更新为 func (f *fooMap) UnmarshalJSON(...)
,但是解组函数从未被调用。
英文:
How do you unmarshal data into a map?
The JSON is a list of objects and I want to convert this into a map during the unmarshaling. However, it appears that initializing the map creates a new object that isn't returned correctly.
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
}
I've checked to make sure there are no errors and that the map contains the correct values at the end of the Unmarshal function, but when I look at the object that the results should have been unmarshalled into, it is empty. Here is how I'm unmarshaling the parent object which is a slice of structs that contain 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
I also tried changing Foos
to be of type *fooMap
and then updated the unmarshal function to be func (f *fooMap) UnmarshalJSON(...)
but then the unmarshal function is never called.
答案1
得分: 3
这似乎非常复杂,有几个地方让人感到困惑。
- 在UnmarshalJSON过程中,你真的需要中间的fooList吗?这会使JSON表示与你定义的类型不同,这确实让我一开始感到困惑。
- 至少在这里,没有理由为每个东西定义自己的类型,这使得代码非常难以阅读,因为它隐藏了结构在另一层间接性之后。
所以你的问题的关键是fooMap方法没有指针接收器。这使得在方法内部无法将非nil的map赋值给接收器。你确实需要一个指针接收器,在每个索引操作上需要对其进行解引用。在你的代码中,你只是将map数据结构赋值给接收器的临时副本(我可能还要补充一句,这种方式是非有效的)。
func (f *fooMap) UnmarshalJSON(data []byte) error {
*f = make(map[string]*foo) // 需要初始化map
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
英文:
This seems very over-complicated, and there's a couple confusing parts here.
- Do you really need the intermediary fooList during UnmarshalJSON? This makes the json representation look different than the types you define, which definitely confused me at first.
- At least here, there's no reason to be defining your own types for everything, and it's making the code very hard to read, as it hides the structure behind another layer of indirection.
So the crux of your problem is that the fooMap method does not have a pointer receiver. This makes it impossible to assign a non-nil map to the receiver from within your method. You do need a pointer receiver, which you need to dereference on each index operation. In your code you're simply assigning the map data structure to a temporary copy of the receiver (in a non-valid way I might add).
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
}
And with my best guess of your json: http://play.golang.org/p/WbwZJxphTj
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论