goavro и оригинальная структура данных Go

# #go #avro

Вопрос:

Как я могу воссоздать исходную структуру данных в Golang, сериализованную с помощью avro, используя goavro?

С помощью этой библиотеки https://github.com/hamba/avro это довольно просто.

 out := SimpleRecord{}
err = avro.Unmarshal(schema, data, amp;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 имеет интерфейс типа {}, так как я могу «упростить» запись?

Ответ №1:

Это можно сделать двумя способами: либо путем приведения out и выполнения «ручного сопоставления», либо с помощью кодека.Текстуальное изречение. Для полноты изложения оба подхода показаны ниже,

Подход 1

Приведение out от interface{} к map[string]interface{} и извлечение значений

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

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

Подход 2

Используйте 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, amp;out)
    if err != nil {
        log.Fatal(err.Error())
    }

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