Skip to content

Commit 97004ed

Browse files
committed
[Java] Fix default values of fields with UNION schemas where the NULL schema comes first
The assumption in JacksonUtils#toObject(JsonNode, Schema), that the actual data schema in a UNION schema (of some data with NULL), always comes first, is incorrect. For example, a field with this schema will have its default value converted incorrectly: ``` { "name": "exampleDateTime", "type": ["null", { "type": "long", "logicalType": "local-timestamp-millis" }], "default": 1746088255000 } ``` Here the "null" schema explicitly comes first and the assumption is no longer correct (JacksonUtils tries to interpret the value 1746088255000 using the NULL schema). Another example using Avro IDL (nullable field, containing an array of nullable items): ``` record SomeRecord { union{array<int?>, null} optArrayOptItemVal = [4]; } ``` In this case, the "optArrayOptItemVal" field fulfills the assumption, but the array item's schema does not. On my machine, with Avro 1.12.1, the item's schema is the following: ``` "type": ["null", { "type": "int" }] ``` which also fails the non-NULL schema first assumption.
1 parent 999b36f commit 97004ed

2 files changed

Lines changed: 21 additions & 1 deletion

File tree

lang/java/avro/src/main/java/org/apache/avro/util/internal/JacksonUtils.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,11 @@ public static Object toObject(JsonNode jsonNode) {
115115

116116
public static Object toObject(JsonNode jsonNode, Schema schema) {
117117
if (schema != null && schema.getType().equals(Schema.Type.UNION)) {
118-
return toObject(jsonNode, schema.getTypes().get(0));
118+
if (schema.getTypes().get(0).getType() != (Schema.Type.NULL)) {
119+
return toObject(jsonNode, schema.getTypes().get(0));
120+
} else {
121+
return toObject(jsonNode, schema.getTypes().get(1));
122+
}
119123
}
120124
if (jsonNode == null) {
121125
return null;

lang/java/avro/src/test/java/org/apache/avro/util/internal/TestJacksonUtils.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ void testToObject() {
7979
assertEquals(1, toObject(IntNode.valueOf(1)));
8080
assertEquals(2L, toObject(IntNode.valueOf(2), Schema.create(Schema.Type.LONG)));
8181
assertEquals(1.0f, toObject(DoubleNode.valueOf(1.0), Schema.create(Schema.Type.FLOAT)));
82+
assertEquals(1.1f, toObject(DoubleNode.valueOf(1.1), Schema.createUnion(Schema.create(Schema.Type.NULL), Schema.create(Schema.Type.FLOAT))));
83+
assertEquals(1.2f, toObject(DoubleNode.valueOf(1.2), Schema.createUnion(Schema.create(Schema.Type.FLOAT), Schema.create(Schema.Type.NULL))));
8284
assertEquals(2.0, toObject(DoubleNode.valueOf(2.0)));
8385
assertEquals(TextNode.valueOf("\u0001\u0002"), toJsonNode(new byte[] { 1, 2 }));
8486
assertArrayEquals(new byte[] { 1, 2 },
@@ -90,6 +92,20 @@ void testToObject() {
9092
an.add(1);
9193
assertEquals(Collections.singletonList(1), toObject(an));
9294

95+
assertEquals(Collections.singletonList(1), toObject(an,
96+
Schema.createUnion(
97+
Schema.create(Schema.Type.NULL),
98+
Schema.createArray(Schema.createUnion(
99+
Schema.create(Schema.Type.NULL),
100+
Schema.create(Schema.Type.INT))))));
101+
102+
assertEquals(Collections.singletonList(1), toObject(an,
103+
Schema.createUnion(
104+
Schema.createArray(Schema.createUnion(
105+
Schema.create(Schema.Type.INT),
106+
Schema.create(Schema.Type.NULL))),
107+
Schema.create(Schema.Type.NULL))));
108+
93109
ObjectNode on = JsonNodeFactory.instance.objectNode();
94110
on.put("a", 1);
95111
assertEquals(Collections.singletonMap("a", 1), toObject(on));

0 commit comments

Comments
 (0)