Skip to content

Commit e15f7cb

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 e15f7cb

File tree

2 files changed

+18
-1
lines changed

2 files changed

+18
-1
lines changed

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: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ 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),
83+
Schema.createUnion(Schema.create(Schema.Type.NULL), Schema.create(Schema.Type.FLOAT))));
84+
assertEquals(1.2f, toObject(DoubleNode.valueOf(1.2),
85+
Schema.createUnion(Schema.create(Schema.Type.FLOAT), Schema.create(Schema.Type.NULL))));
8286
assertEquals(2.0, toObject(DoubleNode.valueOf(2.0)));
8387
assertEquals(TextNode.valueOf("\u0001\u0002"), toJsonNode(new byte[] { 1, 2 }));
8488
assertArrayEquals(new byte[] { 1, 2 },
@@ -90,6 +94,15 @@ void testToObject() {
9094
an.add(1);
9195
assertEquals(Collections.singletonList(1), toObject(an));
9296

97+
assertEquals(Collections.singletonList(1), toObject(an, Schema.createUnion(Schema.create(Schema.Type.NULL),
98+
Schema.createArray(Schema.createUnion(Schema.create(Schema.Type.NULL), Schema.create(Schema.Type.INT))))));
99+
100+
assertEquals(Collections.singletonList(1),
101+
toObject(an,
102+
Schema.createUnion(
103+
Schema.createArray(Schema.createUnion(Schema.create(Schema.Type.INT), Schema.create(Schema.Type.NULL))),
104+
Schema.create(Schema.Type.NULL))));
105+
93106
ObjectNode on = JsonNodeFactory.instance.objectNode();
94107
on.put("a", 1);
95108
assertEquals(Collections.singletonMap("a", 1), toObject(on));

0 commit comments

Comments
 (0)