Celos/avro-json-decoder


JSON decoder for AVRO that infers default values

Download


Step 1. Add the JitPack repository to your build file

Add it in your root settings.gradle at the end of repositories:

	dependencyResolutionManagement {
		repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
		repositories {
			mavenCentral()
			maven { url 'https://jitpack.io' }
		}
	}

Add it in your settings.gradle.kts at the end of repositories:

	dependencyResolutionManagement {
		repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
		repositories {
			mavenCentral()
			maven { url = uri("https://jitpack.io") }
		}
	}

Add to pom.xml

	<repositories>
		<repository>
		    <id>jitpack.io</id>
		    <url>https://jitpack.io</url>
		</repository>
	</repositories>

Add it in your build.sbt at the end of resolvers:

 
    resolvers += "jitpack" at "https://jitpack.io"
        
    

Add it in your project.clj at the end of repositories:

 
    :repositories [["jitpack" "https://jitpack.io"]]
        
    

Step 2. Add the dependency

	dependencies {
		implementation 'com.github.celos:avro-json-decoder:1.2'
	}
	dependencies {
		implementation("com.github.celos:avro-json-decoder:1.2")
	}
	<dependency>
	    <groupId>com.github.celos</groupId>
	    <artifactId>avro-json-decoder</artifactId>
	    <version>1.2</version>
	</dependency>

                            
    libraryDependencies += "com.github.celos" % "avro-json-decoder" % "1.2"
        
        

                            
    :dependencies [[com.github.celos/avro-json-decoder "1.2"]]
        
        

Readme


avro-json-decoder Build Status

JSON decoder for AVRO that infers default values. Based on org.apache.avro.io.JsonDecoder from <a href="https://github.com/apache/avro">AVRO</a> 1.8.2 and org.apache.avro.io.ExtendedJsonDecoder by <a href="https://github.com/zolyfarkas/avro">zolyfarkas</a>.

why

Given this schema (in AVRO IDL)

record User {
  string username;
  union {null, string} name = null;
}

this record is valid and will be decoded properly

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

whereas this record

{"username":"user1"}

will produce something like

org.apache.avro.AvroTypeException: Expected field name not found: name
	at org.apache.avro.io.JsonDecoder.doAction(JsonDecoder.java:495)
	at org.apache.avro.io.parsing.Parser.advance(Parser.java:88)
	at org.apache.avro.io.JsonDecoder.advance(JsonDecoder.java:157)
	at org.apache.avro.io.JsonDecoder.readIndex(JsonDecoder.java:447)
	...

or

org.apache.avro.AvroTypeException: Expected start-union. Got END_OBJECT
	at org.apache.avro.io.JsonDecoder.error(JsonDecoder.java:698)
	at org.apache.avro.io.JsonDecoder.readIndex(JsonDecoder.java:441)
	at org.apache.avro.io.ResolvingDecoder.doAction(ResolvingDecoder.java:290)
	at org.apache.avro.io.parsing.Parser.advance(Parser.java:88)
        ...

The decoder allows decoding JSON that doesn't specify optional values, provided they have defaults.

how

Replace

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

with

Decoder decoder = new ExtendedJsonDecoder(SCHEMA, INPUT_STREAM_OR_STRING);

and pass it to your reader, as usual:

SpecificDatumReader<T> reader = new SpecificDatumReader<>(SCHEMA_OR_CLASS);
reader.read(null, decoder);