From 256de35530957afba03a0a20def06fd18c32d81e Mon Sep 17 00:00:00 2001 From: Guillaume Wallet Date: Fri, 19 Sep 2025 17:57:33 +0200 Subject: [PATCH] fix: AVRO-3106 The Java JsonDecoder does not actually allow there to be unknown fields in the reader compared to the writer's schema. In cases where this happens it gives the following error: org.apache.avro.AvroTypeException: Expected Unknown fields: []. Got END_OBJECT --- .../java/org/apache/avro/io/JsonDecoder.java | 3 --- .../java/org/apache/avro/io/TestEncoders.java | 22 +++++++++---------- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/lang/java/avro/src/main/java/org/apache/avro/io/JsonDecoder.java b/lang/java/avro/src/main/java/org/apache/avro/io/JsonDecoder.java index 64e7ba9faf4..be6d8f005e8 100644 --- a/lang/java/avro/src/main/java/org/apache/avro/io/JsonDecoder.java +++ b/lang/java/avro/src/main/java/org/apache/avro/io/JsonDecoder.java @@ -505,9 +505,6 @@ public Symbol doAction(Symbol input, Symbol top) throws IOException { } if (top == Symbol.RECORD_END) { - if (currentReorderBuffer != null && !currentReorderBuffer.savedFields.isEmpty()) { - throw error("Unknown fields: " + currentReorderBuffer.savedFields.keySet()); - } currentReorderBuffer = reorderBuffers.pop(); } diff --git a/lang/java/avro/src/test/java/org/apache/avro/io/TestEncoders.java b/lang/java/avro/src/test/java/org/apache/avro/io/TestEncoders.java index 51ef375e307..dedc1010988 100644 --- a/lang/java/avro/src/test/java/org/apache/avro/io/TestEncoders.java +++ b/lang/java/avro/src/test/java/org/apache/avro/io/TestEncoders.java @@ -200,18 +200,16 @@ void jsonRecordOrdering() throws IOException { @Test void jsonExcessFields() throws IOException { - assertThrows(AvroTypeException.class, () -> { - String value = "{\"b\": { \"b3\": 1.4, \"b2\": 3.14, \"b1\": \"h\"}, \"a\": {\"a0\": 45, \"a2\":true, \"a1\": null}}"; - Schema schema = new Schema.Parser().parse("{\"type\": \"record\", \"name\": \"ab\", \"fields\": [\n" - + "{\"name\": \"a\", \"type\": {\"type\":\"record\",\"name\":\"A\",\"fields\":\n" - + "[{\"name\":\"a1\", \"type\":\"null\"}, {\"name\":\"a2\", \"type\":\"boolean\"}]}},\n" - + "{\"name\": \"b\", \"type\": {\"type\":\"record\",\"name\":\"B\",\"fields\":\n" - + "[{\"name\":\"b1\", \"type\":\"string\"}, {\"name\":\"b2\", \"type\":\"float\"}, {\"name\":\"b3\", \"type\":\"double\"}]}}\n" - + "]}"); - GenericDatumReader reader = new GenericDatumReader<>(schema); - Decoder decoder = DecoderFactory.get().jsonDecoder(schema, value); - reader.read(null, decoder); - }); + String value = "{\"b\": { \"b3\": 1.4, \"b2\": 3.14, \"b1\": \"h\"}, \"a\": {\"a0\": 45, \"a2\":true, \"a1\": null}}"; + Schema schema = new Schema.Parser().parse("{\"type\": \"record\", \"name\": \"ab\", \"fields\": [\n" + + "{\"name\": \"a\", \"type\": {\"type\":\"record\",\"name\":\"A\",\"fields\":\n" + + "[{\"name\":\"a1\", \"type\":\"null\"}, {\"name\":\"a2\", \"type\":\"boolean\"}]}},\n" + + "{\"name\": \"b\", \"type\": {\"type\":\"record\",\"name\":\"B\",\"fields\":\n" + + "[{\"name\":\"b1\", \"type\":\"string\"}, {\"name\":\"b2\", \"type\":\"float\"}, {\"name\":\"b3\", \"type\":\"double\"}]}}\n" + + "]}"); + GenericDatumReader reader = new GenericDatumReader<>(schema); + Decoder decoder = DecoderFactory.get().jsonDecoder(schema, value); + assertNotNull(reader.read(null, decoder)); } @Test