Avro无法在字段中反序列化具有逻辑类型的联合 [英] Avro is not able to deserialize Union with Logical Types in fields

查看:93
本文介绍了Avro无法在字段中反序列化具有逻辑类型的联合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Avro工具版本-1.9.2

这是我在反序列化Avro数据时面临的问题.字段为具有空值和逻辑类型的Union时,似乎Avro无法生成正确的POJO类.

This is the problem that I am facing while deserializing Avro data. Looks like Avro is not able to generate correct POJO class when field is Union with nulls and logical types.

当前行为:当Avro架构的字段为null和逻辑类型的并集时.Avro不添加转换类型数组,因此我们得到类强制转换异常.这是original.avsc

Current Behavior: When avro schema has a fields that is union of null and logical type. Avro do not add conversion type array thus we get class cast exceptions. This is the problem with original.avsc

预期的行为:Avro应该能够序列化具有空值的逻辑类型.

Expected behavior: Avro should be able to serialize logical types having nulls.

看看下面的original.avsc,没有为任何字段创建 conversions 数组.由于原始字段数据为原始类型,而POJO字段基于逻辑类型,因此会导致 ClassCastException .

Take a look at the below original.avsc, There are no conversions array created for any of the fields. Which results in ClassCastException since original field data is in primitive type and POJO field is based on logical type.

original.avsc

{
    "type": "record",
    "name": "UserRecord",
    "namespace": "com.original",
    "fields": [
        {
            "name": "user",
            "type": {
                "type": "record",
                "name": "User",
                "fields": [
                    {
                        "name": "KEY_NBR",
                        "type": [
                            "null",
                            "string"
                        ],
                        "default": null
                    },
                    {
                        "name": "CRTE_TMS",
                        "type": [
                            "null",
                            {
                                "type": "long",
                                "logicalType": "timestamp-micros"
                            }
                        ],
                        "default": null
                    },
                    {
                        "name": "BIRTH_DT",
                        "type": [
                            "null",
                            {
                                "type": "int",
                                "logicalType": "date"
                            }
                        ],
                        "default": null
                    },
                    {
                        "name": "BAL_AMT",
                        "type": [
                            "null",
                            {
                                "type": "bytes",
                                "precision": 7,
                                "scale": 2,
                                "logicalType": "decimal"
                            }
                        ],
                        "default": null
                    }
                ]
            }
        },
        {
            "name": "beforeUser",
            "type": [
                "null",
                "User"
            ],
            "default": null
        }
    ]
}

基于Original.avsc的POJO



package com.original;

import org.apache.avro.generic.GenericArray;
import org.apache.avro.specific.SpecificData;
import org.apache.avro.util.Utf8;
import org.apache.avro.message.BinaryMessageEncoder;
import org.apache.avro.message.BinaryMessageDecoder;
import org.apache.avro.message.SchemaStore;

@org.apache.avro.specific.AvroGenerated
public class User extends org.apache.avro.specific.SpecificRecordBase implements org.apache.avro.specific.SpecificRecord {
  private static final long serialVersionUID = 4336376255546547414L;
  public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"com.original\",\"fields\":[{\"name\":\"KEY_NBR\",\"type\":[\"null\",\"string\"],\"default\":null},{\"name\":\"CRTE_TMS\",\"type\":[\"null\",{\"type\":\"long\",\"logicalType\":\"timestamp-micros\"}],\"default\":null},{\"name\":\"BIRTH_DT\",\"type\":[\"null\",{\"type\":\"int\",\"logicalType\":\"date\"}],\"default\":null},{\"name\":\"BAL_AMT\",\"type\":[\"null\",{\"type\":\"bytes\",\"precision\":7,\"scale\":2,\"logicalType\":\"decimal\"}],\"default\":null}]}");
  public static org.apache.avro.Schema getClassSchema() { return SCHEMA$; }

  private static SpecificData MODEL$ = new SpecificData();
