如何使用Jackson JSON处理器处理无效值?

时间:2011-07-12 09:00:18

标签: json jackson

我用杰克逊来接替json。

现在,我面临着一个问题。

我的POJO:

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

JSON是

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

如果我写这样的代码:

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

抛出异常:

  

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

如果JSON是"{\"name\":\"Jackson\",\"age\":null}",那就没关系。

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

1 个答案:

答案 0 :(得分:3)

我建议在http://jira.codehaus.org/browse/JACKSON记录问题,要求将其视为错误,或者添加允许正确处理的功能。 (也许DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT允许将空JSON字符串反序列化为默认原始值是合理的,因为这是在绑定到Java原语时以其他方式处理JSON空值的方式。)(更新:我为此记录了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,那么该字段将填充一个空值(不是那个想要的)。为此,我记录了issue 617,以请求反序列化配置,在绑定到原始包装类型字段时自动从JSON空值设置原始默认值。换句话说,当从JSON空值反序列化为整数字段时,目标字段将设置为{{1而不是Integer.valueOf(0)。)