Подтвердить что ты не робот

Удаление десериализации нестрочных карт с помощью 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]

Я читал онлайн, что вам нужно сказать Джексону, как десериализовать ключи карты, но я не нашел никакой информации, объясняющей, как это сделать. Класс глагола должен быть сериализован и десериализован за пределами карты, поэтому любое решение должно сохранить эту функциональность.

Благодарим вас за помощь.

4b9b3361

Ответ 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() );