static {
    MODEL$.addLogicalTypeConversion(new org.apache.avro.data.TimeConversions.DateConversion());
    MODEL$.addLogicalTypeConversion(new org.apache.avro.data.TimeConversions.TimestampMillisConversion());
  }

  private static final BinaryMessageEncoder<User> ENCODER =
      new BinaryMessageEncoder<User>(MODEL$, SCHEMA$);

  private static final BinaryMessageDecoder<User> DECODER =
      new BinaryMessageDecoder<User>(MODEL$, SCHEMA$);


  public static BinaryMessageEncoder<User> getEncoder() {
    return ENCODER;
  }


  public static BinaryMessageDecoder<User> getDecoder() {
    return DECODER;
  }

 
  public static BinaryMessageDecoder<User> createDecoder(SchemaStore resolver) {
    return new BinaryMessageDecoder<User>(MODEL$, SCHEMA$, resolver);
  }

  
  public java.nio.ByteBuffer toByteBuffer() throws java.io.IOException {
    return ENCODER.encode(this);
  }

 
  public static User fromByteBuffer(
      java.nio.ByteBuffer b) throws java.io.IOException {
    return DECODER.decode(b);
  }

   private java.lang.CharSequence KEY_NBR;
   private java.time.Instant CRTE_TMS;
   private java.time.LocalDate BIRTH_DT;
   private java.nio.ByteBuffer BAL_AMT;

 
  public User() {}

  
  public User(java.lang.CharSequence KEY_NBR, java.time.Instant CRTE_TMS, java.time.LocalDate BIRTH_DT, java.nio.ByteBuffer BAL_AMT) {
    this.KEY_NBR = KEY_NBR;
    this.CRTE_TMS = CRTE_TMS;
    this.BIRTH_DT = BIRTH_DT;
    this.BAL_AMT = BAL_AMT;
  }

  public org.apache.avro.specific.SpecificData getSpecificData() { return MODEL$; }
  public org.apache.avro.Schema getSchema() { return SCHEMA$; }
  // Used by DatumWriter.  Applications should not call.
  public java.lang.Object get(int field$) {
    switch (field$) {
    case 0: return KEY_NBR;
    case 1: return CRTE_TMS;
    case 2: return BIRTH_DT;
    case 3: return BAL_AMT;
    default: throw new org.apache.avro.AvroRuntimeException("Bad index");
    }
  }

  // Used by DatumReader.  Applications should not call.
  @SuppressWarnings(value="unchecked")
  public void put(int field$, java.lang.Object value$) {
    switch (field$) {
    case 0: KEY_NBR = (java.lang.CharSequence)value$; break;
    case 1: CRTE_TMS = (java.time.Instant)value$; break;
    case 2: BIRTH_DT = (java.time.LocalDate)value$; break;
    case 3: BAL_AMT = (java.nio.ByteBuffer)value$; break;
    default: throw new org.apache.avro.AvroRuntimeException("Bad index");
    }
  }

 
  public java.lang.CharSequence getKEYNBR() {
    return KEY_NBR;
  }


  /**
   * Sets the value of the 'KEY_NBR' field.
   * @param value the value to set.
   */
  public void setKEYNBR(java.lang.CharSequence value) {
    this.KEY_NBR = value;
  }

  
  public java.time.Instant getCRTETMS() {
    return CRTE_TMS;
  }


  /**
   * Sets the value of the 'CRTE_TMS' field.
   * @param value the value to set.
   */
  public void setCRTETMS(java.time.Instant value) {
    this.CRTE_TMS = value;
  }

  /**
   * Gets the value of the 'BIRTH_DT' field.
   * @return The value of the 'BIRTH_DT' field.
   */
  public java.time.LocalDate getBIRTHDT() {
    return BIRTH_DT;
  }


  public void setBIRTHDT(java.time.LocalDate value) {
    this.BIRTH_DT = value;
  }

  /**
   * Gets the value of the 'BAL_AMT' field.
   * @return The value of the 'BAL_AMT' field.
   */
  public java.nio.ByteBuffer getBALAMT() {
    return BAL_AMT;
  }


  /**
   * Sets the value of the 'BAL_AMT' field.
   * @param value the value to set.
   */
  public void setBALAMT(java.nio.ByteBuffer value) {
    this.BAL_AMT = value;
  }

  /**
   * Creates a new User RecordBuilder.
   * @return A new User RecordBuilder
   */
  public static com.original.User.Builder newBuilder() {
    return new com.original.User.Builder();
  }

 
  public static com.original.User.Builder newBuilder(com.original.User.Builder other) {
    if (other == null) {
      return new com.original.User.Builder();
    } else {
      return new com.original.User.Builder(other);
    }
  }


  public static com.original.User.Builder newBuilder(com.original.User other) {
    if (other == null) {
      return new com.original.User.Builder();
    } else {
      return new com.original.User.Builder(other);
    }
  }

  
  @org.apache.avro.specific.AvroGenerated
  public static class Builder extends org.apache.avro.specific.SpecificRecordBuilderBase<User>
    implements org.apache.avro.data.RecordBuilder<User> {

    private java.lang.CharSequence KEY_NBR;
    private java.time.Instant CRTE_TMS;
    private java.time.LocalDate BIRTH_DT;
    private java.nio.ByteBuffer BAL_AMT;

   
    private Builder() {
      super(SCHEMA$);
    }

    private Builder(com.original.User.Builder other) {
      super(other);
      if (isValidValue(fields()[0], other.KEY_NBR)) {
        this.KEY_NBR = data().deepCopy(fields()[0].schema(), other.KEY_NBR);
        fieldSetFlags()[0] = other.fieldSetFlags()[0];
      }
      if (isValidValue(fields()[1], other.CRTE_TMS)) {
        this.CRTE_TMS = data().deepCopy(fields()[1].schema(), other.CRTE_TMS);
        fieldSetFlags()[1] = other.fieldSetFlags()[1];
      }
      if (isValidValue(fields()[2], other.BIRTH_DT)) {
        this.BIRTH_DT = data().deepCopy(fields()[2].schema(), other.BIRTH_DT);
        fieldSetFlags()[2] = other.fieldSetFlags()[2];
      }
      if (isValidValue(fields()[3], other.BAL_AMT)) {
        this.BAL_AMT = data().deepCopy(fields()[3].schema(), other.BAL_AMT);
        fieldSetFlags()[3] = other.fieldSetFlags()[3];
      }
    }

    private Builder(com.original.User other) {
      super(SCHEMA$);
      if (isValidValue(fields()[0], other.KEY_NBR)) {
        this.KEY_NBR = data().deepCopy(fields()[0].schema(), other.KEY_NBR);
        fieldSetFlags()[0] = true;
      }
      if (isValidValue(fields()[1], other.CRTE_TMS)) {
        this.CRTE_TMS = data().deepCopy(fields()[1].schema(), other.CRTE_TMS);
        fieldSetFlags()[1] = true;
      }
      if (isValidValue(fields()[2], other.BIRTH_DT)) {
        this.BIRTH_DT = data().deepCopy(fields()[2].schema(), other.BIRTH_DT);
        fieldSetFlags()[2] = true;
      }
      if (isValidValue(fields()[3], other.BAL_AMT)) {
        this.BAL_AMT = data().deepCopy(fields()[3].schema(), other.BAL_AMT);
        fieldSetFlags()[3] = true;
      }
    }

    public java.lang.CharSequence getKEYNBR() {
      return KEY_NBR;
    }

    public com.original.User.Builder setKEYNBR(java.lang.CharSequence value) {
      validate(fields()[0], value);
      this.KEY_NBR = value;
      fieldSetFlags()[0] = true;
      return this;
    }

    public boolean hasKEYNBR() {
      return fieldSetFlags()[0];
    }


    public com.original.User.Builder clearKEYNBR() {
      KEY_NBR = null;
      fieldSetFlags()[0] = false;
      return this;
    }

    /**
      * Gets the value of the 'CRTE_TMS' field.
      * @return The value.
      */
    public java.time.Instant getCRTETMS() {
      return CRTE_TMS;
    }


    public com.original.User.Builder setCRTETMS(java.time.Instant value) {
      validate(fields()[1], value);
      this.CRTE_TMS = value;
      fieldSetFlags()[1] = true;
      return this;
    }

    /**
      * Checks whether the 'CRTE_TMS' field has been set.
      * @return True if the 'CRTE_TMS' field has been set, false otherwise.
      */
    public boolean hasCRTETMS() {
      return fieldSetFlags()[1];
    }


    public com.original.User.Builder clearCRTETMS() {
      CRTE_TMS = null;
      fieldSetFlags()[1] = false;
      return this;
    }

  
    public java.time.LocalDate getBIRTHDT() {
      return BIRTH_DT;
    }

    public com.original.User.Builder setBIRTHDT(java.time.LocalDate value) {
      validate(fields()[2], value);
      this.BIRTH_DT = value;
      fieldSetFlags()[2] = true;
      return this;
  
    public boolean hasBIRTHDT() {
      return fieldSetFlags()[2];
    }


    /**
      * Clears the value of the 'BIRTH_DT' field.
      * @return This builder.
      */
    public com.original.User.Builder clearBIRTHDT() {
      BIRTH_DT = null;
      fieldSetFlags()[2] = false;
      return this;
    }

    /**
      * Gets the value of the 'BAL_AMT' field.
      * @return The value.
      */
    public java.nio.ByteBuffer getBALAMT() {
      return BAL_AMT;
    }


    public com.original.User.Builder setBALAMT(java.nio.ByteBuffer value) {
      validate(fields()[3], value);
      this.BAL_AMT = value;
      fieldSetFlags()[3] = true;
      return this;
    }

    /**
      * Checks whether the 'BAL_AMT' field has been set.
      * @return True if the 'BAL_AMT' field has been set, false otherwise.
      */
    public boolean hasBALAMT() {
      return fieldSetFlags()[3];
    }


    public com.original.User.Builder clearBALAMT() {
      BAL_AMT = null;
      fieldSetFlags()[3] = false;
      return this;
    }

    @Override
    @SuppressWarnings("unchecked")
    public User build() {
      try {
        User record = new User();
        record.KEY_NBR = fieldSetFlags()[0] ? this.KEY_NBR : (java.lang.CharSequence) defaultValue(fields()[0]);
        record.CRTE_TMS = fieldSetFlags()[1] ? this.CRTE_TMS : (java.time.Instant) defaultValue(fields()[1]);
        record.BIRTH_DT = fieldSetFlags()[2] ? this.BIRTH_DT : (java.time.LocalDate) defaultValue(fields()[2]);
        record.BAL_AMT = fieldSetFlags()[3] ? this.BAL_AMT : (java.nio.ByteBuffer) defaultValue(fields()[3]);
        return record;
      } catch (org.apache.avro.AvroMissingFieldException e) {
        throw e;
      } catch (java.lang.Exception e) {
        throw new org.apache.avro.AvroRuntimeException(e);
      }
    }
  }

  @SuppressWarnings("unchecked")
  private static final org.apache.avro.io.DatumWriter<User>
    WRITER$ = (org.apache.avro.io.DatumWriter<User>)MODEL$.createDatumWriter(SCHEMA$);

  @Override public void writeExternal(java.io.ObjectOutput out)
    throws java.io.IOException {
    WRITER$.write(this, SpecificData.getEncoder(out));
  }

  @SuppressWarnings("unchecked")
  private static final org.apache.avro.io.DatumReader<User>
    READER$ = (org.apache.avro.io.DatumReader<User>)MODEL$.createDatumReader(SCHEMA$);

  @Override public void readExternal(java.io.ObjectInput in)
    throws java.io.IOException {
    READER$.read(this, SpecificData.getDecoder(in));
  }
}

