2012-06-27 12 views
9

Próbuję użyć Gson z interfejsem:Deserializowanie interfejsu za pomocą Gson?

public interface Photo { 
    public int getWidth(); 
} 

public class DinosaurPhoto implements Photo { 
    ... 
} 

public class Wrapper { 
    private Photo mPhoto; // <- problematic 
} 

... 

Wrapper wrapper = new Wrapper(); 
wrapper.setPhoto(new DinosaurPhoto()); 
Gson gson = new Gson(); 
String raw = gson.toJson(wrapper); 

// Throws an error since "Photo" can't be deserialized as expected. 
Wrapper deserialized = gson.fromJson(raw, Wrapper.class); 

Ponieważ klasa Wrapper posiada zmienną składową, która jest typu Photo, w jaki sposób przejść o deserializacji go za pomocą Gson?

Dzięki

Odpowiedz

8

Niestandardowa deserializacja jest konieczna.

W zależności od większego problemu, który należy rozwiązać, należy użyć ["typ adaptera"] 1 lub "type hierarchy adapter". Adapter hierarchii typów "is to cover the case when you want the same representation for all subtypes of a type".

+1

Cześć Bruce, więc myślę, że jestem wciągnięty w to, co jest, wygląda na to, że Gson po prostu nie obsługuje jeszcze polimorficznej deserializacji. Widziałem na twojej stronie, że masz kilka przykładów Jacksona (które zawierają polimorfizm). Czy w tym momencie poleciłbyś korzystanie z jacksona na Gsonie? Dzięki – user291701

+2

Tak, polecam korzystanie z Jackson over Gson, jak opisano w http://programmerbruce.blogspot.com/2011/07/gson-v-jackson-part-6.html. Jackson ma przyzwoitą wbudowaną obsługę polimorfizmu, a także inne korzyści, takie jak znacznie lepsza wydajność. Zainteresowanym post na temat deserializacji polimorficznej z Jacksonem znajduje się na stronie http://programmerbruce.blogspot.com/2011/05/deserialize-json-with-jackson-into.html –

3

Po prostu nie można tego zrobić za pomocą GSON.

Byłem zaniepokojony tym samym problemem, gdy natknąłem się na Jackson. Z nim jest bardzo proste:

ObjectMapper mapper = new ObjectMapper(); 
mapper.enableDefaultTyping(); 

A potem można iść o de/szeregowania swoje obiekty Java i interfejsy bez konieczności pisania dodatkowych niestandardowych DE/serializers, annotaions i naprawdę nie dodaje kod ogóle.

Nie stanowiło to części pytania, ale może okazać się przydatne, jeśli zdecydujesz się na przeniesienie z Gson do Jacksona. Gson obsługuje domyślnie prywatne pola, ale w przypadku Jacksona należy to uwzględnić w swoim kodzie.

mapper.setVisibilityChecker(g.getVisibilityChecker().with(Visibility.ANY)); 

realizacja Przykładowy kod w main:

ObjectMapper mapper = new ObjectMapper(); 
mapper.enableDefaultTyping(); 
mapper.setVisibilityChecker(g.getVisibilityChecker().with(Visibility.ANY)); 
Wrapper wrapper = new Wrapper(); 
wrapper.setPhoto(new DinosaurPhoto()); 
String wrapper_json = mapper.writeValueAsString(wrapper); 
Wrapper wrapper_from_json = mapper.readValue(wrapper_json,Wrapper.class); 

Gson obiecał będą pracować nad tym problemem w przyszłych wersjach, ale nie zostały one rozwiązać go tak daleko. Jeśli jest to bardzo ważne dla twojej aplikacji, proponuję, abyś portował do Jacksona.

+0

brakuje Twojego linku – ronalchn

0

Zbudowałem prymitywny generator shimowania interfejsu poprzez kompilację klasy właściwości groovy, aby współdziałać z modelem GWT Autobeans. jest to naprawdę trudna metoda na razie obejścia krzywej uczenia ASM/cglib. na tym tle: w przypadku Autobeans można używać tylko interfejsów, a słońca * proxy nie są w stanie interakcji gsonów dla wszystkich prób dostępu, z którymi eksperymentowałem. ALE, gdy groovy classloader jest lokalny dla GsonBuilder, rzeczy stają się trochę łatwiejsze. zauważ, że to się nie powiedzie, chyba że rejestracja gsonBuilder zostanie wywołana z poziomu samej groovy.

dostęp do fabryki podkładka utworzyć jako pojedynczych nazw JSON_SHIM i nazywają

JSON_SHIM.getShim ("{}", MyInterface.class)

zarejestrować się w razie potrzeby i stworzyć [puste] instancja. jeśli masz interfejsy w swoich interfejsach, musisz je wstępnie zarejestrować przed użyciem. jest to wystarczająca ilość magii, aby użyć płaskich Autobeans z gsonem, a nie całą strukturą. W tym generatorze nie ma kodu groovy, więc ktoś z javassist-foo może powtórzyć eksperyment.

Powiązane problemy