json解组嵌入结构

json解组嵌入结构,json,go,unmarshalling,Json,Go,Unmarshalling,我想解组结构Outer定义为: type Outer struct { Inner Num int } type Inner struct { Data string } func (i *Inner) UnmarshalJSON(data []byte) error { i.Data = string(data) return nil } 使用json.Unmarshal(数据,&Outer{})似乎只使用internal的UnmarshalJSON

我想解组结构
Outer
定义为:

type Outer struct {
    Inner
    Num int
}

type Inner struct {
    Data string
}
func (i *Inner) UnmarshalJSON(data []byte) error {
    i.Data = string(data)
    return nil
}
使用
json.Unmarshal(数据,&Outer{})
似乎只使用
internal
UnmarshalJSON
并忽略
Num
字段:

在手动设置
Num
字段时,我遇到了一个麻烦,但我想知道是否有人有更干净或更简单的方法来实现这一点


谢谢

发生这种情况是因为
内部
被嵌入到
外部
中。这意味着当json库在
Outer
上调用unmarshaler时,它会在
internal
上调用它

因此,在
func(i*internal)UnmarshalJSON(data[]byte)
内部,
data
参数包含整个json字符串,然后您只对
internal
进行处理

您可以通过在
Outer

Outer struct {
    I Inner // make Inner an explicit field
    Num int `json:"Num"`
}

只需删除示例中的
解组JSON
,因为它用于解组
外部
,因为
内部
是内联的。否则,如果要执行自定义操作,则需要覆盖它


实际上,您不需要显式字段,您需要正确地封送/解封

例如:


一种方法是完全放弃自定义的
UnmarshalJSON
函数,只使用基本的JSON符号,即:

类型外部结构{
内部的
Num int`json:“Num”`
}
类型内部结构{
数据字符串`json:“数据”`
}
使用自定义解组方法可能会丢失一些更细粒度的功能,但是当您使用基本字段(如字符串)解组结构时,您真的不需要担心这一点

如果确实需要自定义解组,可以使用composition,为结构提供一个自定义json编码标记,并让结构包含要使用的字段。因此,如果
数据
包含多个复杂字段,您可以更改
内部
以反映这些字段,如下所示:

类型外部结构{
数据内部`json:“数据”`
Num int`json:“Num”`
}
类型内部结构{
Thing string`json:“Thing”`
OtherThing int`json:“OtherThing”`
}


同样,它没有自定义的解组功能,但是可以很容易地将其拼凑到
内部。(就我个人而言,在任何特定情况下,我都会完全放弃使用自定义解组功能,而只使用编码标签,除非我必须使用解组功能。)

感谢您的解释!当然,这解决了不解压
Num
的问题,但是,它不适用于嵌入式数据,例如
{“data”:“test”,“Num”:1}
,它只适用于
{“inner”:{“data”:“test”},“Num”:1}
,Eric同意。我认为这个答案在这种情况下几乎不适用,但在一般情况下它是误导性的。这是一个误导性的答案。我知道问题本身有点不清楚,但建议的解决方案与嵌入式类型无关。但是
Num
仍然是0,即使它应该是4Hmm,是的,我们可以删除InnerRaw结构和UnmarshallJSON函数。结果:当内部存在
UnmarshalJSON
时,OP想要解析
Num
,它工作得很好。如果我们删除
UnmarshalJSON
,那么它就不会回答这个问题
package main

import (
    "encoding/json"
    "fmt"
)

type Outer struct {
    Inner
    Num int `json:"Num"`
}

type Inner struct{ Data string }

type InnerRaw struct {Data string}

func (i *Inner) UnmarshalJSON(data []byte) error {
    ir:=&InnerRaw{}
    json.Unmarshal(data, ir)
    i.Data = ir.Data
    return nil
}

func main() {
    x := Outer{}
    data := []byte(`{"Num": 4, "Data":"234"}`)
    _ = json.Unmarshal(data, &x)
    fmt.Printf("%+v\n", x)
    js, _:=json.Marshal(x)
    fmt.Printf("JSON:%s", string(js))
}