Jackson误将数字开头字符串识别为整数的问题及解决咨询
问题分析与解决方案
问题根源
你遇到的核心问题是:输入的5 ttt并非合法JSON值(合法JSON字符串必须用双引号包裹),Jackson默认解析器会尝试将未加引号、以数字开头的内容匹配为数字类型,仅提取开头的有效数字部分5,剩余的 ttt被当作无效后缀直接忽略。此外,Jackson中类级别的反序列化器优先级远高于字段级,所以你配置的字段反序列化器完全不会被触发。
可行解决方案
方案1:修正输入为合法JSON格式
如果可以修改输入内容,将其改为标准JSON字符串(添加双引号):
TestClass testClass = mapper2.readValue("\"5 ttt\"", TestClass.class);
此时Jackson会将其解析为完整的字符串token,你的类级反序列化器调用p.getValueAsString()就能直接拿到5 ttt,输出符合预期。
方案2:在自定义反序列化器中读取原始输入内容
若无法修改输入,可在类级反序列化器中跳过Jackson的自动类型解析,直接读取输入流的全部内容:
private static class TestClassDeserializer extends JsonDeserializer<TestClass> { @Override public TestClass deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException { TestClass param = new TestClass(); // 读取输入流所有字节并转换为字符串,trim()可移除首尾无关空白 byte[] rawInput = p.getInputStream().readAllBytes(); param.field = new String(rawInput, StandardCharsets.UTF_8).trim(); return param; } }
这种方式绕开了Jackson的自动类型推断,直接获取原始输入的完整内容。
方案3:配置ObjectMapper强制识别为字符串
通过修改ObjectMapper的解析特性,允许未加引号的内容,并强制将输入视为字符串:
ObjectMapper mapper2 = new ObjectMapper(); // 允许解析未加引号的内容 mapper2.enable(JsonParser.Feature.ALLOW_UNQUOTED_CONTENT); // 注册自定义反序列化器,此时调用p.getValueAsString()可获取完整内容 SimpleModule module = new SimpleModule(); module.addDeserializer(TestClass.class, new TestClassDeserializer() { @Override public TestClass deserialize(final JsonParser p, final DeserializationContext ctxt) throws IOException { TestClass param = new TestClass(); // 此时Jackson会将整个输入当作字符串处理 param.field = p.getValueAsString(); return param; } }); mapper2.registerModule(module);
注意:字段级反序列化器之所以无效,是因为类级反序列化器会接管整个类的反序列化流程,Jackson不会再去处理单个字段的反序列化逻辑,所以无需配置字段级反序列化器。
内容的提问来源于stack exchange,提问作者Bestows In Constructing
相关产品推荐
相关产品推荐

