Skip to content

Commit

Permalink
Add MessagePackMapper#handleBigDecimalAsString (#745)
Browse files Browse the repository at this point in the history
  • Loading branch information
komamitsu authored Jul 10, 2023
1 parent 4b38954 commit 9586366
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 10 deletions.
32 changes: 22 additions & 10 deletions msgpack-jackson/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,13 @@ Only thing you need to do is to instantiate `MessagePackFactory` and pass it to
Or more easily:

```java
ObjectMapper objectMapper = new MessagePackMapper();
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.

```java
ObjectMapper objectMapper = new MessagePackMapper().handleBigDecimalAsString();
```

### Serialization/Deserialization of List
Expand Down Expand Up @@ -226,26 +232,33 @@ 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. When you want to handle BigDeciaml values as str type with arbitrary precision in MessagePack format, you can use `com.fasterxml.jackson.databind.cfg.MutableConfigOverride#setFormat` like this:
`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.

```java
ObjectMapper mapper = new ObjectMapper(new MessagePackFactory());
mapper.configOverride(BigDecimal.class).setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.STRING));
ObjectMapper objectMapper = new MessagePackMapper().handleBigDecimalAsString();

Pojo obj = new Pojo();
// This value is too large to be serialized as double
obj.value = new BigDecimal("1234567890.98765432100");

byte[] converted = mapper.writeValueAsBytes(obj);
byte[] converted = objectMapper.writeValueAsBytes(obj);

System.out.println(objectMapper.readValue(converted, Pojo.class)); // => Pojo{value=1234567890.98765432100}
```
`MessagePackMapper#handleBigDecimalAsString()` is equivalent to the following configuration.

System.out.println(mapper.readValue(converted, Pojo.class)); // => Pojo{value=1234567890.98765432100}
```java
ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
objectMapper.configOverride(BigDecimal.class).setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.STRING));
```


### Serialize and deserialize Instant instances as MessagePack extension type

`timestamp` extension type is defined in MessagePack as type:-1. Registering `TimestampExtensionModule.INSTANCE` module enables automatic serialization and deserialization of java.time.Instant to/from the MessagePack extension type.

```java
ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory())
ObjectMapper objectMapper = new MessagePackMapper()
.registerModule(TimestampExtensionModule.INSTANCE);
Pojo pojo = new Pojo();
// The type of `timestamp` variable is Instant
Expand Down Expand Up @@ -287,8 +300,8 @@ When you want to use non-String value as a key of Map, use `MessagePackKeySerial
return "Java";
}
return "Not Java";
}
);
});

ObjectMapper objectMapper = new ObjectMapper(
new MessagePackFactory().setExtTypeCustomDesers(extTypeCustomDesers));

Expand Down Expand Up @@ -476,4 +489,3 @@ There are a few options to fix this issue, but they introduce performance degred
ObjectMapper objectMapper = new ObjectMapper(
new MessagePackFactory().setReuseResourceInGenerator(false));
```

Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@
//
package org.msgpack.jackson.dataformat;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.cfg.MapperBuilder;

import java.math.BigDecimal;

public class MessagePackMapper extends ObjectMapper
{
private static final long serialVersionUID = 3L;
Expand All @@ -40,6 +43,12 @@ public MessagePackMapper(MessagePackFactory f)
super(f);
}

public MessagePackMapper handleBigDecimalAsString()
{
configOverride(BigDecimal.class).setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.STRING));
return this;
}

public static Builder builder()
{
return new Builder(new MessagePackMapper());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//
// MessagePack for Java
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack.jackson.dataformat;

import org.junit.Test;

import java.io.IOException;
import java.math.BigDecimal;

import static org.junit.Assert.assertEquals;

public class MessagePackMapperTest
{
static class Pojo
{
public BigDecimal value;
}

@Test
public void handleBigDecimalAsString() throws IOException
{
MessagePackMapper mapper = new MessagePackMapper().handleBigDecimalAsString();
Pojo obj = new Pojo();
obj.value = new BigDecimal("1234567890.98765432100");

byte[] converted = mapper.writeValueAsBytes(obj);

Pojo deserialized = mapper.readValue(converted, Pojo.class);
assertEquals(obj.value, deserialized.value);
}
}

0 comments on commit 9586366

Please sign in to comment.