Использование Jackson ObjectMapper с Generics для POJO вместо LinkedHashMap - PullRequest
6 голосов
/ 18 января 2012

Используя Джерси, я определяю сервис как:

@Path("/studentIds")
public void writeList(JsonArray<Long> studentIds){
 //iterate over studentIds and save them
}

Где JsonArray:

public class JsonArray<T> extends ArrayList<T> {  
    public JsonArray(String v) throws IOException {
        ObjectMapper objectMapper = new ObjectMapper(new MappingJsonFactory());
        TypeReference<ArrayList<T>> typeRef = new TypeReference<ArrayList<T>>() {};
        ArrayList<T> list = objectMapper.readValue(v, typeRef);
        for (T x : list) {
            this.add((T) x);
        }
    }
}

Это работает просто отлично, но когда я делаю что-то более сложное:

@Path("/studentIds")
public void writeList(JsonArray<TypeIdentifier> studentIds){
 //iterate over studentIds and save them by type
}

Где Боб - это простой POJO, такой как

public class TypeIdentifier {
    private String type;
    private Long id;
//getters/setters 
}

Все это ужасно ломается.Он преобразует все в LinkedHashMap вместо реального объекта.Я могу заставить его работать, если я вручную создаю класс, такой как:

public class JsonArrayTypeIdentifier extends ArrayList<TypeIdentifier> { 
    public JsonArrayTypeIdentifier(String v) throws IOException  {
        ObjectMapper objectMapper = new ObjectMapper(new MappingJsonFactory());
        TypeReference<ArrayList<TypeIdentifier>> typeRef = new TypeReference<ArrayList<TypeIdentifier>>(){};
        ArrayList<TypeIdentifier> list = objectMapper.readValue(v, typeRef);
        for(TypeIdentifier x : list){
            this.add((TypeIdentifier) x);
        }
    }
 }

Но я пытаюсь сделать это красиво и обобщенно, не добавляя дополнительные классы.Любые наводки на то, почему это происходит только с общей версией?

1 Ответ

1 голос
/ 18 января 2012

Прежде всего, это работает с Longs, потому что это своего рода нативный тип, и как таковая привязка по умолчанию для целых чисел JSON.

Но относительно того, почему универсальная информация о типах не передается должным образом: это, скорее всего, связано с проблемами, связанными с тем, как API JAX-RS передает тип в MessageBodyReader s и MessageBodyWriter s - передача java.lang.reflect.Type не является ( к сожалению!) достаточно, чтобы передать фактические общие объявления (подробнее об этом читайте эту запись в блоге ).

Один простой способ - создать вспомогательные типы, такие как:

class MyTypeIdentifierArray extends JsonArray<TypeIdentifier> { }

и используйте этот тип - все будет «просто работать», поскольку универсальная информация супертипа всегда сохраняется.

...