Json String for Java Object Avro

I am trying to convert a Json string to a shared Java object using an Avro schema.

Below is my code.

String json = "{\"foo\": 30.1, \"bar\": 60.2}"; String schemaLines = "{\"type\":\"record\",\"name\":\"FooBar\",\"namespace\":\"com.foo.bar\",\"fields\":[{\"name\":\"foo\",\"type\":[\"null\",\"double\"],\"default\":null},{\"name\":\"bar\",\"type\":[\"null\",\"double\"],\"default\":null}]}"; InputStream input = new ByteArrayInputStream(json.getBytes()); DataInputStream din = new DataInputStream(input); Schema schema = Schema.parse(schemaLines); Decoder decoder = DecoderFactory.get().jsonDecoder(schema, din); DatumReader<Object> reader = new GenericDatumReader<Object>(schema); Object datum = reader.read(null, decoder); 

I get "org.apache.avro.AvroTypeException: expected start-join. VALUE_NUMBER_FLOAT exception thrown."

The same code works if I do not have unions in the circuit. Can someone explain and give me a solution.

+7
java json avro
source share
3 answers

Your schema does not match the json string schema. You should have another scheme that does not have a union instead of an error, but a decimal number. Such a circuit should then be used as a writing circuit, while you can freely use the other as a reading circuit.

0
source share

Thanks Reza. I found this web page. It describes how to convert a Json string to an avro object.

http://rezarahim.blogspot.com/2013/06/import-org_26.html

Key of his code:

 static byte[] fromJsonToAvro(String json, String schemastr) throws Exception { InputStream input = new ByteArrayInputStream(json.getBytes()); DataInputStream din = new DataInputStream(input); Schema schema = Schema.parse(schemastr); Decoder decoder = DecoderFactory.get().jsonDecoder(schema, din); DatumReader<Object> reader = new GenericDatumReader<Object>(schema); Object datum = reader.read(null, decoder); GenericDatumWriter<Object> w = new GenericDatumWriter<Object>(schema); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); Encoder e = EncoderFactory.get().binaryEncoder(outputStream, null); w.write(datum, e); e.flush(); return outputStream.toByteArray(); } String json = "{\"username\":\"miguno\",\"tweet\":\"Rock: Nerf paper, scissors is fine.\",\"timestamp\": 1366150681 }"; String schemastr ="{ \"type\" : \"record\", \"name\" : \"twitter_schema\", \"namespace\" : \"com.miguno.avro\", \"fields\" : [ { \"name\" : \"username\", \"type\" : \"string\", \"doc\" : \"Name of the user account on Twitter.com\" }, { \"name\" : \"tweet\", \"type\" : \"string\", \"doc\" : \"The content of the user Twitter message\" }, { \"name\" : \"timestamp\", \"type\" : \"long\", \"doc\" : \"Unix epoch time in seconds\" } ], \"doc:\" : \"A basic schema for storing Twitter messages\" }"; byte[] avroByteArray = fromJsonToAvro(json,schemastr); Schema schema = Schema.parse(schemastr); DatumReader<Genericrecord> reader1 = new GenericDatumReader<Genericrecord>(schema); Decoder decoder1 = DecoderFactory.get().binaryDecoder(avroByteArray, null); GenericRecord result = reader1.read(null, decoder1); 
+6
source share

With Avro 1.4.1, this works:

 private static GenericData.Record parseJson(String json, String schema) throws IOException { Schema parsedSchema = Schema.parse(schema); Decoder decoder = new JsonDecoder(parsedSchema, json); DatumReader<GenericData.Record> reader = new GenericDatumReader<>(parsedSchema); return reader.read(null, decoder); } 

You may need a few tweaks for later versions of Avro.

+3
source share

All Articles