【问题标题】:Big number deserialisation throws NumberFormatException大数字反序列化抛出 NumberFormatException
【发布时间】:2020-04-01 21:05:43
【问题描述】:

我编写了下面的程序来将Parameter 转换为JsonNode。当我设置3.9E38 时得到NumberFormatException。如何在 JsonNode 中设置BigDecimal

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;
        }
    }
}

【问题讨论】:

  • @michalk,更新了代码示例。需要将数字转换为non scientific 格式。所以使用o.toPlainString()
  • BigDecimal 不需要自定义 Jackson 序列化程序。

标签: java json java-8 jackson jackson-databind


【解决方案1】:

看起来像这样,因为在反序列化(在您的情况下是转换)过程中使用的 com.fasterxml.jackson.core.JsonParser 实现无法解析非常大的数字。默认情况下,数字被视为Long 并且值3.9E38 超出了它的范围。不幸的是,USE_BIG_DECIMAL_FOR_FLOATSUSE_BIG_INTEGER_FOR_INTS 功能在这种情况下没有被处理,我们需要在这里编写自定义。见下例:

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;
    }
}

上面的代码打印:

{"prevValue":3.9E+38}

【讨论】:

    猜你喜欢
    • 2020-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-29
    • 2020-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多