如何用Avro RandomData生成含UNION类型的合法JSON样本?
如何用Avro RandomData生成带UNION类型标识的合法JSON样本?
问题背景
使用Avro v1.11.3版本的RandomData工具,基于以下User Schema生成随机JSON样本:
{ "namespace": "example.avro", "type": "record", "name": "User", "fields": [ { "name": "name", "type": "string" }, { "name": "favorite_number", "type": ["int", "null"] }, { "name": "favorite_color", "type": ["string", "null"] } ] }
当前使用的Java代码如下:
package org.example; import org.apache.avro.Schema; import org.apache.avro.util.RandomData; import java.io.IOException; import java.io.InputStream; import java.util.Iterator; public class MyTest { public static void main(String [] args) throws IOException { MyTest me = new MyTest(); ClassLoader classLoader = me.getClass().getClassLoader(); InputStream is = classLoader.getResourceAsStream("person.avsc"); Schema schema = new Schema.Parser().parse(is); Iterator<Object> it = new RandomData(schema, 1).iterator(); System.out.println(it.next()); } }
执行后生成的JSON样本不符合Schema要求,UNION类型字段未生成带类型标识的结构:
{ "name": "rymhxcnbcyohbtjmouegufvchxh", "favorite_number": 4211, "favorite_color": "red" }
预期的合法JSON样本应为:
{ "name": "rymhxcnbcyohbtjmouegufvchxh", "favorite_number": { "int": 4211 }, "favorite_color": { "string": "red" } }
解决方案
RandomData生成的是Avro的GenericRecord实例,直接调用toString()输出的是简化格式,并非符合Avro JSON编码规范的序列化结果。需要使用Avro官方的JSON序列化工具类来处理,才能正确生成带UNION类型标识的结构。
修改后的代码如下:
package org.example; import org.apache.avro.Schema; import org.apache.avro.generic.GenericDatumWriter; import org.apache.avro.generic.GenericRecord; import org.apache.avro.io.DatumWriter; import org.apache.avro.io.Encoder; import org.apache.avro.io.JsonEncoder; import org.apache.avro.util.RandomData; import com.fasterxml.jackson.core.JsonFactory; import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; import java.util.Iterator; public class MyTest { public static void main(String [] args) throws IOException { MyTest me = new MyTest(); ClassLoader classLoader = me.getClass().getClassLoader(); InputStream is = classLoader.getResourceAsStream("person.avsc"); Schema schema = new Schema.Parser().parse(is); // 生成随机GenericRecord Iterator<Object> it = new RandomData(schema, 1).iterator(); GenericRecord record = (GenericRecord) it.next(); // 使用Avro JsonEncoder序列化 DatumWriter<GenericRecord> writer = new GenericDatumWriter<>(schema); JsonFactory jsonFactory = new JsonFactory(); Encoder encoder = new JsonEncoder(schema, jsonFactory.createGenerator(new OutputStreamWriter(System.out))); writer.write(record, encoder); encoder.flush(); } }
说明
- 引入
GenericDatumWriter和JsonEncoder类,这是Avro官方提供的JSON序列化工具,严格遵循Avro的JSON编码规则。 - 将
RandomData生成的Object强制转换为GenericRecord(因为Schema是record类型,生成的实例必然是GenericRecord)。 - 通过
JsonEncoder将GenericRecord序列化为符合规范的JSON,其中UNION类型字段会自动生成带类型标识的嵌套结构。
内容的提问来源于stack exchange,提问作者NoName
相关产品推荐
相关产品推荐

