java - 解码原始字节数组后如何更改特定字段值?

标签 java json avro

我有一个像这样的 Avro 架构 -

{
   "type":"record",
   "name":"new_user",
   "namespace":"com.hello",
   "fields":[
      {
         "name":"user_id",
         "type":[
            "long",
            "null"
         ]
      },
      {
         "name":"segment",
         "type":[
            "string",
            "null"
         ]
      }
   ]
}

我正在使用上面的 Avro 架构来序列化数据,这给了我一个字节数组并且工作正常 -

public static void main(String[] args) throws IOException {
    Schema schema = new Parser()
            .parse("{ \"type\":\"record\", \"name\":\"new_user\", \"namespace\":\"com.hello\", \"fields\":[ { \"name\":\"user_id\", \"type\":[ \"long\", \"null\" ] }, { \"name\":\"segment\", \"type\":[ \"string\", \"null\" ] } ] }");

    byte[] originalAvrodata = getAvroBinaryData(schema);

    // how to get newAvroData byte array in which user_id 
    // is change to some other random long number?
}

private static byte[] getAvroBinaryData(Schema schema) throws IOException {
    GenericRecord record = new GenericData.Record(schema);
    record.put("user_id", 123456L);
    record.put("segment", "hello");

    GenericDatumWriter<GenericRecord> writer = new GenericDatumWriter<GenericRecord>(schema);
    ByteArrayOutputStream os = new ByteArrayOutputStream();

    Encoder e = EncoderFactory.get().binaryEncoder(os, null);

    writer.write(record, e);
    e.flush();
    byte[] byteData = os.toByteArray();
    return byteData;
}

问题陈述:

我需要解码 originalAvrodata 字节数组,然后将 user_id 字段值更改为其他 long 数字,然后构造一个 newAvroData 字节数组使用相同的模式,其中的 user_id 字段值应为某个随机的long 数字。使用 Avro 是否有可能做到这一点?

最佳答案

当然,这里有一些带注释的代码,应该可以帮助您入门:

public static void main(String[] args) throws IOException, JSONException {
        Schema schema = new Schema.Parser()
           .parse("{ \"type\":\"record\", \"name\":\"new_user\", \"namespace\":\"com.hello\", \"fields\":[ { \"name\":\"user_id\", \"type\":[ \"long\", \"null\" ] }, { \"name\":\"segment\", \"type\":[ \"string\", \"null\" ] } ] }");

        // create example record
        GenericRecord record = new GenericData.Record(schema);
        record.put("user_id", 123456L);
        record.put("segment", "hello");

        // serialize record
        byte[] recordData = getAvroBinaryData(schema, record);

        // de-serialize byte array to record  
        GenericRecord readRecord = readRecord(schema, recordData);

        // increment user_id field
        Long userId = (Long) readRecord.get("user_id");
        readRecord.put("user_id", userId + 1);

        // prints 123457 for the user_id
        System.out.println(readRecord);

        // serialize updated recored
        byte[] updatedRecordData = getAvroBinaryData(schema, readRecord);

        // do something with updatedRecordData
    }   

    private static GenericRecord readRecord(Schema schema, byte[] originalAvrodata) throws IOException {
        Decoder decoder = DecoderFactory.get().binaryDecoder(originalAvrodata, null);       
        DatumReader<GenericRecord> reader = new GenericDatumReader<GenericRecord>(schema);
        GenericRecord readRecord = null;

        try {
            readRecord = reader.read(null, decoder);            
        } catch (EOFException eofe) {
            eofe.printStackTrace();
        }

        return readRecord;
    }

    // takes the record to be serialized as an additonal parameter
    private static byte[] getAvroBinaryData(Schema schema, GenericRecord record) throws IOException {
        GenericDatumWriter<GenericRecord> writer = new GenericDatumWriter<GenericRecord>(schema);
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        Encoder e = EncoderFactory.get().binaryEncoder(os, null);
        writer.write(record, e);
        e.flush();
        byte[] byteData = os.toByteArray();
        return byteData;
    }

关于java - 解码原始字节数组后如何更改特定字段值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27912699/

相关文章:

c# - C# 中的 Culture 是否等同于 Java 中的 Locale?

java - 如何在 Java 中解析 JSON

javascript - 未捕获的语法错误 : Unexpected string in JSON at position 7 when using $. parseJSON

java - 如何使用 Avro 和 Flink 解码 Kafka 消息

java - Guava/测试迭代器实现

java - Android alarmManager.setAlarmClock 崩溃 Android 7

java - 如何反序列化 Map<String, Object> 使用不同类型的不同 key 与 jackson ?

java - JsonParseException : Invalid UTF-8 middle byte 0x2d

azure - 我可以将 Avro 序列化数据附加到现有的 Azure blob 中吗?

java - 在 Apache Log4J 中,有没有一种方法可以简单地即时创建多个日志文件,而不是附加到一个日志文件?