将具有嵌入式接口的struct转换为JSON

时间:2017-11-16 17:04:11

标签: go

我有一个我想要编组给JSON的结构。它有一个名为Foo的定义字段(导出为foo)和一个data接口字段,我希望通过该字段传递带有其他JSON字段的动态结构。

但是,当数据字段是接口而不是特定结构时,它永远不会导出为JSON。我怎样才能做到这一点?

package main

import (
    "encoding/json"
    "fmt"
)

type data interface{}

type foo struct {
    Foo string `json:"foo,omitempty"`
    data
}

type bar struct {
    Bar string `json:"bar,omitempty"`
}

func main() {
    b := bar{"bar"}
    f := foo{"foo", b}

    byt, err := json.Marshal(f)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(string(byt))
}

我需要输出看起来像这样(它需要是扁平的,而不是嵌套的):

{"foo": "foo", "bar": "bar"}

3 个答案:

答案 0 :(得分:4)

您可以使用自定义json.Marshaler实现和一些字节切片来完成此操作。

func (f foo) MarshalJSON() ([]byte, error) {
    type goo foo
    g := goo(f)

    b1, err := json.Marshal(g)
    if err != nil {
        return nil, err
    }

    b2, err := json.Marshal(g.data)
    if err != nil {
        return nil, err
    }

    s1 := string(b1[:len(b1)-1])
    s2 := string(b2[1:])

    return []byte(s1 + ", " + s2), nil
}

https://play.golang.org/p/NYTNWIL-xu

请注意,这不是检查字节是否可以实际切片,也不考虑data字段是切片或数组的可能情况,我不确定你是怎么回事无论如何都会想要那么扁平化。

答案 1 :(得分:1)

我会编写一个自定义编组器,如下所示:

func (f foo) MarshalJSON() ([]byte, error) {
    type tmp foo
    g := tmp(f)
    first, err := json.Marshal(g)
    if err != nil {
        return nil, err
    }
    second, err := json.Marshal(f.data)
    if err != nil {
        return nil, err
    }
    data := make(map[string]interface{})
    json.Unmarshal(first, &data)
    json.Unmarshal(second, &data)
    return json.Marshal(data)
    //{"bar":"bar","foo":"foo"}
}

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

答案 2 :(得分:0)

2个选项:

  1. 设置为json.RawMessage类型,因此不会自动解码并保留为接口。 https://golang.org/pkg/encoding/json/#RawMessage

  2. 在结构上编写自定义解组程序。