英文:
Nested properties for structs with unknown property names?
问题
我正在使用JSON从外部源获取一些值,并将其放入变量中。
我有一个像这样的类型,json.Unmarshal
将值放入其中:
type Frame struct {
Type string
Value map[string]interface{}
}
var data Frame
解码后,我可以通过data.Type
访问类型
但是,如果我尝试这样做:
if data.Type == "image" {
fmt.Printf("%s\n", data.Value.Imagedata)
}
编译器会报错,说没有data.Value.Imagedata
这样的值。
所以我的问题是,如何在Go中引用我知道根据某些条件将存在的属性?
这样做是可以的:
type Image struct {
Filename string
}
type Frame struct {
Type string
Value map[string]interface{}
}
但是这并不是很灵活,因为我将会接收到不同的Value
。
英文:
I'm using JSON to get some values into a variable from an external source.
I have a type like this that json.Unmarshal
puts values into:
type Frame struct {
Type string
Value map[string]interface{}
}
var data Frame
After unmarshal, I can access a the type by: data.Type
but if I try doing something like:
if data.Type == "image" {
fmt.Printf("%s\n", data.Value.Imagedata)
}
The compiler complains about no such value data.Value.Imagedata
.
So my question is, how do I reference properties in Go that I know will be there depending on some condition?
Doing this works:
type Image struct {
Filename string
}
type Frame struct {
Type string
Value map[string]interface{}
}
But that isn't very flexible as I will be receiving different Value
s.
答案1
得分: 15
json.Unmarshal
将尽力将数据放置在与您的类型最匹配的位置。从技术上讲,您的第一个示例将起作用,但是您正在尝试使用点表示法访问Value
字段,即使您声明它是一个映射:
这应该给您一些输出形式:
if data.Type == 'image'{
fmt.Printf("%v\n", data.Value["Imagedata"])
}
...假设"Imagedata"是JSON中的一个键。
您可以选择根据您希望的结构的深度来定义类型,或者使用interface{}
,然后对值进行类型断言。由于Value
字段是一个映射,您总是可以像Value[key]
这样访问键,并且该映射条目的值是一个interface{}
,您可以像Value[key].(float64)
这样进行类型断言。
至于更明确的结构,我发现您可以将对象分解为它们自己的类型,或者在一个地方嵌套定义它:
嵌套(使用匿名结构)
type Frame struct {
Type string
Value struct {
Imagedata string `json:"image_data"`
}
}
单独的结构
type Frame struct {
Type string
Value value
}
type value struct {
Imagedata string `json:"image_data"`
}
我自己还在学习Go,所以这是我目前理解的范围。
英文:
json.Unmarshal
will do its best to place the data where it best aligns with your type. Technically your first example will work, but you are trying to access the Value
field with dot notation, even though you declared it to be a map:
This should give you some form of output:
if data.Type == 'image'{
fmt.Printf("%v\n", data.Value["Imagedata"])
}
… considering that "Imagedata" was a key in the JSON.
You have the option of defining the type as deeply as you want or expect the structure to be, or using an interface{}
and then doing type assertions on the values. With the Value
field being a map, you would always access the keys like Value[key]
, and the value of that map entry is an interface{}
which you could type assert like Value[key].(float64)
.
As for doing more explicit structures, I have found that you could either break up the objects into their own types, or define it nested in one place:
Nested (with anonymous struct)
type Frame struct {
Type string
Value struct {
Imagedata string `json:"image_data"`
}
}
Seperate structs
type Frame struct {
Type string
Value value
}
type value struct {
Imagedata string `json:"image_data"`
}
I'm still learning Go myself, so this the extent of my current understanding :-).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论