Skip to the content.

Avro Json Optional Decoder

Java CI Quality Gate Status Coverage Maintainability Rating

Avro Decoder with support optional fields in JSON. Based on Celos fork.

Dependency

Gradle

dependencies {
    implementation 'com.github.goodforgod:avro-json-optional-decoder:1.1.6'
}

Maven

<dependency>
    <groupId>com.github.goodforgod</groupId>
    <artifactId>avro-json-optional-decoder</artifactId>
    <version>1.1.6</version>
</dependency>

Compatibility

Library is Java 1.8 compatible.

Library is compatible with different Apache Avro versions. Please use compatible library version for your Apache Avro version.

Apache Avro Version Library Version
1.9.2 1.1.6
1.8.2 1.0.1

Optional Field Problem

For given AVRO Schema.

{
  "type" : "record",
  "name" : "Person",
  "fields" : [ {
    "name" : "username",
    "type" : "string"
  }, {
    "name" : "name",
    "type" : [ "null", "string" ]
  } ]
}

Such JSON will be treated correctly.

{"username":"user1","name":null}

However, such JSON (name field is missing).

{"username":"user1"}

Will fail with:

org.apache.avro.AvroTypeException: Expected field name not found: name

Solution

JsonOptionalDecoder provided by library allow correct JSON validation in both cases, decoding JSON that doesn’t specify optional values, provided they have defaults.

Check guides on how-to-use Avro Decoders.

Be aware JsonOptionalDecoder is not thread-safe.

Optional Record Problem

For given AVRO Schema.

{
  "name": "Test",
  "type": "record",
  "fields": [
    {
      "name": "required",
      "type": "string"
    },
    {
      "name": "inner",
      "type": [
        "null",
        {
          "name": "inner",
          "type": "record",
          "fields": [
            {
              "name": "req",
              "type": "string"
            }
          ]
        }
      ]
    }
  ]
}

This input will be correct:

{"required":"u", "inner": {"req": "q"}}

As this input will be correct:

{"required":"u"}

By Default

If property default is not specified, then missing field will be treated as avro null value.

{
    "name" : "name",
    "type" : [ "null", "string" ]
}

You can specify default value as per AVRO specification.

Keep in mind you mind putting type corresponding to default value first, due to AVRO incorrect union type validation.

{
    "name" : "name",
    "type" : [ "string", "null" ],
    "default": "bob"
}

How To Use

Change

Decoder decoder = DecoderFactory.get().jsonDecoder(SCHEMA, INPUT_STREAM_OR_STRING);

With

Decoder decoder = new JsonOptionalDecoder(SCHEMA, INPUT_STREAM_OR_STRING);

License

This project licensed under the MIT - see the LICENSE file for details.