我有一个实际的JSON字符串,我需要将二进制编码转换为字节数组。完成Apache Avro specification之后,我想出了以下代码。
我不确定这是否是正确的做法。任何人都可以看看我试图avro二进制编码我的JSON字符串的方式是否正确?我正在使用Apache Avro 1.7.7版本。
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 {
}
}
}
答案 0 :(得分:13)
它似乎至少起作用了。它可以简化:循环是无用的,因为有多个对象会导致无效的JSON。此外,最好通过预先设置来避免对模式进行不必要的解析。
这是我的版本:
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");
}
}