使Avro模式中的所有字段都可为空的最短,最安全的方法是什么?
当然,我可以使用模式的Json进行操作,就像schema.toString().replaceAll("\"type\": \"long\"", "\"type\": [\"null\", \"long\"]")
一样,但这是一个非常丑陋且不安全的解决方案。
答案 0 :(得分:0)
以下代码将为联合类型添加默认值,并且还将首先将类型与null类型交换。您可以为原始类型添加另一个条件,并添加联合类型以及'null'默认值。
import org.apache.avro.JsonProperties;
import org.apache.avro.Schema;
...
String srcSchemaFile = "sample.avsc"; // Source Avro schema file
String targetSchemaFile = "sample_fixed.avsc"; // Target Avro schema file
Schema.Parser avroParser = new Schema.Parser();
Schema schema = avroParser.parse(new File(srcSchemaFile));
makeNullable(schema);
PrintWriter writer = new PrintWriter(targetSchemaFile);
writer.write(schema.toString().replaceAll("defaultXXX", "default"));
writer.close();
...
private static void makeNullable(Schema schema){
if ( schema.getType() != Schema.Type.NULL){
for ( Schema.Field field: schema.getFields()){
if (field.schema().getType() == Schema.Type.UNION){
int nullIndex = IntStream.range(0, field.schema().getTypes().size())
.filter(i -> field.schema().getTypes().get(i).getType() == Schema.Type.NULL )
.findFirst().orElse(-1);
if (nullIndex > 0 && field.defaultVal() == null){
// default property is reserved and cannot be added through addProp method, adding defaultXXX to replace later as a workaround
field.addProp("defaultXXX", JsonProperties.NULL_VALUE);
Collections.swap(field.schema().getTypes(), 0, nullIndex);
}
for (Schema fieldSchema: field.schema().getTypes()){
if (fieldSchema.getType() == Schema.Type.RECORD){
makeNullable(fieldSchema);
} else if (fieldSchema.getType() == Schema.Type.ARRAY){
for (Schema elemSchema: fieldSchema.getElementType().getTypes()){
if (elemSchema.getType() == Schema.Type.RECORD){
makeNullable(elemSchema);
}
}
}
}
}
}
}
}