I wrote below program to convert Parameter
to JsonNode
. Getting NumberFormatException
when I set 3.9E38
. How to set BigDecimal
in JsonNode?
public class JsonCheck {
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper om = new ObjectMapper();
Parameter p = new Parameter();
p.setPrevValue(new BigDecimal("3.9E38"));
JsonNode node = om.convertValue(p,JsonNode.class);
System.out.println(node);
}
public static class DefaultValueSerializer extends JsonSerializer<BigDecimal> {
@Override
public void serialize(BigDecimal o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeNumber(o.toPlainString());
}
}
public static class Parameter {
@JsonSerialize(using = DefaultValueSerializer.class)
private BigDecimal prevValue;
public void setPrevValue(BigDecimal prevValue) {
this.prevValue = prevValue;
}
public BigDecimal getPrevValue() {
return prevValue;
}
}
}
It looks like this because com.fasterxml.jackson.core.JsonParser
implementation used during deserialization (in your case conversion) process can not parse really big numbers. By default, number is treated as Long
and value 3.9E38
exceeds it's range. Unfortunately, features USE_BIG_DECIMAL_FOR_FLOATS and USE_BIG_INTEGER_FOR_INTS are not handled in this case and we need to write customization here. See below example:
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.util.JsonParserDelegate;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.deser.std.JsonNodeDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import java.io.IOException;
import java.math.BigDecimal;
public class JsonApp {
public static void main(String[] args) {
Parameter parameter = new Parameter();
parameter.setPrevValue(new BigDecimal("3.9E38"));
SimpleModule module = new SimpleModule();
module.addDeserializer(JsonNode.class, new BigDecimalFirstJsonNodeDeserializer());
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(module);
JsonNode node = mapper.convertValue(parameter, JsonNode.class);
System.out.println(node);
}
}
class BigDecimalFirstJsonNodeDeserializer extends JsonNodeDeserializer {
@Override
public JsonNode deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
return super.deserialize(new BigDecimalJsonParser(p), ctxt);
}
}
class BigDecimalJsonParser extends JsonParserDelegate {
public BigDecimalJsonParser(JsonParser parser) {
super(parser);
}
@Override
public NumberType getNumberType() {
return NumberType.BIG_DECIMAL;
}
@Override
public BigDecimal getDecimalValue() throws IOException {
String value = getText();
return new BigDecimal(value);
}
}
class BigDecimalPlainStringJsonSerializer extends JsonSerializer<BigDecimal> {
@Override
public void serialize(BigDecimal o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeNumber(o.toPlainString());
}
}
class Parameter {
@JsonSerialize(using = BigDecimalPlainStringJsonSerializer.class)
private BigDecimal prevValue;
public void setPrevValue(BigDecimal prevValue) {
this.prevValue = prevValue;
}
public BigDecimal getPrevValue() {
return prevValue;
}
}
Above code prints:
{"prevValue":3.9E+38}