如果我修改了原始模式并从逻辑类型字段中取出空值.Avro会为逻辑类型字段生成正确的转换(选中突出显示的部分),并且我能够成功将avro消息反序列化为POJO.

Whereas, If I modify the original schema and take out null values from logical type fields. Avro generates proper conversions (check highlighted part) for the logical type fields and I am able to successfully deserialize the avro message to POJO.

modified.avsc

{
    "type": "record",
    "name": "UserRecord",
    "namespace": "com.modified",
    "fields": [
        {
            "name": "user",
            "type": {
                "type": "record",
                "name": "User",
                "fields": [
                    {
                        "name": "KEY_NBR",
                        "type": [
                            "null",
                            "string"
                        ],
                        "default": null
                    },
                    {
                        "name": "CRTE_TMS",
                        "type":
                            {
                                "type": "long",
                                "logicalType": "timestamp-micros"
                            },
                        "default": 1
                    },
                    {
                        "name": "BIRTH_DT",
                        "type":
                            {
                                "type": "int",
                                "logicalType": "date"
                            },
                        "default": 1
                    },
                    {
                        "name": "BAL_AMT",
                        "type":
                            {
                                "type": "bytes",
                                "precision": 7,
                                "scale": 2,
                                "logicalType": "decimal"
                            }
                    }
                ]
            }
        },
        {
            "name": "beforeUser",
            "type": [
                "null",
                "User"
            ],
            "default": null
        }
    ]
}

