Удаление десериализации нестрочных карт с помощью Jackson
У меня есть карта, которая выглядит так:
public class VerbResult {
@JsonProperty("similarVerbs")
private Map<Verb, List<Verb>> similarVerbs;
}
Мой класс глаголов выглядит следующим образом:
public class Verb extends Word {
@JsonCreator
public Verb(@JsonProperty("start") int start, @JsonProperty("length") int length,
@JsonProperty("type") String type, @JsonProperty("value") VerbInfo value) {
super(length, length, type, value);
}
//...
}
Я хочу сериализовать и десериализовать экземпляры моего класса VerbResult, но когда я получу эту ошибку: Can not find a (Map) Key deserializer for type [simple type, class my.package.Verb]
Я читал онлайн, что вам нужно сказать Джексону, как десериализовать ключи карты, но я не нашел никакой информации, объясняющей, как это сделать. Класс глагола должен быть сериализован и десериализован за пределами карты, поэтому любое решение должно сохранить эту функциональность.
Благодарим вас за помощь.
Ответы
Ответ 1
Основываясь на ответе приведенном здесь, который предлагает реализовать модуль с десериализатором, я ссылаюсь на Документация модуля Jackson. JodaTime Module - это простой для понимания полный пример модуля, содержащего сериализаторы и десериализаторы.
Обратите внимание, что функция модуля была введена в версии 1.7 для Джексона, поэтому вам может потребоваться обновление.
Итак, шаг за шагом:
- создать модуль, содержащий сериализатор (de) для вашего класса на основе примера Joda
- зарегистрируйте этот модуль с помощью
mapper.registerModule(module);
и все будет установлено
Ответ 2
После дня поиска я столкнулся с более простым способом сделать это на основе этого вопроса. Решением было добавить аннотацию @JsonDeserialize(keyUsing = YourCustomDeserializer.class)
к карте. Затем выполните свой собственный десериализатор, расширив KeyDeserializer
и переопределив метод deserializeKey
. Метод будет вызываться с помощью строкового ключа, и вы можете использовать строку для создания реального объекта или даже извлечения существующего из базы данных.
Итак, сначала в объявлении карты:
@JsonDeserialize(keyUsing = MyCustomDeserializer.class)
private Map<Verb, List<Verb>> similarVerbs;
Затем создайте десериализатор, который будет вызываться с помощью строкового ключа.
public class MyCustomDeserializer extends KeyDeserializer {
@Override
public MyMapKey deserializeKey(String key, DeserializationContext ctxt) throws IOException, JsonProcessingException {
//Use the string key here to return a real map key object
return mapKey;
}
}
Работает с Джерси и Джексоном 2.x
Ответ 3
Как упоминалось выше, трюк заключается в том, что вам нужен десериализатор (это тоже меня поймало). В моем случае в моем классе был сконфигурирован не-строковый ключ карты, но он не был в JSON, который я обрабатывал, поэтому для меня очень простое решение (просто возвращающее значение null в десериализаторе ключей).
public class ExampleClassKeyDeserializer extends KeyDeserializer
{
@Override
public Object deserializeKey( final String key,
final DeserializationContext ctxt )
throws IOException, JsonProcessingException
{
return null;
}
}
public class ExampleJacksonModule extends SimpleModule
{
public ExampleJacksonModule()
{
addKeyDeserializer(
ExampleClass.class,
new ExampleClassKeyDeserializer() );
}
}
final ObjectMapper mapper = new ObjectMapper();
mapper.registerModule( new ExampleJacksonModule() );