【问题标题】:How to change a particular field value after decoding the original byte array?解码原始字节数组后如何更改特定字段值?
【发布时间】:2015-01-12 23:42:21
【问题描述】:

我有一个像这样的 Avro Schema -

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

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

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 数字,然后使用应该具有user_id 字段值的相同架构构造一个newAvroData 字节数组到一些随机的long 号码。使用 Avro 是否有可能做到这一点?

【问题讨论】:

    标签: java json avro


    【解决方案1】:

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

    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;
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-08
      • 1970-01-01
      • 1970-01-01
      • 2019-05-02
      • 2019-10-19
      • 2019-03-24
      • 2022-01-07
      • 2019-12-29
      相关资源
      最近更新 更多