一尘不染

在Go中的嵌入式结构上实现json marshaller

go

我有一个想要有效地进行JSON编码的结构:

type MyStruct struct {
    *Meta
    Contents []interface{}
}

type Meta struct {
    Id int
}

该结构包含一个已知形式的元数据和一个未知形式的目录。目录列表在运行时填充,因此我并没有真正的控制权。为了提高Go的编组速度,我想在Meta结构上实现Marshaller接口。Marshaller界面如下所示:

type Marshaler interface {
        MarshalJSON() ([]byte, error)
}

请记住,元结构并不像这里所示的那么简单。我尝试过在Meta结构上实现Marshaler接口,但似乎当我再将JSON编组MyStruct时,结果只是Meta编组接口返回的结果。

所以我的问题是:我如何才能JSON封送一个结构,该结构包含带有自己的JSON编组器和另一个不带JSON的结构的嵌入式结构?


阅读 203

收藏
2020-07-02

共1个答案

一尘不染

由于MarshalJSON匿名字段的方法*Meta将提升为MyStruct,因此在encoding/json将MyStruct编组后,程序包将使用该方法。

您可以做的是,您可以像这样在MyStruct上Meta实现Marshaller接口,而不是让其实现接口:

package main

import (
    "fmt"
    "encoding/json"
    "strconv"
)

type MyStruct struct {
    *Meta
    Contents []interface{}
}

type Meta struct {
    Id int
}

func (m *MyStruct) MarshalJSON() ([]byte, error) {
    // Here you do the marshalling of Meta
    meta := `"Id":` + strconv.Itoa(m.Meta.Id)

    // Manually calling Marshal for Contents
    cont, err := json.Marshal(m.Contents)
    if err != nil {
        return nil, err
    }

    // Stitching it all together
    return []byte(`{` + meta + `,"Contents":` + string(cont) + `}`), nil
}


func main() {
    str := &MyStruct{&Meta{Id:42}, []interface{}{"MyForm", 12}}

    o, err := json.Marshal(str)
    if err != nil {
        panic(err)
    }
    fmt.Println(string(o))
}

{“ Id”:42,“ Contents”:[“ MyForm”,12]}

操场

2020-07-02