How to avro binary encode my json string to a byte array?
12,196
It seems to be working at least. It can be simplified though: the loops are useless since having more than one object would result in invalid JSON. Also, it could be a good idea to avoid unnecessary parsing of the schema by preparsing it.
Here's my version:
public class AvroTest {
private static final String JSON = "{" + "\"name\":\"Frank\"," + "\"age\":47" + "}";
private static final Schema SCHEMA = new Schema.Parser().parse("{ \"type\":\"record\", \"namespace\":\"foo\", \"name\":\"Person\", \"fields\":[ { \"name\":\"name\", \"type\":\"string\" }, { \"name\":\"age\", \"type\":\"int\" } ] }");
public static void main(String[] args) throws IOException {
byte[] data = jsonToAvro(JSON, SCHEMA);
String jsonString = avroToJson(data, SCHEMA);
System.out.println(jsonString);
}
/**
* Convert JSON to avro binary array.
*
* @param json
* @param schema
* @return
* @throws IOException
*/
public static byte[] jsonToAvro(String json, Schema schema) throws IOException {
DatumReader<Object> reader = new GenericDatumReader<>(schema);
GenericDatumWriter<Object> writer = new GenericDatumWriter<>(schema);
ByteArrayOutputStream output = new ByteArrayOutputStream();
Decoder decoder = DecoderFactory.get().jsonDecoder(schema, json);
Encoder encoder = EncoderFactory.get().binaryEncoder(output, null);
Object datum = reader.read(null, decoder);
writer.write(datum, encoder);
encoder.flush();
return output.toByteArray();
}
/**
* Convert Avro binary byte array back to JSON String.
*
* @param avro
* @param schema
* @return
* @throws IOException
*/
public static String avroToJson(byte[] avro, Schema schema) throws IOException {
boolean pretty = false;
GenericDatumReader<Object> reader = new GenericDatumReader<>(schema);
DatumWriter<Object> writer = new GenericDatumWriter<>(schema);
ByteArrayOutputStream output = new ByteArrayOutputStream();
JsonEncoder encoder = EncoderFactory.get().jsonEncoder(schema, output, pretty);
Decoder decoder = DecoderFactory.get().binaryDecoder(avro, null);
Object datum = reader.read(null, decoder);
writer.write(datum, encoder);
encoder.flush();
output.flush();
return new String(output.toByteArray(), "UTF-8");
}
}
Author by
john
Updated on July 24, 2022Comments
-
john almost 2 years
I have a actual JSON String which I need to avro binary encode to a byte array. After going through the Apache Avro specification, I came up with the below code.
I am not sure whether this is the right way to do it or not. Can anyone take a look whether the way I am trying to avro binary encode my JSON String is correct or not?. I am using Apache Avro 1.7.7 version.
public class AvroTest { private static final String json = "{" + "\"name\":\"Frank\"," + "\"age\":47" + "}"; private static final String schema = "{ \"type\":\"record\", \"namespace\":\"foo\", \"name\":\"Person\", \"fields\":[ { \"name\":\"name\", \"type\":\"string\" }, { \"name\":\"age\", \"type\":\"int\" } ] }"; public static void main(String[] args) throws IOException { byte[] data = jsonToAvro(json, schema); String jsonString = avroToJson(data, schema); System.out.println(jsonString); } /** * Convert JSON to avro binary array. * * @param json * @param schemaStr * @return * @throws IOException */ public static byte[] jsonToAvro(String json, String schemaStr) throws IOException { InputStream input = null; GenericDatumWriter<Object> writer = null; Encoder encoder = null; ByteArrayOutputStream output = null; try { Schema schema = new Schema.Parser().parse(schemaStr); DatumReader<Object> reader = new GenericDatumReader<Object>(schema); input = new ByteArrayInputStream(json.getBytes()); output = new ByteArrayOutputStream(); DataInputStream din = new DataInputStream(input); writer = new GenericDatumWriter<Object>(schema); Decoder decoder = DecoderFactory.get().jsonDecoder(schema, din); encoder = EncoderFactory.get().binaryEncoder(output, null); Object datum; while (true) { try { datum = reader.read(null, decoder); } catch (EOFException eofe) { break; } writer.write(datum, encoder); } encoder.flush(); return output.toByteArray(); } finally { try { input.close(); } catch (Exception e) { } } } /** * Convert Avro binary byte array back to JSON String. * * @param avro * @param schemaStr * @return * @throws IOException */ public static String avroToJson(byte[] avro, String schemaStr) throws IOException { boolean pretty = false; GenericDatumReader<Object> reader = null; JsonEncoder encoder = null; ByteArrayOutputStream output = null; try { Schema schema = new Schema.Parser().parse(schemaStr); reader = new GenericDatumReader<Object>(schema); InputStream input = new ByteArrayInputStream(avro); output = new ByteArrayOutputStream(); DatumWriter<Object> writer = new GenericDatumWriter<Object>(schema); encoder = EncoderFactory.get().jsonEncoder(schema, output, pretty); Decoder decoder = DecoderFactory.get().binaryDecoder(input, null); Object datum; while (true) { try { datum = reader.read(null, decoder); } catch (EOFException eofe) { break; } writer.write(datum, encoder); } encoder.flush(); output.flush(); return new String(output.toByteArray()); } finally { } } }