diff --git a/logstash-core/src/main/java/org/logstash/ObjectMappers.java b/logstash-core/src/main/java/org/logstash/ObjectMappers.java index 525d02d05..1a8f1dafc 100644 --- a/logstash-core/src/main/java/org/logstash/ObjectMappers.java +++ b/logstash-core/src/main/java/org/logstash/ObjectMappers.java @@ -15,6 +15,7 @@ import com.fasterxml.jackson.dataformat.cbor.CBORFactory; import com.fasterxml.jackson.dataformat.cbor.CBORGenerator; import java.io.IOException; import java.math.BigDecimal; +import java.math.BigInteger; import java.util.HashMap; import org.jruby.RubyBignum; import org.jruby.RubyBoolean; @@ -41,8 +42,6 @@ public final class ObjectMappers { private static final SimpleModule CBOR_DESERIALIZERS = new SimpleModule("CborRubyDeserializers") - .addDeserializer(RubyBigDecimal.class, new RubyBigDecimalDeserializer()) - .addDeserializer(RubyBignum.class, new RubyBignumDeserializer()) .addDeserializer(RubyNil.class, new RubyNilDeserializer()); public static final ObjectMapper JSON_MAPPER = @@ -195,79 +194,35 @@ public final class ObjectMappers { /** * Serializer for {@link RubyBignum} since Jackson can't handle that type natively, so we - * simply serialize it as if it were a {@code String} and wrap it in type arguments, so that - * deserialization happens via {@link ObjectMappers.RubyBignumDeserializer}. + * simply serialize it as if it were a {@link BigInteger}. */ - private static final class RubyBignumSerializer extends StdSerializer { + private static final class RubyBignumSerializer extends NonTypedScalarSerializerBase { RubyBignumSerializer() { - super(RubyBignum.class); + super(RubyBignum.class, true); } @Override public void serialize(final RubyBignum value, final JsonGenerator jgen, final SerializerProvider provider) throws IOException { - jgen.writeString(value.toString()); - } - - @Override - public void serializeWithType(final RubyBignum value, final JsonGenerator jgen, - final SerializerProvider serializers, final TypeSerializer typeSer) throws IOException { - typeSer.writeTypePrefixForScalar(value, jgen, RubyBignum.class); - jgen.writeString(value.toString()); - typeSer.writeTypeSuffixForScalar(value, jgen); - } - } - - private static final class RubyBignumDeserializer extends StdDeserializer { - - RubyBignumDeserializer() { - super(RubyBignum.class); - } - - @Override - public RubyBignum deserialize(final JsonParser p, final DeserializationContext ctxt) - throws IOException { - return RubyBignum.newBignum(RubyUtil.RUBY, p.getText()); + jgen.writeNumber(value.getBigIntegerValue()); } } /** - * Serializer for {@link RubyBigDecimal} since Jackson can't handle that type natively, so we - * simply serialize it as if it were a {@code String} and wrap it in type arguments, so that - * deserialization happens via {@link ObjectMappers.RubyBigDecimalDeserializer}. + * Serializer for {@link BigDecimal} since Jackson can't handle that type natively, so we + * simply serialize it as if it were a {@link BigDecimal}. */ - private static final class RubyBigDecimalSerializer extends StdSerializer { + private static final class RubyBigDecimalSerializer extends NonTypedScalarSerializerBase { RubyBigDecimalSerializer() { - super(RubyBigDecimal.class); + super(RubyBigDecimal.class, true); } @Override public void serialize(final RubyBigDecimal value, final JsonGenerator jgen, final SerializerProvider provider) throws IOException { - jgen.writeString(value.getBigDecimalValue().toString()); - } - - @Override - public void serializeWithType(final RubyBigDecimal value, final JsonGenerator jgen, - final SerializerProvider serializers, final TypeSerializer typeSer) throws IOException { - typeSer.writeTypePrefixForScalar(value, jgen, RubyBigDecimal.class); - jgen.writeString(value.getBigDecimalValue().toString()); - typeSer.writeTypeSuffixForScalar(value, jgen); - } - } - - private static final class RubyBigDecimalDeserializer extends StdDeserializer { - - RubyBigDecimalDeserializer() { - super(RubyBigDecimal.class); - } - - @Override - public RubyBigDecimal deserialize(final JsonParser p, final DeserializationContext ctxt) - throws IOException { - return new RubyBigDecimal(RubyUtil.RUBY, new BigDecimal(p.getText())); + jgen.writeNumber(value.getBigDecimalValue()); } } diff --git a/logstash-core/src/test/java/org/logstash/EventTest.java b/logstash-core/src/test/java/org/logstash/EventTest.java index c2b90ab46..b9b762a67 100644 --- a/logstash-core/src/test/java/org/logstash/EventTest.java +++ b/logstash-core/src/test/java/org/logstash/EventTest.java @@ -84,6 +84,22 @@ public final class EventTest { assertEquals(e.getTimestamp().toString(), er.getTimestamp().toString()); } + /** + * Test for proper BigInteger and BigDecimal serialization + * related to Jackson/CBOR issue https://github.com/elastic/logstash/issues/8379 + */ + @Test + public void bigNumsBinaryRoundtrip() throws Exception { + final Event e = new Event(); + final BigInteger bi = new BigInteger("9223372036854776000"); + final BigDecimal bd = new BigDecimal("9223372036854776001.99"); + e.setField("bi", bi); + e.setField("bd", bd); + final Event deserialized = Event.deserialize(e.serialize()); + assertEquals(bi, deserialized.getField("bi")); + assertEquals(bd, deserialized.getField("bd")); + } + @Test public void testBareToJson() throws Exception { Event e = new Event();