JSON的编组和解组结构会丢失信息

时间:2018-07-23 14:09:52

标签: json go

我正在尝试将一个结构编组为json(按预期工作)并再次直接将其编组,但是好像信息丢失了。

这可能是我的应用程序中的一个设计缺陷,但是作为我的新手,我并不了解。帮助表示赞赏。

package main

import (
    "encoding/json"
    "fmt"
)

type Flow interface {
    Exec(input map[string]string) (output map[string]string, err error)
}

type FlowData struct {
    Static map[string]string
    Output map[string]string
}

type FooFlow struct {
    Data FlowData
}

func (flow FooFlow) Exec(input map[string]string) (output map[string]string, err error) {
    output = map[string]string{"message": flow.Data.Static["message"]}
    return output, nil
}

type BarFlow struct {
    Data FlowData
}

func (flow BarFlow) Exec(input map[string]string) (output map[string]string, err error) {
    output = map[string]string{"message": flow.Data.Static["prefix"] + "_bar"}
    return output, nil
}

type Pipeline struct {
    Entrypoint string
    Flows      map[string]Flow
}

func main() {
    foo := FooFlow{
        Data: FlowData{
            Static: map[string]string{"message": "foo"},
        },
    }

    bar := BarFlow{
        Data: FlowData{
            Static: map[string]string{"prefix:": "baz"},
        },
    }

    pipe := Pipeline{
        Entrypoint: "foobar",
        Flows: map[string]Flow{
            "foo": foo,
            "bar": bar,
        },
    }

    data, _ := json.Marshal(pipe)
    fmt.Printf("pipe1: %+v\n", pipe)
    fmt.Println("json:", string(data))

    var pipe2 Pipeline
    json.Unmarshal(data, &pipe2)
    fmt.Printf("pipe2: %+v\n", pipe2)
}

执行此操作将得到以下结果:

pipe1: {Entrypoint:foobar Flows:map[foo:{Data:{Static:map[message:foo] Output:map[]}} bar:{Data:{Static:map[prefix::baz] Output:map[]}}]}

json: {"Entrypoint":"foobar","Flows":{"bar":{"Data":{"Static":{"prefix:":"baz"},"Output":null}},"foo":{"Data":{"Static":{"message":"foo"},"Output":null}}}}

pipe2: {Entrypoint:foobar Flows:map[bar:<nil> foo:<nil>]}

显然所有信息都正确地编组到json中。但是,解组忽略了Flow的实际值,只是将它们以<nil>的形式添加到地图中。

如何正确解决此问题?

1 个答案:

答案 0 :(得分:1)

当struct字段是接口类型时,encoding/json无法知道要用于解编的具体类型,因此它会跳过它。要么在定义中使用具体类型,要么在接口字段中填充可以解组的空具体实例。