Как обработать недопустимое значение с процессором Jackson JSON? - PullRequest
2 голосов
/ 12 июля 2011

Я использую Джексона для обработки 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. А как мне это сделать?

1 Ответ

3 голосов
/ 12 июля 2011

Я рекомендую зарегистрировать проблему на http://jira.codehaus.org/browse/JACKSON,, требуя, чтобы это считалось ошибкой или чтобы была добавлена ​​функция, обеспечивающая правильную обработку. (Возможно, разумно, что DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT также разрешит десериализацию пустых строк JSON до значений примитивов по умолчанию, поскольку именно так иначе обрабатываются нулевые значения JSON при привязке к примитивам Java.) ( Обновление: Я вошел в систему вопрос 616 . Проголосуйте за него, если хотите, чтобы он был реализован.)

До тех пор, пока Джексон не будет усовершенствован, потребуется специальная обработка десериализации, чтобы преобразовать пустую строку 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 в поле Integer целевое поле будет установлено на Integer.valueOf(0) вместо null.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...