如何避免用科学计数法表示的双精度数和数字从字符串转换为数字?

我收到JSON有效载荷,它是一组键值对。值可以是字符串或数字。我必须解析JSON并将键值对存储到适当的varchar2列中。我应该完全按照输入的有效载荷中输入的号码来保存输入的 。 但是对于像1.1E40.00000000000003之类的数字和类似的数字,我得到的是11000.03.0E-14

这是一种禁用/阻止数字转换而只使用字符串表示的方法吗?

我使用FasterXML Jackson实现。 顺便说一句,没有可用的实际文档-我发现的所有来源都指向http://wiki.fasterxml.com/JacksonHome,该文档现在不可用。 我在这里发现了两个类似的问题 Jackson JSON converts integers into strings Disable the Number to String automatic conversion in jackson 但是遇到数字时都需要例外,这不是我的情况。我尝试了建议的解决方案,但未能成功修改它们以适合我的任务。

也没有答案 https://github.com/FasterXML/jackson-databind/issues/796

现在,除了键值对之外,我没有输入字符串的规范。所以只是一个例子:

可能会收到类似的消息:

{"a":"text","b":"35","c":{"d":"another"},"e":["array",35],"f":1.1E4,"g":0.00000000000003}

我想要字符串对

"a" -> "text","b" -> "35","c" -> "{\"d\":\"another\"}","e" -> "[\"array\",35]","f" -> "1.1E4" 

最简单的转换方式是:

public void test() throws IOException {
    Map map = new ObjectMapper().readValue(
    "{\"a\":\"text\",\"b\":\"35\",\"c\":{\"d\":\"another\"},\"e\":[\"array\",\"f\":1.1E4,\"g\":0.00000000000003}",Map.class);
    System.out.println(map);
}

结果:

{a=text,b=35,c={d=another},e=[array,f=11000.0,g=3.0E-14}

更准确的方法:

public class JsonUtil2 {

    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    public static Map<String,String> parse(String json) throws IOException {
        ObjectNode objectNode = (ObjectNode) OBJECT_MAPPER.readTree(json);

        Map<String,String> result = new HashMap<>(objectNode.size());
        objectNode.fields().forEachRemaining(entry -> result.put(entry.getKey(),toJson(entry.getvalue())));
        return result;
    }

    private static String toJson(JsonNode jsonNode) {
        if (jsonNode.isnumber()) {
            if (jsonNode instanceof DoubleNode || jsonNode instanceof FloatNode) {
                DecimalFormatSymbols dfs = new DecimalFormatSymbols();
                dfs.setDecimalSeparator('.');
                dfs.setMinusSign('-');
                DecimalFormat df = new DecimalFormat("#.#",dfs);
                df.setMaximumFractionDigits(32);
                df.setMaximumIntegerDigits(32);
                return df.format(jsonNode.doubleValue());
            } else {
                return jsonNode.asText();
            }
        } else if (jsonNode.isValueNode()) {
            return jsonNode.asText();
        } else {
            try {
                return OBJECT_MAPPER.writeValueAsString(jsonNode);
            } catch (JsonProcessingException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

结果为:

{a=text,c={"d":"another"},e=["array",f=11000,g=0.00000000000003}

这要好得多,但在f=11000而非f=1.1E4上还是有所不同。

dsfvdkjdfg4ah94njknh 回答:如何避免用科学计数法表示的双精度数和数字从字符串转换为数字?

在您的情况下,您希望将所有内容都视为String,因此需要一个自定义反序列化程序,该程序将JSON ObjectJSON Array读为String。我们也可以通过使用Jackson提供此信息来强制Map<String,String>阅读TypeFactory

假设我们的JSON有效载荷如下所示:

{
  "a": "text","b": "35","c": {
    "d": "another","dd":3.44E3
  },"e": [
    "array",35,2.3E5
  ],"f": 1.1E4,"g": 0.00000000000003
}

示例代码:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.std.StringDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.type.CollectionType;
import com.fasterxml.jackson.databind.type.MapType;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class JsonTreeApp {

    public static void main(String[] args) throws Exception {
        File jsonFile = new File("./resource/test.json").getAbsoluteFile();

        SimpleModule everythingIsStringModule = new SimpleModule();
        everythingIsStringModule.addDeserializer(String.class,new EverythingIsStringDeserializer());

        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(everythingIsStringModule);

        MapType mapType = mapper.getTypeFactory().constructMapType(LinkedHashMap.class,String.class,String.class);

        LinkedHashMap<String,String> map = mapper.readValue(jsonFile,mapType);
        map.forEach((k,v) -> System.out.println(k + " => " + v));
    }
}

class EverythingIsStringDeserializer extends StringDeserializer {

    @Override
    public String deserialize(JsonParser p,DeserializationContext ctxt) throws IOException {
        if (p.currentToken() == JsonToken.START_OBJECT) {
            return _deserializeFromObject(p,ctxt);
        }
        return super.deserialize(p,ctxt);
    }

    private String _deserializeFromObject(JsonParser p,DeserializationContext ctxt) throws IOException {
        MapType mapType = ctxt.getTypeFactory().constructMapType(LinkedHashMap.class,String.class);
        JsonDeserializer<Object> deserializer = ctxt.findRootValueDeserializer(mapType);
        Map<String,String> map = (Map<String,String>) deserializer.deserialize(p,ctxt);

        return toString(map);
    }

    @Override
    protected String _deserializeFromArray(JsonParser p,DeserializationContext ctxt) throws IOException {
        CollectionType collectionType = ctxt.getTypeFactory().constructCollectionType(ArrayList.class,String.class);
        JsonDeserializer<Object> deserializer = ctxt.findRootValueDeserializer(collectionType);
        List<String> list = (List<String>) deserializer.deserialize(p,ctxt);

        return toString(list);
    }

    private String toString(Map<String,String> map) {
        StringBuilder builder = new StringBuilder(128);

        builder.append('{');
        boolean addComa = false;
        for (Map.Entry<String,String> entry : map.entrySet()) {
            if (addComa) {
                builder.append(',');
            }
            builder.append('"').append(entry.getKey())
                    .append("\":");
            appendValue(entry.getValue(),builder);
            addComa = true;
        }
        builder.append('}');

        return builder.toString();
    }

    private String toString(List<String> list) {
        StringBuilder builder = new StringBuilder(128);

        builder.append('[');
        boolean addComa = false;
        for (String item : list) {
            if (addComa) {
                builder.append(',');
            }
            appendValue(item,builder);
            addComa = true;
        }
        builder.append(']');

        return builder.toString();
    }

    private void appendValue(String value,StringBuilder builder) {
        if (value == null || value.isEmpty()) {
            builder.append("\"\"");
            return;
        }
        if (Character.isAlphabetic(value.charAt(0))) {
            builder.append('"').append(value).append('"');
        } else {
            builder.append(value);
        }
    }
}

打印:

a => text
b => 35
c => {d=another,dd=3.44E3}
e => [array,2.3E5]
f => 1.1E4
g => 0.00000000000003
本文链接:https://www.f2er.com/3154919.html

大家都在问