json unmarshal嵌入式结构

时间:2016-08-16 18:52:47

标签: 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(data, &Outer{})似乎只能使用Inner的{​​{1}}并忽略UnmarshalJSON字段:https://play.golang.org/p/WUBfzpheMl

我有一个笨拙的solution,我在那里手动设置Num字段,但我想知道是否有人使用更简洁的方法来执行此操作。

谢谢!

5 个答案:

答案 0 :(得分:4)

这种情况正在发生,因为Inner已嵌入Outer。这意味着当json库在Outer上调用unmarshaler时,它最终会在Inner上调用它。

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

您可以通过Inner

中的Outer显式字段来解决此问题
Outer struct {
    I Inner // make Inner an explicit field
    Num int `json:"Num"`
}

Working example

答案 1 :(得分:2)

你不应该需要一个解组功能

https://play.golang.org/p/-HZwX5-rPD

编辑:这是一个更完整的例子

https://play.golang.org/p/oz5kiwy3_K

答案 2 :(得分:0)

只需删除示例中的UnmarshalJSON,因为自Outer内联Inner以来,它已被用于解组。否则,如果要进行自定义操作,则需要覆盖它。

https://play.golang.org/p/D6V6vKpx9J

答案 3 :(得分:0)

实际上您不需要明确的字段,您需要适当的元帅/反元帅

示例:https://play.golang.org/p/mWPM7m44wfK

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))
}

答案 4 :(得分:0)

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

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

type Inner struct {
   Data string `json:"data"`
}

您失去了一些使用自定义解组方法可能具有的更精细的功能,但是当您解组一个主要包含字符串等原始字段的结构时,您真的不需要担心这一点。

Example in go playground

如果你真的需要自定义解组,你可以使用组合,给结构一个自定义的 json 编码标签,让结构包含你想要使用的字段。因此,如果 data 包含多个复杂字段,您可以更改 Inner 以反映这些字段,如下所示:

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

type Inner struct {
    Thing string `json:"thing"`
    OtherThing int `json:"otherThing"`
}

Example in go playground

再说一次,它没有自定义的解组功能,但可以很容易地将其拼凑在一起以获取 Inner。 (就我个人而言,我会在任何给定情况下完全放弃使用自定义解组函数,只使用编码标签,除非我绝对必须使用解组函数。)