diff --git a/msgpack-jackson/README.md b/msgpack-jackson/README.md index e91c6f8b..0156453e 100644 --- a/msgpack-jackson/README.md +++ b/msgpack-jackson/README.md @@ -64,10 +64,10 @@ Or more easily: ObjectMapper objectMapper = new MessagePackMapper(); ``` -We strongly recommend to call `MessagePackMapper#handleBigDecimalAsString()` if you serialize and/or deserialize BigDecimal values. See [Serialize and deserialize BigDecimal as str type internally in MessagePack format](#serialize-and-deserialize-bigdecimal-as-str-type-internally-in-messagepack-format) for details. +We strongly recommend to call `MessagePackMapper#handleBigIntegerAndBigDecimalAsString()` if you serialize and/or deserialize BigInteger/BigDecimal values. See [Serialize and deserialize BigDecimal as str type internally in MessagePack format](#serialize-and-deserialize-bigdecimal-as-str-type-internally-in-messagepack-format) for details. ```java - ObjectMapper objectMapper = new MessagePackMapper().handleBigDecimalAsString(); + ObjectMapper objectMapper = new MessagePackMapper().handleBigIntegerAndBigDecimalAsString(); ``` ### Serialization/Deserialization of List @@ -232,10 +232,10 @@ When you want to use non-String value as a key of Map, use `MessagePackKeySerial ### Serialize and deserialize BigDecimal as str type internally in MessagePack format -`jackson-dataformat-msgpack` represents BigDecimal values as float type in MessagePack format by default for backward compatibility. But the default behavior could fail when handling too large value for `double` type. So we strongly recommend to call `MessagePackMapper#handleBigDecimalAsString()` to internally handle BigDecimal values as String. +`jackson-dataformat-msgpack` represents BigDecimal values as float type in MessagePack format by default for backward compatibility. But the default behavior could fail when handling too large value for `double` type. So we strongly recommend to call `MessagePackMapper#handleBigIntegerAndBigDecimalAsString()` to internally handle BigDecimal values as String. ```java - ObjectMapper objectMapper = new MessagePackMapper().handleBigDecimalAsString(); + ObjectMapper objectMapper = new MessagePackMapper().handleBigIntegerAndBigDecimalAsString(); Pojo obj = new Pojo(); // This value is too large to be serialized as double @@ -245,10 +245,11 @@ When you want to use non-String value as a key of Map, use `MessagePackKeySerial System.out.println(objectMapper.readValue(converted, Pojo.class)); // => Pojo{value=1234567890.98765432100} ``` -`MessagePackMapper#handleBigDecimalAsString()` is equivalent to the following configuration. +`MessagePackMapper#handleBigIntegerAndDecimalAsString()` is equivalent to the following configuration. ```java ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory()); + objectMapper.configOverride(BigInteger.class).setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.STRING)); objectMapper.configOverride(BigDecimal.class).setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.STRING)); ``` diff --git a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackMapper.java b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackMapper.java index 52af0372..144c8d1a 100644 --- a/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackMapper.java +++ b/msgpack-jackson/src/main/java/org/msgpack/jackson/dataformat/MessagePackMapper.java @@ -20,6 +20,7 @@ import com.fasterxml.jackson.databind.cfg.MapperBuilder; import java.math.BigDecimal; +import java.math.BigInteger; public class MessagePackMapper extends ObjectMapper { @@ -43,12 +44,23 @@ public MessagePackMapper(MessagePackFactory f) super(f); } + public MessagePackMapper handleBigIntegerAsString() + { + configOverride(BigInteger.class).setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.STRING)); + return this; + } + public MessagePackMapper handleBigDecimalAsString() { configOverride(BigDecimal.class).setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.STRING)); return this; } + public MessagePackMapper handleBigIntegerAndBigDecimalAsString() + { + return handleBigIntegerAsString().handleBigDecimalAsString(); + } + public static Builder builder() { return new Builder(new MessagePackMapper()); diff --git a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackMapperTest.java b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackMapperTest.java index 6dfd41cf..68721fce 100644 --- a/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackMapperTest.java +++ b/msgpack-jackson/src/test/java/org/msgpack/jackson/dataformat/MessagePackMapperTest.java @@ -15,30 +15,97 @@ // package org.msgpack.jackson.dataformat; +import com.fasterxml.jackson.core.JsonProcessingException; import org.junit.Test; import java.io.IOException; import java.math.BigDecimal; +import java.math.BigInteger; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; public class MessagePackMapperTest { - static class Pojo + static class PojoWithBigInteger + { + public BigInteger value; + } + + static class PojoWithBigDecimal { public BigDecimal value; } - @Test - public void handleBigDecimalAsString() throws IOException + private void shouldFailToHandleBigInteger(MessagePackMapper messagePackMapper) throws JsonProcessingException + { + PojoWithBigInteger obj = new PojoWithBigInteger(); + obj.value = BigInteger.valueOf(Long.MAX_VALUE).multiply(BigInteger.valueOf(10)); + + try { + messagePackMapper.writeValueAsBytes(obj); + fail(); + } + catch (IllegalArgumentException e) { + // Expected + } + } + + private void shouldSuccessToHandleBigInteger(MessagePackMapper messagePackMapper) throws IOException { - MessagePackMapper mapper = new MessagePackMapper().handleBigDecimalAsString(); - Pojo obj = new Pojo(); + PojoWithBigInteger obj = new PojoWithBigInteger(); + obj.value = BigInteger.valueOf(Long.MAX_VALUE).multiply(BigInteger.valueOf(10)); + + byte[] converted = messagePackMapper.writeValueAsBytes(obj); + + PojoWithBigInteger deserialized = messagePackMapper.readValue(converted, PojoWithBigInteger.class); + assertEquals(obj.value, deserialized.value); + } + + private void shouldFailToHandleBigDecimal(MessagePackMapper messagePackMapper) throws JsonProcessingException + { + PojoWithBigDecimal obj = new PojoWithBigDecimal(); obj.value = new BigDecimal("1234567890.98765432100"); - byte[] converted = mapper.writeValueAsBytes(obj); + try { + messagePackMapper.writeValueAsBytes(obj); + fail(); + } + catch (IllegalArgumentException e) { + // Expected + } + } - Pojo deserialized = mapper.readValue(converted, Pojo.class); + private void shouldSuccessToHandleBigDecimal(MessagePackMapper messagePackMapper) throws IOException + { + PojoWithBigDecimal obj = new PojoWithBigDecimal(); + obj.value = new BigDecimal("1234567890.98765432100"); + + byte[] converted = messagePackMapper.writeValueAsBytes(obj); + + PojoWithBigDecimal deserialized = messagePackMapper.readValue(converted, PojoWithBigDecimal.class); assertEquals(obj.value, deserialized.value); } + + @Test + public void handleBigIntegerAsString() throws IOException + { + shouldFailToHandleBigInteger(new MessagePackMapper()); + shouldSuccessToHandleBigInteger(new MessagePackMapper().handleBigIntegerAsString()); + } + + @Test + public void handleBigDecimalAsString() throws IOException + { + shouldFailToHandleBigDecimal(new MessagePackMapper()); + shouldSuccessToHandleBigDecimal(new MessagePackMapper().handleBigDecimalAsString()); + } + + @Test + public void handleBigIntegerAndBigDecimalAsString() throws IOException + { + MessagePackMapper messagePackMapper = new MessagePackMapper().handleBigIntegerAndBigDecimalAsString(); + shouldSuccessToHandleBigInteger(messagePackMapper); + shouldSuccessToHandleBigDecimal(messagePackMapper); + } }