Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add MessagePackMapper#handleBigDecimalAsString #745

Merged
merged 2 commits into from
Jul 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
}
}