2016-11-15 99 views
0

我已經JSON包通過「_embedded」標籤象下面這樣:無法反序列化使用改造(安卓)嵌套的JSON

{ 
    "_embedded" : { 
    "events" : [ { ... }]} 

我使用的是改造與接口:

public interface IEventRest { 
    @GET("/events/search/findByPlaceId") 
    Observable<List<Event>> getEventList(@Query("placeId")String placeId); 
} 

這是我的REST類:

public class EventRest implements IEventRest { 
Gson gson = new GsonBuilder() 
     .registerTypeAdapter(Event[].class, new MyDeserializer()) 
     .create(); 

private Retrofit getRetrofitClient() { 
    final HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); 
    interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); 

    final OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build(); 

    return new Retrofit.Builder() 
      .addConverterFactory(GsonConverterFactory.create(gson)) 
      .baseUrl(UrlUtils.URL) 
      .client(client) 
      .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 
      .build(); 
} 

@Override 
public Observable<List<Event>> getEventList(String placeId) { 
    final IEventRest placeRest = getRetrofitClient().create(IEventRest.class); 

    return placeRest.getEventList(placeId) 
      .subscribeOn(Schedulers.io()) 
      .observeOn(Schedulers.newThread()); 
} 

private class MyDeserializer implements JsonDeserializer<List<Event>> { 
    @Override 
    public List<Event> deserialize(JsonElement je, Type type, JsonDeserializationContext jdc) 
      throws JsonParseException { 
     JsonElement content = je.getAsJsonObject().get("_embedded"); 

     Type collectionType = new TypeToken<Collection<Event>>(){}.getType(); 
     return new Gson().fromJson(content, collectionType); 

    } 
} 
} 

但調用placeRest.getEventList(placeId)拋出異常:

java.lang.IllegalStateException: Exception thrown on Scheduler.Worker thread. Add `onError` handling. 
    at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:57) 
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:423) 
    at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:269) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 
    at java.lang.Thread.run(Thread.java:818) 
Caused by: rx.exceptions.OnErrorNotImplementedException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $ 
    at rx.internal.util.InternalObservableUtils$ErrorNotImplementedAction.call(InternalObservableUtils.java:386) 
    at rx.internal.util.InternalObservableUtils$ErrorNotImplementedAction.call(InternalObservableUtils.java:383) 
    at rx.internal.util.ActionSubscriber.onError(ActionSubscriber.java:44) 
    at rx.observers.SafeSubscriber._onError(SafeSubscriber.java:152) 
    at rx.observers.SafeSubscriber.onError(SafeSubscriber.java:115) 
    at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber.checkTerminated(OperatorObserveOn.java:276) 
    at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber.call(OperatorObserveOn.java:219) 
    at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55) 
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:423) 
    at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:269) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) 
    at java.lang.Thread.run(Thread.java:818) 
Caused by: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $ 
    at com.google.gson.stream.JsonReader.beginArray(JsonReader.java:351) 
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:80) 
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61) 
    at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:37) 
    at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:25) 
    at retrofit2.ServiceMethod.toResponse(ServiceMethod.java:117) 
    at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:211) 
    at retrofit2.OkHttpCall.execute(OkHttpCall.java:174) 
    at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$RequestArbiter.request(RxJavaCallAdapterFactory.java:171) 
    at rx.internal.operators.OperatorSubscribeOn$1$1$1.request(OperatorSubscribeOn.java:80) 
    at rx.Subscriber.setProducer(Subscriber.java:211) 
    at rx.internal.operators.OperatorSubscribeOn$1$1.setProducer(OperatorSubscribeOn.java:76) 
    at rx.Subscriber.setProducer(Subscriber.java:205) 
    at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:152) 
    at retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$CallOnSubscribe.call(RxJavaCallAdapterFactory.java:138) 
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48) 
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30) 
    at rx.Observable.unsafeSubscribe(Observable.java:9860) 
    at rx.internal.operators.OperatorSubscribeOn$1.call(OperatorSubscribeOn.java:94) 
    at rx.internal.schedulers.CachedThreadScheduler$EventLoopWorker$1.call(CachedThreadScheduler.java:221) 

你能幫我找出有什麼問題嗎?先謝謝你。

+0

你註冊了'Event []。class',但你要求'List '你需要保持一致。 – njzk2

+0

'{「_embedded」:{'是一個對象,而不是它自己的事件列表。你的數據不是以'['開始的,所以你不能像這樣解析它。 –

回答

1

我已經JSON包裹由 「_embedded」 標籤

而這正是問題。 Gson不知道你的數據是封裝的,它只關心它看到的字符串,它是一個對象。

拉動預覽,from here ...我們得到一共有三個對象

Event.java

(因爲你留下了什麼樣的JSON看起來這並沒有產生)

Embedded.java

import java.util.ArrayList; 
import java.util.List; 
import com.google.gson.annotations.Expose; 
import com.google.gson.annotations.SerializedName; 

public class Embedded { 

    @SerializedName("events") 
    @Expose 
    private List<Event> events = new ArrayList<Event>(); 

    public Embedded() { 
    } 

    public Embedded(List<Event> events) { 
     this.events = events; 
    } 

    public List<Event> getEvents() { 
     return events; 
    } 

    public void setEvents(List<Event> events) { 
     this.events = events; 
    } 

} 

Response.java

​​

而且,所以現在,改造在乎Call<Response>,你可以調用.getEmbedded().getEvents()


或者,你可以用MyDeserializer勾搭更多,因爲這似乎成爲現有代碼的問題。

+0

好的,它看起來很有效。非常感謝你!但我不知道這是否是最佳做法。我找不到使用GSON和改進的反序列化Jsons的適當解決方案或優秀教程。有沒有人有這種問題的經驗? – dudeck

+0

改造只是使用GSON直接,這樣你就可以從公式,除非你有自定義解串器 –

+1

我只會加重帽子歌廳EventsList可觀察的樣子取出那件: eventRest.getResponse(BuildConfig.PLACE_ID) .MAP(響應:: getEmbedded) .map(Embedded :: getEvents) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); – dudeck