当为嵌套结构使用自定义unmarshal时,GoLang结构不会正确解组

问题描述 投票:2回答:1

我们需要为一个嵌套在多个其他结构中的结构使用自定义的unmarshaler,这些结构不需要自定义的unmarshaler。我们有许多类似于下面定义的B结构的结构(类似于嵌套A)。代码的输出是true false 0(预期true false 2)。有任何想法吗?


去游乐场示例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所以它根本没有帮助。

json go struct nested unmarshalling
1个回答
0
投票

由于B嵌入AA.UnmarshalJSON()暴露为B.UnmarshalJSON()。因此,B实施json.Unmarshaler,结果json.Unmarshal()B.UnmarshalJSON()只解组了A的领域。这就是B.Z没有从JSON设置的原因。

这是我能想到的最简单的方法,让它按照你不改变A中数据类型的约束来工作:

  1. 使B嵌入另一个结构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
}
© www.soinside.com 2019 - 2024. All rights reserved.