使用自定义解组嵌套结构时,GoLang结构无法正确解组

时间:2018-09-12 11:24:58

标签: json go struct nested unmarshalling

对于嵌套在多个不需要自定义拆组器的其他结构中的结构,我们需要使用自定义拆组器。我们有很多类似于下面定义的B结构的结构(类似于嵌套A中的结构)。代码的输出为true false 0(预期为true false 2)。有什么想法吗?


转到Playground示例here

package main

import (
    "fmt"
    "encoding/json"
)

type A struct {
    X bool `json:"x"`
    Y bool `json:"y"`
}

type B struct {
    A
    Z int `json:"z"`
}

func (a *A) UnmarshalJSON(bytes []byte) error {
    var aa struct {
        X string `json:"x"`
        Y string `json:"y"`
    }
    json.Unmarshal(bytes, &aa)

    a.X = aa.X == "123"
    a.Y = aa.Y == "abc"
    return nil
}

const myJSON = `{"x": "123", "y": "fff", "z": 2}`

func main() {
    var b B
    json.Unmarshal([]byte(myJSON), &b)
    fmt.Print(b.X," ",b.Y," ",b.Z)
}

编辑:问题被标记为重复的here,但是将A设为显式字段将使我们的API混乱。同样,在将A设为显式字段后,结果为false false 2,因此完全没有帮助。

1 个答案:

答案 0 :(得分:0)

由于B嵌入A,因此A.UnmarshalJSON()被公开为B.UnmarshalJSON()。因此,B实现了json.Unmarshaler,结果json.Unmarshal()调用了B.UnmarshalJSON(),这仅解组了A的字段。这就是未从JSON设置B.Z的原因。

这是我想出的最简单的方法,可以根据您的约束而不更改A中的数据类型:

  1. 使B嵌入另一个结构C,该结构C包含A中未包含的字段。
  2. 为B写一个UnmarshalJSON()方法,该方法将相同的JSON解组到B.A和B.C。使用不在A中的字段定义另一个类型C的好处是,您可以将解组的委托委托给json包。

使用新的B.UnmarshalJSON()方法,您现在也可以完全控制A之外的字段的封送处理。

type A struct {
    X bool `json:"x"`
    Y bool `json:"y"`
}

func (a *A) UnmarshalJSON(bytes []byte) error {
    // the special unmarshalling logic here
}

type C struct {
    Z int `json:"z"`
}

type B struct {
    A
    C
}

func (b *B) UnmarshalJSON(bytes []byte) error {
    if err := json.Unmarshal(bytes, &b.A); err != nil {
        return err
    }
    if err := json.Unmarshal(bytes, &b.C); err != nil {
        return err
    }
    return nil
}
相关问题