【问题标题】:How to enable strict type parsing for jackson?如何为杰克逊启用严格的类型解析?
【发布时间】:2012-09-22 18:58:12
【问题描述】:

Jackson 1.9.9 在解析成标量值(bool、int、string)时有些不一致。任何数组或对象类型都会失败,但您可以将任何标量类型放入字符串中。对于 bool 0 而不是 0 映射到 false/true。 int 属性只接受数字。

public class Foo { public String s; public boolean b; public int i; }

ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.readValue("{\"s\":\"abc\"}", Foo.class).s); // "abc"
System.out.println(mapper.readValue("{\"s\":true}", Foo.class).s); // "true"
System.out.println(mapper.readValue("{\"s\":123}", Foo.class).s); // "123"
System.out.println(mapper.readValue("{\"b\":123}", Foo.class).b); // true
System.out.println(mapper.readValue("{\"b\":0}", Foo.class).b); // false
System.out.println(mapper.readValue("{\"b\":\"abc\"}", Foo.class).b); // fails with JsonMappingException
System.out.println(mapper.readValue("{\"i\":\"abc\"}", Foo.class).i); // fails with JsonMappingException
System.out.println(mapper.readValue("{\"i\":true}", Foo.class).i); // fails with JsonMappingException
System.out.println(mapper.readValue("{\"s\":[]}", Foo.class).s); // fails with JsonMappingException
System.out.println(mapper.readValue("{\"s\":{}}", Foo.class).s); // fails  with JsonMappingException
System.out.println(mapper.readValue("{\"b\":[]}", Foo.class).b); // fails with JsonMappingException
System.out.println(mapper.readValue("{\"b\":{}}", Foo.class).b); // fails  with JsonMappingException
System.out.println(mapper.readValue("{\"i\":[]}", Foo.class).i); // fails with JsonMappingException
System.out.println(mapper.readValue("{\"i\":{}}", Foo.class).i); // fails  with JsonMappingException

Jackson 是否有 严格模式,如果有人将布尔值传递给 String 属性,我会收到错误消息?

我在一个 JAX-RS 项目中使用它,这使得基于 Jackson 抛出的异常的错误报告有些困难,因为我得到了大部分错误,但不是全部。我想避免获取原始 ObjectNode 并手动检查所有内容。如果调用者为字符串传递布尔值,那么我想告诉他,因为这很可能是编程错误。

【问题讨论】:

    标签: java jax-rs jackson


    【解决方案1】:

    FWIW,如果您像我一样在很久以后遇到这种情况,ALLOW_COERCION_OF_SCALARS 将通过减少 Jackson 为您完成的转换次数而有所帮助,尽管它远非完全严格的模式;许多类型强制仍然会执行,但有些会被阻止。链接的文档涉及到一些细节。

    【讨论】:

    • 警告:这只会对 bool 和 int 有帮助。如果你的 POJO 有一个字符串字段,并且输入的 JSON 有一个数字/布尔值,那么在反序列化过程中,它们仍然会被强制转换为字符串,没有任何异常
    【解决方案2】:

    Jackson 数据绑定随着时间的推移而增长,可以接受更多的自动强制,尽管有一些功能 (DeserializationConfig.Feature.FAIL_ON_NULL_FOR_PRIMITIVES) 可以强制执行更严格的检查,但请求的并不多。

    鉴于此,您最好为您想要更严格的类型注册自定义JsonDeserializer,例如boolean/Boolean。您可以在那里实施更严格的检查。

    此外,您可以请求功能以获得更严格的限制:我认为这对于某些用例确实有意义,尤其是。如果更松散的转换可以隐藏真正的问题。

    【讨论】:

    • Java 的默认 JSON 解决方案怎么会如此糟糕?
    • @polkovnikov.ph 鉴于许多编程语言缺乏实际的布尔类型,或者由于某种原因或其他使用值,其他人认为您认为行为不端的行为对互操作性非常有用比 JSON true/false 的类似概念。严格的失败是一些用户想要的,但许多其他人会觉得很麻烦,而且行为不端。
    • 考虑是主观的。 Implicit casting considered harmful 很久以前。无论某些用户如何看待隐式转换的有用性,它们都会导致错误。对于没有布尔类型(或具有多个布尔类型)的语言,显式转换注释是唯一正确的方法。 Jackson 的问题在于它不一致地实现了其中一些转换,否则整个类型都需要(反)序列化器,这就是我称之为行为不端的原因。
    • @polkovnikov.ph 是的,您和我的意见都是主观的,一篇声称某事(如隐式转换)的文章只是另一个人的意见。至于 Jackson,强制是在数据绑定级别完成的:在流解析器中,令牌和类型完全按原样公开 - 但在数据绑定用户特别期望 boolean 作为目标类型,所以强制是合理的。如果是这样,只有两种方法:要么(a)做被要求的事情,要么(b)成为一个混蛋并声称无法做到。一些库会这样做。其他人没有。没有正确的答案。
    • 是的,"4a"+6 可能是6.16667 按要求,或者编程语言可能是个混蛋并拒绝它。肯定没有正确答案。您是否尝试摆脱无知的泡沫,找到数百篇此类文章和一些关于类型论的科学文献?
    猜你喜欢
    • 2014-08-22
    • 2019-11-25
    • 2014-06-17
    • 1970-01-01
    • 1970-01-01
    • 2019-07-27
    • 1970-01-01
    • 2018-04-20
    相关资源
    最近更新 更多