通过修改后的模式生成的POJO类


package com.modified;

import org.apache.avro.generic.GenericArray;
import org.apache.avro.specific.SpecificData;
import org.apache.avro.util.Utf8;
import org.apache.avro.message.BinaryMessageEncoder;
import org.apache.avro.message.BinaryMessageDecoder;
import org.apache.avro.message.SchemaStore;

@org.apache.avro.specific.AvroGenerated
public class User extends org.apache.avro.specific.SpecificRecordBase implements org.apache.avro.specific.SpecificRecord {
  private static final long serialVersionUID = -2671150121474031299L;
  public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"User\",\"namespace\":\"com.modified\",\"fields\":[{\"name\":\"KEY_NBR\",\"type\":[\"null\",\"string\"],\"default\":null},{\"name\":\"CRTE_TMS\",\"type\":{\"type\":\"long\",\"logicalType\":\"timestamp-micros\"},\"default\":1},{\"name\":\"BIRTH_DT\",\"type\":{\"type\":\"int\",\"logicalType\":\"date\"},\"default\":1},{\"name\":\"BAL_AMT\",\"type\":{\"type\":\"bytes\",\"precision\":7,\"scale\":2,\"logicalType\":\"decimal\"}}]}");
  public static org.apache.avro.Schema getClassSchema() { return SCHEMA$; }

  private static SpecificData MODEL$ = new SpecificData();
