Skip to content

Commit

Permalink
[parser] fix default parsing of record field's of type union (#487)
Browse files Browse the repository at this point in the history
  • Loading branch information
dg-builder authored May 2, 2023
1 parent 54e2c11 commit 3865773
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -857,44 +857,12 @@ mapSchema, locationOf(context.getUri(), literalNode), map
AvroUnionSchema unionSchema = (AvroUnionSchema) fieldSchema;
//union values are encoded as a json object {"<branch>" : <value>}
//except for null
JsonValue.ValueType valueType = fieldLiteral.getValueType();
int branchNumber;
switch (valueType) {
case NULL:
branchNumber = unionSchema.resolve(AvroType.NULL);
literal = fieldLiteral;
break;
case OBJECT:
Set<Map.Entry<String, JsonValue>> unionObjectProps = ((JsonObjectExt) fieldLiteral).entrySet();
if (unionObjectProps.size() != 1) {
//TODO - provide more details (union object expected to only have a single prop)
issue = AvscIssues.badFieldDefaultValue(locationOf(context.getUri(), literalNode),
literalNode.toString(), avroType, fieldName);
return new LiteralOrIssue(issue);
}
Map.Entry<String, JsonValue> discriminatorEntry = unionObjectProps.iterator().next();
String discriminator = discriminatorEntry.getKey();
literal = (JsonValueExt) discriminatorEntry.getValue();
AvroType literalType = AvroType.fromTypeName(discriminator);
if (literalType != null) {
branchNumber = unionSchema.resolve(literalType);
} else {
//assume fullname then
branchNumber = unionSchema.resolve(discriminator);
}
break;
default:
issue = AvscIssues.badFieldDefaultValue(locationOf(context.getUri(), literalNode),
literalNode.toString(), avroType, fieldName);
return new LiteralOrIssue(issue);

}
if (branchNumber < 0) {
if (unionSchema.getTypes().size() == 0) {
issue = AvscIssues.badFieldDefaultValue(locationOf(context.getUri(), literalNode),
literalNode.toString(), avroType, fieldName);
return new LiteralOrIssue(issue);
}
literalSchema = unionSchema.getTypes().get(branchNumber).getSchema();
literalSchema = unionSchema.getTypes().get(0).getSchema();
}
LiteralOrIssue fieldValueOrIssue = parseLiteral(literal, literalSchema, fieldName, context);
if (fieldValueOrIssue.getIssue() != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import com.linkedin.avroutil1.model.AvroMapLiteral;
import com.linkedin.avroutil1.model.AvroMapSchema;
import com.linkedin.avroutil1.model.AvroPrimitiveSchema;
import com.linkedin.avroutil1.model.AvroRecordLiteral;
import com.linkedin.avroutil1.model.AvroRecordSchema;
import com.linkedin.avroutil1.model.AvroSchema;
import com.linkedin.avroutil1.model.AvroSchemaField;
Expand Down Expand Up @@ -72,6 +73,16 @@ public void testParseInvalidType2() throws Exception {
Assert.assertTrue(result.getParseError() instanceof AvroSyntaxException);
}

@Test
public void testRecordDefaults() throws Exception {
String avsc = TestUtil.load("schemas/RecordDefaultWithUnionField.avsc");
AvscParser parser = new AvscParser();
AvscParseResult result = parser.parse(avsc);
Assert.assertNull(result.getParseError());
AvroRecordLiteral defaultFieldValue =
(AvroRecordLiteral) ((AvroRecordSchema) result.getTopLevelSchema()).getFields().get(0).getDefaultValue();
Assert.assertEquals(defaultFieldValue.getValue().toString(), "{f2=null, f3=Enum1, f1=someString}");
}
@Test
public void testParseInvalidDoc() throws Exception {
String avsc = TestUtil.load("schemas/TestInvalidDocRecord.avsc");
Expand Down
45 changes: 45 additions & 0 deletions parser/src/test/resources/schemas/RecordDefaultWithUnionField.avsc
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"type": "record",
"name": "SchemaWithRecordDefault",
"fields": [
{
"name": "mainField",
"type": {
"type": "record",
"name": "InnerRecord",
"fields": [
{
"name": "f1",
"type": [
"string",
"null"
]
},
{
"name": "f2",
"type": [
"null",
"string"
]
},
{
"name": "f3",
"type": {
"type": "enum",
"name": "MyEnum",
"symbols": [
"Enum1",
"Enum2"
]
}
}
]
},
"default": {
"f1": "someString",
"f2": null,
"f3": "Enum1"
}
}
]
}
5 changes: 3 additions & 2 deletions parser/src/test/resources/schemas/TestTreeNode.avsc
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@
"null"
],
"default": [
{"children" : {"array": []}},
{"children" : null}
{
"children": []
}
]
}
]
Expand Down

0 comments on commit 3865773

Please sign in to comment.