简体   繁体   English

Avro:在新字段中使用默认值保持向后功能,而无需使用编写器/旧模式

[英]Avro: Keep backwards capability using default value in new field without using writer/old schema

AVRO can handle most common forwards and backwards compatibility. AVRO可以处理最常见的向前和向后兼容性。 But it somehow needs the writer schema when reading the data using a newer schema. 但是在使用较新的架构读取数据时,它某种程度上需要编写者架构。

Saying there is a old schema: 说有一个旧的模式:

{
  "type": "record",
  "name": "com.test.Contact",
  "fields": [
    {
      "name": "address",
      "type": "string"
    }
  ]
}

If using the following new schema to decode bytes that written by old schema, it is needed to have both old and new schema. 如果使用以下新模式解码由旧模式写入的字节,则必须同时具有新模式和旧模式。

{
  "type": "record",
  "name": "com.test.Contact",
  "fields": [
    {
      "name": "address",
      "type": "string"
    },
    {
      "name": "phone",
      "type": ["null", "string"],
      "default": null
    }
  ]
}

The code to read 要读取的代码

    static void sede3() throws IOException {
        System.out.println("----------------------sede3---------------------");
        Schema.Parser parserNew = new Schema.Parser();
        Schema.Parser parserOld = new Schema.Parser();
        Schema addrSchemaNew = parserNew.parse(AppMainCore.class.getClassLoader()
                .getResourceAsStream("compatibility-new.schema.json"));
        Schema addrSchemaOld = parserOld.parse(AppMainCore.class.getClassLoader()
                .getResourceAsStream("compatibility-old.schema.json"));

        GenericRecord addressOld = new GenericData.Record(addrSchemaOld);
        addressOld.put("address", "ABCDEF");
        // Generate bytes using old schema.
        ByteArrayOutputStream bbos = new ByteArrayOutputStream();
        Encoder encoder = EncoderFactory.get().binaryEncoder(bbos, null);
        DatumWriter<GenericRecord> writer = new GenericDatumWriter<>(addrSchemaOld);
        writer.write(addressOld, encoder);
        encoder.flush();
        bbos.close();
        byte[] oldBytes = bbos.toByteArray();
        System.out.println(Hex.encodeHexString(oldBytes) + " is old record bytes");
        // Try to deserialize old bytes using new schema, with old schema's help
        DatumReader<GenericRecord> readerGood = new GenericDatumReader<>(addrSchemaOld, addrSchemaNew);
        Decoder decoderGood = DecoderFactory.get().binaryDecoder(oldBytes, null);
        GenericRecord goodAddress = readerGood.read(null, decoderGood);

        System.out.println(goodAddress + " is record from old bytes using new schema");
    }

What I am trying is deserializing old bytes using new schema, WITHOUT old schema's help. 我正在尝试的是在没有旧模式帮助的情况下使用新模式反序列化旧字节。

like: 喜欢:

DatumReader<GenericRecord> readerGood = new GenericDatumReader<>(addrSchemaNew);

But not 但不是

DatumReader<GenericRecord> readerGood = new GenericDatumReader<>(addrSchemaOld, addrSchemaNew);

Is it supported in Avro? Avro支持吗?

I don't think that's possible, see documentation here: https://avro.apache.org/docs/1.8.2/spec.html#Schema+Resolution . 我认为这是不可能的,请参阅此处的文档: https : //avro.apache.org/docs/1.8.2/spec.html#Schema+Resolution Avro needs both old and new schema to perform the conversion. Avro需要新旧架构来执行转换。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM