goavro 和原始 Go 数据结构

标签 go avro

如何使用 goavro 在使用 avro 序列化的 Golang 中重新创建原始数据结构?

有了这个图书馆https://github.com/hamba/avro这很容易。

out := SimpleRecord{}
err = avro.Unmarshal(schema, data, &out)

out 的变量类型是 SimpleRecord。

假设我有这个结构和 avro 模式:

type SimpleRecord struct {
    F1           int      `avro:"f1"`
    F2           string   `avro:"f2"`
    F3           string   `avro:"f3"`
    Dependencies []string `avro:"dependencies"`
}

func main() {
    avro_schema_txt := `{
        "type": "record",
        "name": "AvroData",
        "namespace": "data.avro",
        "doc": "docstring",
        "fields": [
            {
                "name": "f1",
                "type": "int"
            },
            {
                "name": "f2",
                "type": "string"
            },
            {
                "name": "f3",
                "type": "string"
            },
            {
                "name": "dependencies",
                "type": {
                    "type": "array",
                    "items": "string"
                }
            }
        ]
    }`
}

然后

codec, err := goavro.NewCodec(avro_schema_txt)
    if err != nil {
        log.Fatal(err.Error())
    }
    out, _, err := codec.NativeFromBinary(data)
    if err != nil {
        log.Fatal(err.Error())
    }
    fmt.Println(out)

数据是用 avro 编码的,out 是 interface{} 类型的,那么我怎样才能“使”它成为 SimpleRecord?

最佳答案

有两种方法可以做到这一点,一种是强制转换 out 并进行“手动映射”,另一种是使用 codec.TextualFromNative 。为了完整起见,下面显示了这两种方法,

方法一

outinterface{} 转换为 map[string]interface{} 并检索值

...
simpleMap := out.(map[string]interface{})
f1 := simpleMap["f1"]
f2 := simpleMap["f2"] 
...

SimpleRecord {
    F1: f1,
    F2: f2,
    ...
} 

方法二

使用TextualFromNative,下面的代码展示了编码解码的过程

var avro_schema_txt = `{
    "type": "record",
    "name": "AvroData",
    "namespace": "data.avro",
    "doc": "docstring",
    "fields": [
        {
            "name": "f1",
            "type": "int"
        },
        {
            "name": "f2",
            "type": "string"
        },
        {
            "name": "f3",
            "type": "string"
        },
        {
            "name": "dependencies",
            "type": {
                "type": "array",
                "items": "string"
            }
        }
    ]
}`

// added json to match field names in avro
type SimpleRecord struct {
    F1           int      `avro:"f1" json:"f1"`
    F2           string   `avro:"f2" json:"f2"`
    F3           string   `avro:"f3" json:"f3"`
    Dependencies []string `avro:"dependencies" json:"dependencies"`
}

func encodeDecode() {

    data := SimpleRecord{
        F1: 1,
        F2: "tester2",
        F3: "tester3",
        Dependencies: []string { "tester4", "tester5" },
    }

    codec, err := goavro.NewCodec(avro_schema_txt)
    if err != nil {
        log.Fatal(err.Error())
    }

    // encode

    textualIn, err := json2.Marshal(data)
    if err != nil {
        log.Fatal(err.Error())
    }

    nativeIn, _, err := codec.NativeFromTextual(textualIn)
    if err != nil {
        log.Fatal(err.Error())
    }

    binaryIn, err := codec.BinaryFromNative(nil, nativeIn)
    if err != nil {
        log.Fatal(err.Error())
    }

    // decode

    nativeOut, _, err := codec.NativeFromBinary(binaryIn)
    if err != nil {
        log.Fatal(err.Error())
    }

    textualOut, err := codec.TextualFromNative(nil, nativeOut)
    if err != nil {
        log.Fatal(err.Error())
    }

    var out = SimpleRecord{}
    err = json2.Unmarshal(textualOut, &out)
    if err != nil {
        log.Fatal(err.Error())
    }

    if !reflect.DeepEqual(data, out) {
        log.Fatal("should be equal")
    }
}

关于goavro 和原始 Go 数据结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69101669/

相关文章:

json - 解码 JSON 时指向接口(interface)的指针与持有指针的接口(interface)

java - Amazon Hadoop 2.4 + Avro 1.77 : Found interface org. apache.hadoop.mapreduce.TaskAttemptContext,但预期类

java - 从字节反序列化 Avro 数据

avro - AWS 上的架构注册

go - 如何为我的 go 项目制作 go get hook?

parsing - 尝试使用 Golang 在命令行上解析标准输出

单个模式中的多个相同类型的Avro记录

python - Hadoop Streaming破坏了Python生产的Avro

rest - 路由传入请求

go - 无法在终端上运行测试