大数反序列化引发NumberFormatException

时间:2019-12-08 16:22:51

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

我在下面编写了将Parameter转换为JsonNode的程序。设置NumberFormatException时得到3.9E38。如何在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;
        }
    }
}

1 个答案:

答案 0 :(得分:1)

之所以这样,是因为在反序列化(在您的情况下为转换)过程中使用的addWeighted实现无法解析很大的数字。默认情况下,数字被视为com.fasterxml.jackson.core.JsonParser,而值Long超出了它的范围。不幸的是,在这种情况下无法处理功能USE_BIG_DECIMAL_FOR_FLOATSUSE_BIG_INTEGER_FOR_INTS,因此我们需要在此处编写自定义项。参见以下示例:

3.9E38

上面的代码显示:

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