static {
    MODEL$.addLogicalTypeConversion(new org.apache.avro.data.TimeConversions.DateConversion());
    MODEL$.addLogicalTypeConversion(new org.apache.avro.data.TimeConversions.TimestampMillisConversion());
  }

  private static final BinaryMessageEncoder<User> ENCODER =
      new BinaryMessageEncoder<User>(MODEL$, SCHEMA$);

  private static final BinaryMessageDecoder<User> DECODER =
      new BinaryMessageDecoder<User>(MODEL$, SCHEMA$);

  public static BinaryMessageEncoder<User> getEncoder() {
    return ENCODER;
  }

  public static BinaryMessageDecoder<User> getDecoder() {
    return DECODER;
  }

 
  public static BinaryMessageDecoder<User> createDecoder(SchemaStore resolver) {
    return new BinaryMessageDecoder<User>(MODEL$, SCHEMA$, resolver);
  }

 
  public java.nio.ByteBuffer toByteBuffer() throws java.io.IOException {
    return ENCODER.encode(this);
  }

 
  public static User fromByteBuffer(
      java.nio.ByteBuffer b) throws java.io.IOException {
    return DECODER.decode(b);
  }

   private java.lang.CharSequence KEY_NBR;
   private java.time.Instant CRTE_TMS;
   private java.time.LocalDate BIRTH_DT;
   private java.nio.ByteBuffer BAL_AMT;

  public User() {}

 
  public User(java.lang.CharSequence KEY_NBR, java.time.Instant CRTE_TMS, java.time.LocalDate BIRTH_DT, java.nio.ByteBuffer BAL_AMT) {
    this.KEY_NBR = KEY_NBR;
    this.CRTE_TMS = CRTE_TMS.truncatedTo(java.time.temporal.ChronoUnit.MICROS);
    this.BIRTH_DT = BIRTH_DT;
    this.BAL_AMT = BAL_AMT;
  }

  public org.apache.avro.specific.SpecificData getSpecificData() { return MODEL$; }
  public org.apache.avro.Schema getSchema() { return SCHEMA$; }
  // Used by DatumWriter.  Applications should not call.
  public java.lang.Object get(int field$) {
    switch (field$) {
    case 0: return KEY_NBR;
    case 1: return CRTE_TMS;
    case 2: return BIRTH_DT;
    case 3: return BAL_AMT;
    default: throw new org.apache.avro.AvroRuntimeException("Bad index");
    }
  }
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// This was missing from original POJO class thus failing deserialization

  private static final org.apache.avro.Conversion<?>[] conversions =
      new org.apache.avro.Conversion<?>[] {
      null,
      new org.apache.avro.data.TimeConversions.TimestampMicrosConversion(),
      new org.apache.avro.data.TimeConversions.DateConversion(),
      null,
      null
  };
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<


  @Override
  public org.apache.avro.Conversion<?> getConversion(int field) {
    return conversions[field];
  }

  // Used by DatumReader.  Applications should not call.
  @SuppressWarnings(value="unchecked")
  public void put(int field$, java.lang.Object value$) {
    switch (field$) {
    case 0: KEY_NBR = (java.lang.CharSequence)value$; break;
    case 1: CRTE_TMS = (java.time.Instant)value$; break;
    case 2: BIRTH_DT = (java.time.LocalDate)value$; break;
    case 3: BAL_AMT = (java.nio.ByteBuffer)value$; break;
    default: throw new org.apache.avro.AvroRuntimeException("Bad index");
    }
  }

 
  public java.lang.CharSequence getKEYNBR() {
    return KEY_NBR;
  }


  public void setKEYNBR(java.lang.CharSequence value) {
    this.KEY_NBR = value;
  }

  
  public java.time.Instant getCRTETMS() {
    return CRTE_TMS;
  }


  public void setCRTETMS(java.time.Instant value) {
    this.CRTE_TMS = value.truncatedTo(java.time.temporal.ChronoUnit.MICROS);
  }


  public java.time.LocalDate getBIRTHDT() {
    return BIRTH_DT;
  }



  public void setBIRTHDT(java.time.LocalDate value) {
    this.BIRTH_DT = value;
  }

 
  public java.nio.ByteBuffer getBALAMT() {
    return BAL_AMT;
  }


  public void setBALAMT(java.nio.ByteBuffer value) {
    this.BAL_AMT = value;
  }

 
  public static com.modified.User.Builder newBuilder() {
    return new com.modified.User.Builder();
  }


  public static com.modified.User.Builder newBuilder(com.modified.User.Builder other) {
    if (other == null) {
      return new com.modified.User.Builder();
    } else {
      return new com.modified.User.Builder(other);
    }
  }

  
  public static com.modified.User.Builder newBuilder(com.modified.User other) {
    if (other == null) {
      return new com.modified.User.Builder();
    } else {
      return new com.modified.User.Builder(other);
    }
  }
 
  @org.apache.avro.specific.AvroGenerated
  public static class Builder extends org.apache.avro.specific.SpecificRecordBuilderBase<User>
    implements org.apache.avro.data.RecordBuilder<User> {

    private java.lang.CharSequence KEY_NBR;
    private java.time.Instant CRTE_TMS;
    private java.time.LocalDate BIRTH_DT;
    private java.nio.ByteBuffer BAL_AMT;

    /** Creates a new Builder */
    private Builder() {
      super(SCHEMA$);
    }

    private Builder(com.modified.User.Builder other) {
      super(other);
      if (isValidValue(fields()[0], other.KEY_NBR)) {
        this.KEY_NBR = data().deepCopy(fields()[0].schema(), other.KEY_NBR);
        fieldSetFlags()[0] = other.fieldSetFlags()[0];
      }
      if (isValidValue(fields()[1], other.CRTE_TMS)) {
        this.CRTE_TMS = data().deepCopy(fields()[1].schema(), other.CRTE_TMS);
        fieldSetFlags()[1] = other.fieldSetFlags()[1];
      }
      if (isValidValue(fields()[2], other.BIRTH_DT)) {
        this.BIRTH_DT = data().deepCopy(fields()[2].schema(), other.BIRTH_DT);
        fieldSetFlags()[2] = other.fieldSetFlags()[2];
      }
      if (isValidValue(fields()[3], other.BAL_AMT)) {
        this.BAL_AMT = data().deepCopy(fields()[3].schema(), other.BAL_AMT);
        fieldSetFlags()[3] = other.fieldSetFlags()[3];
      }
    }

    /**
     * Creates a Builder by copying an existing User instance
     * @param other The existing instance to copy.
     */
    private Builder(com.modified.User other) {
      super(SCHEMA$);
      if (isValidValue(fields()[0], other.KEY_NBR)) {
        this.KEY_NBR = data().deepCopy(fields()[0].schema(), other.KEY_NBR);
        fieldSetFlags()[0] = true;
      }
      if (isValidValue(fields()[1], other.CRTE_TMS)) {
        this.CRTE_TMS = data().deepCopy(fields()[1].schema(), other.CRTE_TMS);
        fieldSetFlags()[1] = true;
      }
      if (isValidValue(fields()[2], other.BIRTH_DT)) {
        this.BIRTH_DT = data().deepCopy(fields()[2].schema(), other.BIRTH_DT);
        fieldSetFlags()[2] = true;
      }
      if (isValidValue(fields()[3], other.BAL_AMT)) {
        this.BAL_AMT = data().deepCopy(fields()[3].schema(), other.BAL_AMT);
        fieldSetFlags()[3] = true;
      }
    }

    /**
      * Gets the value of the 'KEY_NBR' field.
      * @return The value.
      */
    public java.lang.CharSequence getKEYNBR() {
      return KEY_NBR;
    }


    public com.modified.User.Builder setKEYNBR(java.lang.CharSequence value) {
      validate(fields()[0], value);
      this.KEY_NBR = value;
      fieldSetFlags()[0] = true;
      return this;
    }

   
    public boolean hasKEYNBR() {
      return fieldSetFlags()[0];
    }


    public com.modified.User.Builder clearKEYNBR() {
      KEY_NBR = null;
      fieldSetFlags()[0] = false;
      return this;
    }

  
    public java.time.Instant getCRTETMS() {
      return CRTE_TMS;
    }


    public com.modified.User.Builder setCRTETMS(java.time.Instant value) {
      validate(fields()[1], value);
      this.CRTE_TMS = value.truncatedTo(java.time.temporal.ChronoUnit.MICROS);
      fieldSetFlags()[1] = true;
      return this;
    }


    public boolean hasCRTETMS() {
      return fieldSetFlags()[1];
    }


 
    public com.modified.User.Builder clearCRTETMS() {
      fieldSetFlags()[1] = false;
      return this;
    }

  
    public java.time.LocalDate getBIRTHDT() {
      return BIRTH_DT;
    }

    public com.modified.User.Builder setBIRTHDT(java.time.LocalDate value) {
      validate(fields()[2], value);
      this.BIRTH_DT = value;
      fieldSetFlags()[2] = true;
      return this;
    }


    public boolean hasBIRTHDT() {
      return fieldSetFlags()[2];
    }


    public com.modified.User.Builder clearBIRTHDT() {
      fieldSetFlags()[2] = false;
      return this;
    }

    /**
      * Gets the value of the 'BAL_AMT' field.
      * @return The value.
      */
    public java.nio.ByteBuffer getBALAMT() {
      return BAL_AMT;
    }


    public com.modified.User.Builder setBALAMT(java.nio.ByteBuffer value) {
      validate(fields()[3], value);
      this.BAL_AMT = value;
      fieldSetFlags()[3] = true;
      return this;
    }

    /**
      * Checks whether the 'BAL_AMT' field has been set.
      * @return True if the 'BAL_AMT' field has been set, false otherwise.
      */
    public boolean hasBALAMT() {
      return fieldSetFlags()[3];
    }


    public com.modified.User.Builder clearBALAMT() {
      BAL_AMT = null;
      fieldSetFlags()[3] = false;
      return this;
    }

    @Override
    @SuppressWarnings("unchecked")
    public User build() {
      try {
        User record = new User();
        record.KEY_NBR = fieldSetFlags()[0] ? this.KEY_NBR : (java.lang.CharSequence) defaultValue(fields()[0]);
        record.CRTE_TMS = fieldSetFlags()[1] ? this.CRTE_TMS : (java.time.Instant) defaultValue(fields()[1]);
        record.BIRTH_DT = fieldSetFlags()[2] ? this.BIRTH_DT : (java.time.LocalDate) defaultValue(fields()[2]);
        record.BAL_AMT = fieldSetFlags()[3] ? this.BAL_AMT : (java.nio.ByteBuffer) defaultValue(fields()[3]);
        return record;
      } catch (org.apache.avro.AvroMissingFieldException e) {
        throw e;
      } catch (java.lang.Exception e) {
        throw new org.apache.avro.AvroRuntimeException(e);
      }
    }
  }

  @SuppressWarnings("unchecked")
  private static final org.apache.avro.io.DatumWriter<User>
    WRITER$ = (org.apache.avro.io.DatumWriter<User>)MODEL$.createDatumWriter(SCHEMA$);

  @Override public void writeExternal(java.io.ObjectOutput out)
    throws java.io.IOException {
    WRITER$.write(this, SpecificData.getEncoder(out));
  }

  @SuppressWarnings("unchecked")
  private static final org.apache.avro.io.DatumReader<User>
    READER$ = (org.apache.avro.io.DatumReader<User>)MODEL$.createDatumReader(SCHEMA$);

  @Override public void readExternal(java.io.ObjectInput in)
    throws java.io.IOException {
    READER$.read(this, SpecificData.getDecoder(in));
  }
}

我不明白为什么Avro会这样做,并且我不满意破解原始模式以使事情正常进行.有人可以帮我弄清楚世界如何处理这些问题?

I am not understanding why Avro is doing this and I do not feel comfortable with hacking original schema to make things work. Can someone please help me to figure out how the world is handling these issues?

注意:此问题与

Note: This question is related to this original question that I have asked.

推荐答案

我在avro 1.10.1版中得到的相同行为.以我的经验,Avro未能将类型为null的联合类型和逻辑类型(时间戳,十进制)之一的字段反义化

The same behavior i got in avro version 1.10.1. In my experience, Avro fails on deserealising of field of type union of null and one of the logical types(timestamp, decimal)

示例:

{名称":"CostAmount",类型":["null",{"type":"bytes","logicalType":十进制","precision":19,规模":2}]," default":null},

{ "name": "CostAmount", "type": [ "null", { "type": "bytes", "logicalType": "decimal", "precision": 19, "scale": 2 } ], "default": null },

这篇关于Avro无法在字段中反序列化具有逻辑类型的联合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