【问题标题】:How to avro binary encode my json string to a byte array?如何将我的 json 字符串二进制编码为字节数组?
【发布时间】:2015-02-27 02:21:21
【问题描述】:

我有一个实际的 JSON 字符串,我需要将其二进制编码为字节数组。经过Apache Avro specification之后,我想出了下面的代码。

我不确定这是否是正确的做法。谁能看看我尝试对我的 JSON 字符串进行 avro 二进制编码的方式是否正确?我使用的是 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 {

        }
    }

}

【问题讨论】:

    标签: java json bytearray avro


    【解决方案1】:

    它似乎至少可以工作。不过可以简化:循环是无用的,因为拥有多个对象会导致 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");
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2020-03-04
      • 2013-07-17
      • 1970-01-01
      • 2021-12-20
      • 2013-09-29
      • 1970-01-01
      • 2011-10-02
      • 1970-01-01
      相关资源
      最近更新 更多