英文:
How to unmarshal two json values into same variable?
问题
我经常遇到具有相同结构但不同名称的 JSON 数据。如何将它们都分配给同一个结构体?例如:
{
"e":"g",
"a":[
{
"b":"b1",
"c":"c1"
}
]
}
和
{
"e":"f",
"d":[
{
"b":"b1",
"c":"c1"
}
]
}
这两个 JSON 数据具有相同的内部结构,但无法解析为相同的 Golang 结构体。
英文:
I frequently come across json that have same structure but different name. How is it possible to assign all of them in same struct. for example
{
"e":"g"
"a":[
{
"b":"b1",
"c":"c1"
}
]
}
and
{
"e":"f"
"d":[
{
"b":"b1",
"c":"c1"
}
]
}
have same internal structure but could not be unmarsheled into same golang struct.
答案1
得分: 1
使用结构标签来解码JSON是为了最常见的用例。对于自定义行为,请实现Unmarshaler
接口(https://play.golang.org/p/rCpCDvWXGP):
type InnerStruct struct {
B, C string
}
type OuterStruct struct {
E string
A []InnerStruct
}
func (o *OuterStruct) UnmarshalJSON(bs []byte) error {
var intermediate map[string]json.RawMessage
err := json.Unmarshal(bs, &intermediate)
if err != nil {
return err
}
// e is just e
e, ok := intermediate["e"]
if !ok {
return fmt.Errorf("invalid json, expected `e`")
}
err = json.Unmarshal(e, &o.E)
if err != nil {
return err
}
// a is a or d
a, ok := intermediate["a"]
if !ok {
a, ok = intermediate["d"]
}
if !ok {
return fmt.Errorf("invalid json, expected `a` or `d`")
}
err = json.Unmarshal(a, &o.A)
if err != nil {
return err
}
return nil
}
在这个例子中,我使用了一个中间映射,并延迟处理内部值以匹配a
或d
。我确定这不是你要处理的实际数据,但希望这足以让你开始。
英文:
Using struct tags for decoding json is intended for the most common use cases. For custom behavior implement the Unmarshaler
interface (https://play.golang.org/p/rCpCDvWXGP):
type InnerStruct struct {
B, C string
}
type OuterStruct struct {
E string
A []InnerStruct
}
func (o *OuterStruct) UnmarshalJSON(bs []byte) error {
var intermediate map[string]json.RawMessage
err := json.Unmarshal(bs, &intermediate)
if err != nil {
return err
}
// e is just e
e, ok := intermediate["e"]
if !ok {
return fmt.Errorf("invalid json, expected `e`")
}
err = json.Unmarshal(e, &o.E)
if err != nil {
return err
}
// a is a or d
a, ok := intermediate["a"]
if !ok {
a, ok = intermediate["d"]
}
if !ok {
return fmt.Errorf("invalid json, expected `a` or `d`")
}
err = json.Unmarshal(a, &o.A)
if err != nil {
return err
}
return nil
}
In this case I used an intermediate map and delayed the processing of the inner values to match a
or d
. I'm sure this wasn't the actual data you had to work with, but hopefully it's enough to get you started.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论