英文:
Unmarshal JSON in JSON in Go
问题
我想要将一个包含 JSON 字符串的字段解析为一个完整的对象。在 Go 语言中,我该如何做呢?
示例:
输入:
{
"foo": 1,
"bar": "{\"a\":\"Hello\"}"
}
Go 类型:
type Child struct {
A string `json:"a"`
}
type Main struct {
Foo int `json:"foo"`
Bar Child `json:"bar"`
}
我猜我需要在其中一个类型上实现一个自定义的 UnmarshalJSON
方法,但是我不确定是在哪个类型上以及如何实现。
英文:
I want to unmarshal a JSON object where one field contains a JSON string into one coherent object. How do I do that in Go?
Example:
Input:
{
"foo":1,
"bar":"{\\"a\\":\\"Hello\\"}"
}
Go type:
type Child struct {
A string `json:"a"`
}
type Main struct {
Foo int `json:"foo"`
Bar Child `json:"bar"`
}
I guess I'd need to implement a custom UnmarshalJSON
implementation on one of the types, but its twisting my head to figure out on which one and how.
答案1
得分: 4
我猜你想把这个JSON字符串当作周围JSON对象的一部分来处理?如果是这样的话,就像你建议的那样,在Child
上使用自定义的UnmarshalJSON
方法应该可以实现这个。
func (c *Child) UnmarshalJSON(p []byte) error {
var jsonString string
if err := json.Unmarshal(p, &jsonString); err != nil {
return err // 表示字符串无效
}
type C Child // 一个没有UnmarshalJSON方法的新类型
return json.Unmarshal([]byte(jsonString), (*C)(c))
}
英文:
I guess you want to treat this as if the JSON String were just part of the surrounding JSON object? If so, then yes, as you suggest, a custom UnmarshalJSON
method on Child
should accomplish this.
func (c *Child) UnmarshalJSON(p []byte) error {
var jsonString string
if err := json.Unmarshal(p, &jsonString); err != nil {
return err // Means the string was invalid
}
type C Child // A new type that doesn't have UnmarshalJSON method
return json.Unmarshal([]byte(jsonString), (*C)(c))
}
答案2
得分: 0
如果我要为该数据创建一个自定义的UnmarshalJson
,我会创建一个辅助结构体auxMain
,它与主结构体具有相同的字段,但Bar
字段为字符串。然后,它将JSON数据解组到这个辅助结构体中,提取Foo
字段和Bar
字段作为字符串。之后,它将Bar
字段作为字符串解组到Child
结构体中,并将提取的Foo
字段和Child
结构体赋给主结构体。
这是一种绕弯的方式,但在Playground中似乎可以工作。
func (m *Main) UnmarshalJSON(b []byte) error {
type auxMain struct {
Foo int `json:"foo"`
Bar string `json:"bar"`
}
var a auxMain
if err := json.Unmarshal(b, &a); err != nil {
return err
}
var child Child
if err := json.Unmarshal([]byte(a.Bar), &child); err != nil {
return err
}
m.Foo = a.Foo
m.Bar = child
return nil
}
在Playground中尝试一下,看看效果:https://go.dev/play/p/wWIceUxu1tj
不知道这是否符合你的要求。
英文:
if i were to create a custom UnmarshalJson
for that data, I would create an auxiliary struct auxMain
that has the same fields as the main struct but with Bar
field as string. Then it unmarshals the JSON data into this auxiliary struct, extracting the Foo
field and the Bar
field as a string. After that, it unmarshals the Bar field as string into the Child
struct, and assigns the extracted Foo field and the Child struct to the Main struct.
It's a round about way but seems to work in the playground.
func (m *Main) UnmarshalJSON(b []byte) error {
type auxMain struct {
Foo int `json:"foo"`
Bar string `json:"bar"`
}
var a auxMain
if err := json.Unmarshal(b, &a); err != nil {
return err
}
var child Child
if err := json.Unmarshal([]byte(a.Bar), &child); err != nil {
return err
}
m.Foo = a.Foo
m.Bar = child
return nil
}
try it out in the PlayGround and see: https://go.dev/play/p/wWIceUxu1tj
Don't know if this is what you are looking for.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论