【问题标题】:How to process an invalid value with Jackson JSON processor?如何使用 Jackson JSON 处理器处理无效值?
【发布时间】:2011-10-03 10:52:45
【问题描述】:

我使用 Jackson 来处理 json。

现在,我遇到了一个问题。

我的 POJO:

class Person{
    public String name;
    public int age;
}

JSON 是

{"name":"Jackson","age":""}.

如果我这样写代码:

Person person = mapper.readValue("{\"name\":\"Jackson\",\"age\":\"\"}", Person.class);

抛出异常:

无法从字符串值“”构造 int 的实例:不是有效的 int 值。

如果 JSON 是"{\"name\":\"Jackson\",\"age\":null}",就可以了。

但是现在,我不想修改 JSON。我该怎么办?

【问题讨论】:

  • 那些双引号是无效的,但无论如何都会导致不同的错误和无法编译的代码。为避免红鲱鱼,请将问题中的引号改为直引号。
  • 你想处理任何可能的输入字符串,不是数字,还是只是一个空字符串?

标签: json jackson


【解决方案1】:

我建议在http://jira.codehaus.org/browse/JACKSON 记录一个问题,要求将其视为错误,或者添加允许正确处理的功能。 (也许DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT 还允许将空 JSON 字符串反序列化为默认原始值是合理的,因为这就是 JSON 空值在绑定到 Java 原始值时的处理方式。)(更新:我记录了issue 616 对此。如果您希望它实现,请投票支持它。)

在 Jackson 如此增强之前,需要自定义反序列化处理来将 JSON 空字符串转换为默认的原始值(或任何需要的非字符串值)。下面是这样一个例子,幸运的是,它很简单,因为现有的反序列化为 int 的代码已经处理了一个空字符串,将其变为 0。

import java.io.IOException;

import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.Version;
import org.codehaus.jackson.map.DeserializationContext;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.deser.StdDeserializer;
import org.codehaus.jackson.map.module.SimpleModule;

public class Foo
{
  public static void main(String[] args) throws Exception
  {
    // {"name":"Jackson","age":""}
    String json = "{\"name\":\"Jackson\",\"age\":\"\"}";

    SimpleModule module = new SimpleModule("EmptyJsonStringAsInt", Version.unknownVersion());
    module.addDeserializer(int.class, new EmptyJsonStringAsIntDeserializer(int.class));

    ObjectMapper mapper = new ObjectMapper().withModule(module);
    Person p = mapper.readValue(json, Person.class);
    System.out.println(mapper.writeValueAsString(p));
    // {"name":"Jackson","age":0}
  }
}

class Person
{
  public String name;
  public int age;
}

class EmptyJsonStringAsIntDeserializer extends StdDeserializer<Integer>
{
  protected EmptyJsonStringAsIntDeserializer(Class<?> vc)
  {
    super(vc);
  }

  @Override
  public Integer deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException
  {
    return super._parseIntPrimitive(jp, ctxt);
  }
}

(另外,请注意,如果目标类型是 Integer 而不是 int,则该字段将填充 null 值(这不是我们想要的)。为此,我记录了 issue 617,以请求反序列化配置当绑定到原始包装类型字段时,自动从 JSON 空值设置原始默认值。换句话说,当从 JSON 空值反序列化为整数字段时,目标字段将设置为 Integer.valueOf(0) 而不是null.)

【讨论】:

  • 感谢您的回答,布鲁斯。也许我没有清楚地发布我的目的。如果目标类型是 Integer 而不是 int,则该字段将填充空值。我认为这是合理的。这就是我想要的。
  • 感谢您的回答,布鲁斯。也许我没有清楚地发布我的目的。如果目标类型是 Integer 而不是 int,则该字段将填充空值。我认为这是合理的。这就是我想要的。例如,一个人的“年龄”为 null,只是因为他的名字是未知的,除了他的年龄是 0。我的问题是我无法处理整数的空字符串。我猜这可能是因为我的jackson版本是1.5.5。昨天,我更新到1.8.3版本。它默认可以处理一个空字符串。
    我的英语很差,不知道你能不能看懂我的想法。
  • 我还不确定我是否理解。升级到 Jackson 1.8.3 后,你还有问题吗?如果是这样,确切地你在做什么,你想让它做什么,它在做什么呢?
  • 如果我使用Jackson 1.5.5,当我将空字符串(例如{“age”:“”})反序列化为Integer时,会抛出异常(“无法从String构造int实例value ”:不是有效的 int 值。”)。升级到 Jackson 1.8.3 后,没问题并返回 NULL 值。这就是我想要的。所以我只是将 Jackson 升级到版本 1.8.3,它运行良好。- -----谢谢你的提示:_)
猜你喜欢
  • 2018-02-21
  • 1970-01-01
  • 2015-02-25
  • 2011-03-17
  • 2011-06-22
  • 1970-01-01
  • 2016-11-01
  • 2012-05-12
  • 1970-01-01
相关资源
最近更新 更多