问题
Is it possible to make an avro schema which is recursive, like
Schema schema = SchemaBuilder
.record("RecursiveItem")
.namespace("com.example")
.fields()
.name("subItem")
.type("RecursiveItem")
.withDefault(null) // not sure about that too...
.endRecord();
I get a StackOverflowError when using it like that:
static class RecursiveItem {
RecursiveItem subItem;
}
RecursiveItem item1 = new RecursiveItem();
RecursiveItem item2 = new RecursiveItem();
item1.subItem = item2;
final DatumWriter<RecursiveItem> writer = new SpecificDatumWriter<>(schema);
// note: I actually want a binary output, but I started with some json code I found
ByteArrayOutputStream stream = new ByteArrayOutputStream();
final JsonEncoder encoder = EncoderFactory.get().jsonEncoder(schema, stream);
writer.write(rec1, encoder);
String json = stream.toString();
Note: I also get StackOverflowError if I make the schema using:
Schema schema = ReflectData.get().getSchema(RecursiveItem.class);
回答1:
Warning: I found a solution to write, but cannot read it bask :-\
I am not sure to really understand, but I manage to make it works with:
ReflectDatumWriter
should be used instead ofSpecificDatumWriter
I still had issue with schema not found due to automated lookup of schema upon encoding. It looks for a schema with a namespace+name derived automatically. And in my case where the class is a static subclass, the following should be used:
String cls = RecursiveItem.class.getSimpleName(); String pck = RecursiveItem.class.getPackage().getName(); if (RecursiveItem.class.getEnclosingClass() != null) // nested class pck = RecursiveItem.class.getEnclosingClass().getName() + "$";
To manage the null, the following schema should be used
Schema schema0 = SchemaBuilder .record(cls) .namespace(pck) .fields() .name("subItem") .type().unionOf().nullType().and().type("RecursiveItem").endUnion() .nullDefault() .endRecord();
来源:https://stackoverflow.com/questions/56681506/recursive-schema-with-avro-schemabuilder