From bbddba8a2fe51fae2904eccc830ac50eff3dcca4 Mon Sep 17 00:00:00 2001 From: Ryan Skraba Date: Tue, 2 Dec 2025 20:44:29 +0100 Subject: [PATCH] Revert "Avro 3876 jackson util (#2529)" This reverts commit 51851d49af3283cd31caecf6bdc7b3a4e973a5a6. --- .../java/org/apache/avro/io/JsonEncoder.java | 2 +- .../avro/util/internal/JacksonUtils.java | 26 ++------- .../org/apache/avro/TestSchemaBuilder.java | 57 +++++++++---------- .../org/apache/avro/io/TestBinaryDecoder.java | 25 -------- .../org/apache/avro/io/TestJsonDecoder.java | 26 --------- .../avro/util/internal/TestJacksonUtils.java | 36 +----------- 6 files changed, 38 insertions(+), 134 deletions(-) diff --git a/lang/java/avro/src/main/java/org/apache/avro/io/JsonEncoder.java b/lang/java/avro/src/main/java/org/apache/avro/io/JsonEncoder.java index 50f44c0afd4..4613f403d04 100644 --- a/lang/java/avro/src/main/java/org/apache/avro/io/JsonEncoder.java +++ b/lang/java/avro/src/main/java/org/apache/avro/io/JsonEncoder.java @@ -206,7 +206,7 @@ public void writeLong(long n) throws IOException { @Override public void writeFloat(float f) throws IOException { parser.advance(Symbol.FLOAT); - out.writeNumber(f + 0d); + out.writeNumber(f); } @Override diff --git a/lang/java/avro/src/main/java/org/apache/avro/util/internal/JacksonUtils.java b/lang/java/avro/src/main/java/org/apache/avro/util/internal/JacksonUtils.java index b0871fad96c..29593fba092 100644 --- a/lang/java/avro/src/main/java/org/apache/avro/util/internal/JacksonUtils.java +++ b/lang/java/avro/src/main/java/org/apache/avro/util/internal/JacksonUtils.java @@ -18,7 +18,6 @@ package org.apache.avro.util.internal; import java.io.IOException; -import java.io.UncheckedIOException; import java.math.BigDecimal; import java.math.BigInteger; import java.nio.charset.StandardCharsets; @@ -88,7 +87,7 @@ static void toJson(Object datum, JsonGenerator generator) throws IOException { } generator.writeEndArray(); } else if (datum instanceof byte[]) { // bytes, fixed - generator.writeBinary((byte[]) datum);// writeString(new String((byte[]) datum, StandardCharsets.ISO_8859_1)); + generator.writeString(new String((byte[]) datum, StandardCharsets.ISO_8859_1)); } else if (datum instanceof CharSequence || datum instanceof Enum) { // string, enum generator.writeString(datum.toString()); } else if (datum instanceof Double) { // double @@ -149,23 +148,10 @@ public static Object toObject(JsonNode jsonNode, Schema schema) { return jsonNode.asDouble(); } } else if (jsonNode.isDouble() || jsonNode.isFloat()) { - if (schema != null) { - if (schema.getType().equals(Schema.Type.DOUBLE)) { - return jsonNode.doubleValue(); - } else if (schema.getType().equals(Schema.Type.FLOAT)) { - return jsonNode.floatValue(); - } - } else if (jsonNode.isDouble()) { - return jsonNode.doubleValue(); - } else { - return jsonNode.floatValue(); - } - } else if (jsonNode.isBinary()) { - try { - return jsonNode.binaryValue(); - } catch (IOException ex) { - // only for TextNode, so, can't happen with binaryNode. - throw new UncheckedIOException(ex); + if (schema == null || schema.getType().equals(Schema.Type.DOUBLE)) { + return jsonNode.asDouble(); + } else if (schema.getType().equals(Schema.Type.FLOAT)) { + return (float) jsonNode.asDouble(); } } else if (jsonNode.isTextual()) { if (schema == null || schema.getType().equals(Schema.Type.STRING) || schema.getType().equals(Schema.Type.ENUM)) { @@ -201,7 +187,7 @@ public static Object toObject(JsonNode jsonNode, Schema schema) { /** * Convert an object into a map - * + * * @param datum The object * @return Its Map representation */ diff --git a/lang/java/avro/src/test/java/org/apache/avro/TestSchemaBuilder.java b/lang/java/avro/src/test/java/org/apache/avro/TestSchemaBuilder.java index fdb18d0f87c..86d76b5449d 100644 --- a/lang/java/avro/src/test/java/org/apache/avro/TestSchemaBuilder.java +++ b/lang/java/avro/src/test/java/org/apache/avro/TestSchemaBuilder.java @@ -23,7 +23,6 @@ import java.io.File; import java.io.IOException; import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -112,14 +111,14 @@ void objectProps() { assertTrue(s.getObjectProp("intProp") instanceof Integer); assertTrue(s.getObjectProp("longProp") instanceof Long); assertEquals(Long.MAX_VALUE, s.getObjectProp("longProp")); - assertTrue(s.getObjectProp("floatProp") instanceof Float); + assertTrue(s.getObjectProp("floatProp") instanceof Double); // float converts to double - assertEquals(1.0f, s.getObjectProp("floatProp")); + assertEquals(1.0d, s.getObjectProp("floatProp")); assertTrue(s.getObjectProp("doubleProp") instanceof Double); assertEquals(Double.MAX_VALUE, s.getObjectProp("doubleProp")); // byte[] converts to string - assertTrue(s.getObjectProp("byteProp") instanceof byte[]); - assertArrayEquals(new byte[] { 0x41, 0x42, 0x43 }, (byte[]) s.getObjectProp("byteProp")); + assertTrue(s.getObjectProp("byteProp") instanceof String); + assertEquals("ABC", s.getObjectProp("byteProp")); assertTrue(s.getObjectProp("stringProp") instanceof String); assertEquals("abc", s.getObjectProp("stringProp")); } @@ -142,14 +141,14 @@ void fieldObjectProps() { assertTrue(f.getObjectProp("intProp") instanceof Integer); assertTrue(f.getObjectProp("longProp") instanceof Long); assertEquals(Long.MAX_VALUE, f.getObjectProp("longProp")); - assertTrue(f.getObjectProp("floatProp") instanceof Float); + assertTrue(f.getObjectProp("floatProp") instanceof Double); // float converts to double - assertEquals(1.0f, f.getObjectProp("floatProp")); + assertEquals(1.0d, f.getObjectProp("floatProp")); assertTrue(f.getObjectProp("doubleProp") instanceof Double); assertEquals(Double.MAX_VALUE, f.getObjectProp("doubleProp")); // byte[] converts to string - assertTrue(f.getObjectProp("byteProp") instanceof byte[]); - assertArrayEquals(new byte[] { 0x41, 0x42, 0x43 }, (byte[]) f.getObjectProp("byteProp")); + assertTrue(f.getObjectProp("byteProp") instanceof String); + assertEquals("ABC", f.getObjectProp("byteProp")); assertTrue(f.getObjectProp("stringProp") instanceof String); assertEquals("abc", f.getObjectProp("stringProp")); @@ -181,11 +180,11 @@ void arrayObjectProp() { assertEquals(true, iter.next()); assertEquals(Integer.MAX_VALUE, iter.next()); assertEquals(Long.MAX_VALUE, iter.next()); - - assertEquals(1.0f, iter.next()); + // float converts to double + assertEquals(1.0d, iter.next()); assertEquals(Double.MAX_VALUE, iter.next()); - - assertArrayEquals(new byte[] { 0x41, 0x42, 0x43 }, (byte[]) iter.next()); + // byte[] converts to string + assertEquals("ABC", iter.next()); assertEquals("abc", iter.next()); } @@ -216,11 +215,11 @@ void fieldArrayObjectProp() { assertEquals(true, iter.next()); assertEquals(Integer.MAX_VALUE, iter.next()); assertEquals(Long.MAX_VALUE, iter.next()); - - assertEquals(1.0f, iter.next()); + // float converts to double + assertEquals(1.0d, iter.next()); assertEquals(Double.MAX_VALUE, iter.next()); - - assertArrayEquals(new byte[] { 0x41, 0x42, 0x43 }, (byte[]) iter.next()); + // byte[] converts to string + assertEquals("ABC", iter.next()); assertEquals("abc", iter.next()); } @@ -249,14 +248,14 @@ void mapObjectProp() { assertEquals(Integer.MAX_VALUE, valueMap.get("intKey")); assertTrue(valueMap.get("longKey") instanceof Long); assertEquals(Long.MAX_VALUE, valueMap.get("longKey")); - - assertTrue(valueMap.get("floatKey") instanceof Float); - assertEquals(1.0f, valueMap.get("floatKey")); + // float converts to double + assertTrue(valueMap.get("floatKey") instanceof Double); + assertEquals(1.0d, valueMap.get("floatKey")); assertTrue(valueMap.get("doubleKey") instanceof Double); assertEquals(Double.MAX_VALUE, valueMap.get("doubleKey")); - - assertTrue(valueMap.get("byteKey") instanceof byte[]); - assertArrayEquals("ABC".getBytes(StandardCharsets.UTF_8), (byte[]) valueMap.get("byteKey")); + // byte[] converts to string + assertTrue(valueMap.get("byteKey") instanceof String); + assertEquals("ABC", valueMap.get("byteKey")); assertTrue(valueMap.get("stringKey") instanceof String); assertEquals("abc", valueMap.get("stringKey")); } @@ -289,14 +288,14 @@ void fieldMapObjectProp() { assertEquals(Integer.MAX_VALUE, valueMap.get("intKey")); assertTrue(valueMap.get("longKey") instanceof Long); assertEquals(Long.MAX_VALUE, valueMap.get("longKey")); - - assertTrue(valueMap.get("floatKey") instanceof Float); - assertEquals(1.0f, valueMap.get("floatKey")); + // float converts to double + assertTrue(valueMap.get("floatKey") instanceof Double); + assertEquals(1.0d, valueMap.get("floatKey")); assertTrue(valueMap.get("doubleKey") instanceof Double); assertEquals(Double.MAX_VALUE, valueMap.get("doubleKey")); - - assertTrue(valueMap.get("byteKey") instanceof byte[]); - assertEquals("ABC", new String((byte[]) valueMap.get("byteKey"))); + // byte[] converts to string + assertTrue(valueMap.get("byteKey") instanceof String); + assertEquals("ABC", valueMap.get("byteKey")); assertTrue(valueMap.get("stringKey") instanceof String); assertEquals("abc", valueMap.get("stringKey")); } diff --git a/lang/java/avro/src/test/java/org/apache/avro/io/TestBinaryDecoder.java b/lang/java/avro/src/test/java/org/apache/avro/io/TestBinaryDecoder.java index b9437bd8a0e..491151b849e 100644 --- a/lang/java/avro/src/test/java/org/apache/avro/io/TestBinaryDecoder.java +++ b/lang/java/avro/src/test/java/org/apache/avro/io/TestBinaryDecoder.java @@ -20,10 +20,8 @@ import org.apache.avro.AvroRuntimeException; import org.apache.avro.Schema; import org.apache.avro.SystemLimitException; -import org.apache.avro.generic.GenericData; import org.apache.avro.generic.GenericDatumReader; import org.apache.avro.generic.GenericDatumWriter; -import org.apache.avro.generic.GenericRecord; import org.apache.avro.util.ByteBufferInputStream; import org.apache.avro.util.ByteBufferOutputStream; import org.apache.avro.util.RandomData; @@ -45,7 +43,6 @@ import java.util.Arrays; import static org.apache.avro.TestSystemLimitException.*; -import static org.junit.jupiter.api.Assertions.assertEquals; public class TestBinaryDecoder { // prime number buffer size so that looping tests hit the buffer edge @@ -686,26 +683,4 @@ void eof(boolean useDirect) throws IOException { Assertions.assertThrows(EOFException.class, () -> d.readInt()); } - @Test - void testFloatPrecision() throws Exception { - String def = "{\"type\":\"record\",\"name\":\"X\",\"fields\":" + "[{\"type\":\"float\",\"name\":\"n\"}]}"; - Schema schema = new Schema.Parser().parse(def); - DatumReader reader = new GenericDatumReader<>(schema); - - float value = 33.33000183105469f; - - GenericData.Record record = new GenericData.Record(schema); - record.put(0, value); - ByteArrayOutputStream out = new ByteArrayOutputStream(); - Encoder encoder = EncoderFactory.get().directBinaryEncoder(out, null); - - DatumWriter writer = new GenericDatumWriter<>(schema); - writer.write(record, encoder); - encoder.flush(); - - Decoder decoder = DecoderFactory.get().directBinaryDecoder(new ByteArrayInputStream(out.toByteArray()), null); - GenericRecord r = reader.read(null, decoder); - assertEquals(value + 0d, ((float) r.get("n")) + 0d); - } - } diff --git a/lang/java/avro/src/test/java/org/apache/avro/io/TestJsonDecoder.java b/lang/java/avro/src/test/java/org/apache/avro/io/TestJsonDecoder.java index 1f44344e3aa..05057139600 100644 --- a/lang/java/avro/src/test/java/org/apache/avro/io/TestJsonDecoder.java +++ b/lang/java/avro/src/test/java/org/apache/avro/io/TestJsonDecoder.java @@ -22,15 +22,12 @@ import org.apache.avro.AvroTypeException; import org.apache.avro.Schema; import org.apache.avro.SchemaBuilder; -import org.apache.avro.generic.GenericData; import org.apache.avro.generic.GenericDatumReader; -import org.apache.avro.generic.GenericDatumWriter; import org.apache.avro.generic.GenericRecord; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import java.io.ByteArrayOutputStream; import java.io.IOException; public class TestJsonDecoder { @@ -69,29 +66,6 @@ private void checkNumeric(String type, Object value) throws Exception { } } - @Test - void testFloatPrecision() throws Exception { - String def = "{\"type\":\"record\",\"name\":\"X\",\"fields\":" + "[{\"type\":\"float\",\"name\":\"n\"}]}"; - Schema schema = new Schema.Parser().parse(def); - DatumReader reader = new GenericDatumReader<>(schema); - - float value = 33.33000183105469f; - GenericData.Record record = new GenericData.Record(schema); - record.put(0, value); - ByteArrayOutputStream out = new ByteArrayOutputStream(); - JsonEncoder encoder = EncoderFactory.get().jsonEncoder(schema, out); - - DatumWriter writer = new GenericDatumWriter<>(schema); - writer.write(record, encoder); - encoder.flush(); - // check the whole float precision is kept. - assertEquals("{\"n\":33.33000183105469}", out.toString()); - - Decoder decoder = DecoderFactory.get().jsonDecoder(schema, out.toString()); - GenericRecord r = reader.read(null, decoder); - assertEquals(value + 0d, ((float) r.get("n")) + 0d); - } - // Ensure that even if the order of fields in JSON is different from the order // in schema, // it works. diff --git a/lang/java/avro/src/test/java/org/apache/avro/util/internal/TestJacksonUtils.java b/lang/java/avro/src/test/java/org/apache/avro/util/internal/TestJacksonUtils.java index 4a272ae5b35..cd6fe3f74da 100644 --- a/lang/java/avro/src/test/java/org/apache/avro/util/internal/TestJacksonUtils.java +++ b/lang/java/avro/src/test/java/org/apache/avro/util/internal/TestJacksonUtils.java @@ -21,10 +21,8 @@ import static org.apache.avro.util.internal.JacksonUtils.toObject; import static org.junit.jupiter.api.Assertions.*; -import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.BigIntegerNode; -import com.fasterxml.jackson.databind.node.BinaryNode; import com.fasterxml.jackson.databind.node.BooleanNode; import com.fasterxml.jackson.databind.node.DecimalNode; import com.fasterxml.jackson.databind.node.DoubleNode; @@ -33,24 +31,15 @@ import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.LongNode; import com.fasterxml.jackson.databind.node.NullNode; -import com.fasterxml.jackson.databind.node.NumericNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.TextNode; import java.math.BigDecimal; import java.math.BigInteger; -import java.nio.charset.StandardCharsets; import java.util.Collections; -import java.util.stream.Stream; - import org.apache.avro.JsonProperties; import org.apache.avro.Schema; import org.apache.avro.SchemaBuilder; - -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; public class TestJacksonUtils { @@ -66,9 +55,8 @@ void testToJsonNode() { assertEquals(IntNode.valueOf(1), toJsonNode(1)); assertEquals(LongNode.valueOf(2), toJsonNode(2L)); assertEquals(FloatNode.valueOf(1.0f), toJsonNode(1.0f)); - assertEquals(FloatNode.valueOf(33.33000183105469f), toJsonNode(33.33000183105469f)); - assertEquals(DoubleNode.valueOf(2.0), toJsonNode(2.0d)); - assertEquals(BinaryNode.valueOf(new byte[] { 1, 2 }), toJsonNode(new byte[] { 1, 2 })); + assertEquals(DoubleNode.valueOf(2.0), toJsonNode(2.0)); + assertEquals(TextNode.valueOf("\u0001\u0002"), toJsonNode(new byte[] { 1, 2 })); assertEquals(TextNode.valueOf("a"), toJsonNode("a")); assertEquals(TextNode.valueOf("UP"), toJsonNode(Direction.UP)); assertEquals(BigIntegerNode.valueOf(BigInteger.ONE), toJsonNode(BigInteger.ONE)); @@ -92,7 +80,7 @@ void testToObject() { assertEquals(2L, toObject(IntNode.valueOf(2), Schema.create(Schema.Type.LONG))); assertEquals(1.0f, toObject(DoubleNode.valueOf(1.0), Schema.create(Schema.Type.FLOAT))); assertEquals(2.0, toObject(DoubleNode.valueOf(2.0))); - assertEquals(BinaryNode.valueOf(new byte[] { 1, 2 }), toJsonNode(new byte[] { 1, 2 })); + assertEquals(TextNode.valueOf("\u0001\u0002"), toJsonNode(new byte[] { 1, 2 })); assertArrayEquals(new byte[] { 1, 2 }, (byte[]) toObject(TextNode.valueOf("\u0001\u0002"), Schema.create(Schema.Type.BYTES))); assertEquals("a", toObject(TextNode.valueOf("a"))); @@ -114,22 +102,4 @@ void testToObject() { assertEquals("a", toObject(TextNode.valueOf("a"), SchemaBuilder.unionOf().stringType().and().intType().endUnion())); } - @ParameterizedTest - @MethodSource("nodes") - void cycle(JsonNode input) { - Object object = JacksonUtils.toObject(input); - JsonNode node = JacksonUtils.toJsonNode(object); - Assertions.assertEquals(input, node); - } - - public static Stream nodes() { - ObjectNode o1 = JsonNodeFactory.instance.objectNode(); - o1.put("intField", 123); - o1.put("floatField", 33.33000183105469f); - o1.put("doubleField", 33.33000183105469245d); - return Stream.of(JsonNodeFactory.instance.numberNode(33.33000183105469f), - JsonNodeFactory.instance.binaryNode("Hello".getBytes(StandardCharsets.ISO_8859_1)), - JsonNodeFactory.instance.arrayNode().add(1).add("Hello").add(o1)).map(Arguments::of); - } - }