2012-10-29 15 views
5

Próbuję stworzyć klasę, która używa Jacksona do deserializacji POJO.Deserializowanie rodzaju ogólnego z Jacksonem

Wygląda to tak ...

public class DeserialiserImp<T> implements Deserialiser<T> { 

     protected ObjectMapper objectMapper = new ObjectMapper(); 

     @Override 
     public T get(String content, Class clazz) throws IOException { 
      return (T) objectMapper.readValue(content, clazz); 
     } 

     @Override 
     public List<T> getList(String content, Class clazz) throws IOException { 
      return objectMapper.readValue(content, TypeFactory.collectionType(ArrayList.class, clazz)); 
     } 

    } 

Mam 2 pytania dotyczące tej realizacji.

Po pierwsze, przekazuję typ klasy do metod, dzięki czemu obiekt poznaje typ, który powinien deserializować. Czy istnieje lepszy sposób korzystania z generycznych?

Również w metodzie get rzutuję obiekt zwrócony z obiektuMapper na T. Wydaje się to szczególnie nieprzyjemny sposób, ponieważ muszę tu rzutować T, a następnie muszę również rzutować typ obiektu z metody, która nazywa to.

Używam Roboguice w tym projekcie, więc byłoby miło, gdybym mógł zmienić typ poprzez wstrzyknięcie, a następnie dodać obiekt, który typowy jest mi potrzebny do powrotu. Czytałem o TypeLiteral i zastanawiasz się, czy to może rozwiązać ten problem?

+0

Zobacz http://stackoverflow.com/questions/17400850/is-jackson-really-unable-to-deserialize-json-into-a-generic-type – lisak

Odpowiedz

5

Więc myślę, że to wymyśliłem w końcu. Prosimy o komentarz, jeśli widzisz coś nie tak z tym, co robię.

Interfejs jest zdefiniowane tak jak ...

public interface Deserialiser<T> { 

    T get(String content) throws IOException; 

    List<T> getList(String content) throws IOException; 
} 

Realizacja interfejsu jest tak ...

public class DeserialiserImp<T> implements Deserialiser<T> { 

    private ObjectMapper objectMapper = new ObjectMapper(); 
    private final Class<T> klass; 

    @Inject 
    public DeserialiserImp(TypeLiteral<T> type){ 
     this.klass = (Class<T>) type.getRawType(); 
    } 

    @Override 
    public T get(String content) throws IOException { 
     return objectMapper.readValue(content, klass); 
    } 

    @Override 
    public List<T> getList(String content) throws IOException { 
     return objectMapper.readValue(content, TypeFactory.collectionType(ArrayList.class, klass)); 
    } 

} 

wiążę 2 jak tak ..

bind(new TypeLiteral<Deserialiser<User>>(){}).annotatedWith(Names.named("user")).to(new TypeLiteral<DeserialiserImp<User>>(){}); 

Wtedy wszystko, co trzeba zrobić, aby wykorzystać to ta ...

@Inject 
@Named("user") 
private Deserialiser<User> deserialiserImp; 

public void test(String userString) { 
    User user = deserialiserImp.get(UserString); 
} 

Wzór ten może również działać dobrze, jeśli klasa jako abstrakcyjne klasy do wykorzystania w obiekcie DAO

This artykuł bardzo mi pomógł

5

Pierwszym jest to, że jestem przekazując typ klasy do metod tak więc ObjectMapper zna typ, który powinien deserializowania. Czy istnieje lepszy sposób na używanie generycznych?

Niestety nie, a to z powodu wymazania tekstu.

Również metody GET Mam oddające obiekt zwrócony z ObjectMapper T. To wydaje się szczególnie przykry sposób to zrobić jak mam do oddania T tutaj i wtedy muszę również rzutować typ obiektu od metody, która go wywołuje.

Czy to zamiast:

@Override 
public T get(String content, Class<T> clazz) throws IOException { 
    return objectMapper.readValue(content, clazz); 
} 

Używam Roboguice w tym projekcie, więc byłoby miło, gdybym mógł zmienić typ poprzez iniekcję i następnie opisywanie przedmiotu który uniwersalnym typem Potrzebuję go, aby wrócić. Czytałem o TypeLiteral i zastanawiając się, czy to rozwiąże ten problem?

Nie bardzo rozumiem, co chcesz osiągnąć, ale skoro i tak musisz przejść zajęcia, czy to nadal możliwe?

+0

Chodzi mi o używaniu TypeLiteral przyjść s z tego pytania http://stackoverflow.com/questions/3370641/how-does-guices-typeliteral-work Mówi, że "Sztuczka, która jest tu używana, to to, że podpisy generycznych super typów są przechowywane w podklasach i w ten sposób przetrwają wymazanie. " Mam nadzieję, że nie przekażę tego typu. – jiduvah

+1

OK Rozumiem. Nie widzę tutaj żadnego praktycznego rozwiązania, musisz gdzieś go zapisać (zwykły obiekt klasy jako pole, używając TypeLiteral itp.), Aby go pobrać w czasie wykonywania. Nie wydaje mi się, że przekazywanie tego typu za każdym razem stanowi poważny problem, ponieważ jest wymagane przez wszystkie biblioteki "niemagające". Byłbym jednak zainteresowany innym podejściem. –

+0

Cóż, próbuję uczynić kod czystszym. W chwili obecnej przekazuję typ jako rodzajowy podczas tworzenia instancji deserialiserImp, muszę przekazać klasę do metody, a następnie muszę również rzucić obiekt, który otrzymuję. Więc to 3 razy odwołuję się do typu. Wydaje się, że bardzo messey – jiduvah

Powiązane problemy