2017-03-10 63 views
6

Chcę dodać niestandardowy serializator i deserializer dla JSR 363 javax.measure.Quantity<Q extends Quantity<Q>>, który zasadniczo zawiera "wartość" i "jednostkę". Tworzenie serializera (extends JsonSerializer<Quantity<?>>) i deserializatora (extends StdDeserializer<Quantity<?>>) jest łatwe.Sygnatura modułu Jacksona zapobiega serializacjom addycji do samodzielnych odwoływania się do generycznych typów.

Ale nie jest łatwo je zarejestrować. W przypadku deserializatorów jest OK; spójrz na podpis:

SimpleModule.addDeserializer(Class<T> type, JsonDeserializer<? extends T> deser) 

Zwróć uwagę, że deserializator umożliwia rozszerzenie typu ogólnego. Mogę to zrobić:

module.addDeserializer(Quantity.class, new MyQuantityJsonDeserializer()); 

Ale serializator to inna historia; spójrz na podpis do rejestracji:

SimpleModule.addSerializer(Class<? extends T> type, JsonSerializer<T> ser) 

Och, ból ten powoduje z powodu ograniczonego rodzaju rodzajowego. Nie mogę tego zrobić:

module.addSerializer(Quantity.class, new MyQuantityJsonSerializer()); 

To dlatego Quantity.class nigdy nie da mi Class<Quantity<Q extends Quantity<Q>>. Nie ma łatwego rzutu wokół tego, bez wprowadzania jakiejś arbitralnej zmiennej ogólnej w metodzie modułowej i przy użyciu rzutów akrobatycznych. Nawet to nie będzie działać:

module.addSerializer((Class<Quantity<?>>) Quantity.class, new MyQuantityJsonSerializer()); 

Najlepszą udało mi się zrobić to, aby moja klasa serializer QuantityJsonSerializer<Q extends Quantity<Q>> extends JsonSerializer<Q>, a następnie w module zarejestrować go jako typ RAW:

@SuppressWarnings({"rawtypes", "unchecked"}) 
final JsonSerializer<Quantity> quantitySerializer = 
    (JsonSerializer<Quantity>) new MyQuantityJsonSerializer(); 
module.addSerializer(Quantity.class, quantitySerializer); 

Ugh, jakie to brzydkie? Ale to jeden z jedynych sposobów, dzięki którym mogę go uruchomić, i musiałem przejść przez więcej gimnastyki, aby usunąć ostrzeżenia.

Z pewnością SimpleModule.addSerializer() mógłby być nieco bardziej elastyczny pod względem swoich parametrów ogólnych, analogicznie do SimpleModule.addDeserializer()?

Zgłaszam to tutaj, ponieważ projekt Jackson powiedział, że zgłaszał tu błędy - i ja także proszę o lepsze rozwiązania. Dzięki.

+0

Do potrzebujesz generycznych? – mikep

+0

Możesz rzucić klasę z dwuczęściową obsadą, coś w rodzaju '(Klasa >) (Klasa ) Klasa.class' lub' (Klasa >) (Klasa ) Quantity.class'. Projekt "Klasy" jest po prostu bardzo zły na tego typu rzeczy. Java musi go zastąpić czymś takim jak ['TypeToken'] (http://google.github.io/guava/releases/snapshot/api/docs/com/google/common/reflect/TypeToken.html). Problemy nie znikną, o ile warto zarejestrować jakiś rodzaj obsługi z konkretnym typem. Odpowiedź ck1 sugeruje, że nie musisz wykonywać obsady w tym przypadku. – Radiodef

+0

Ale co z niespójnością metod 'addSerializer()' i 'addDeserializer()'? Dlaczego istnieje niespójność? Gdzie mogę zgłosić problem, aby Jackson mógł to naprawić? Czy istnieje powód, dla którego powinna pozostać niespójność? –

Odpowiedz

3

W SimpleModule nie jest przeciążona wersja addSerializer():

public SimpleModule addSerializer(JsonSerializer<?> ser) 

który pozwala na to, aby pracować:

module.addSerializer(new MyQuantityJsonSerializer()); 

tak długo, jak zdefiniować serializatora jak:

public class MyQuantityJsonSerializer extends StdSerializer<Quantity<?>> { 
    public MyQuantityJsonSerializer() { 
     // Note: second argument here is ignored. 
     super(Quantity.class, false); 
    } 

    @Override 
    public void serialize(Quantity<?> value, JsonGenerator gen, SerializerProvider serializers) throws IOException { 
     // Serialize value here... 
    } 
}