我有这个JSON正文:
[
{
"id": 0,
"field1": "10",
"field2": "22"
},
{
"id": 1,
"field1": "11",
"field2": "23"
}
]
我的pojoItem
:
@AutoValue
public abstract class PojoItem{
@SerializedName("field1")
public abstract String field1();
@SerializedName("id")
public abstract int id();
@SerializedName("field2")
public abstract String field2();
}
我的pojoItemList
:
@AutoValue
public abstract class PojoItemList{
public abstract List< PojoItem > itemList();
public static TypeAdapter<PojoItemList> typeAdapter(Gson gson) {
return new AutoValue_PojoItemList.GsonTypeAdapter(gson);
}
}
我有AutoValueGsonFactory
:
@GsonTypeAdapterFactory
public abstract class AutoValueGsonFactory implements TypeAdapterFactory {
// Static factory method to access the package
// private generated implementation
public static TypeAdapterFactory create() {
return new AutoValueGson_AutoValueGsonFactory();
}
}
我在RxJava上使用Retrofit。我有这个例外:
java.lang.IllegalStateException:预期BEGIN_OBJECT但是BEGIN_ARRAY
如何设置我的POJO以将JSON读作对象数组而不是集合?
答案 0 :(得分:1)
问题是您为列表指定了名称itemList
,但在回复中不存在。
改造应该适用于这样的事情:
public class Item {
@SerializedName("field1")
public String field1;
@SerializedName("id")
public int id;
@SerializedName("field2")
public String field2;
}
然后,当您定义Retrofit的界面时,请使用以下内容:
@GET("/path")
Single<List<Item>> getItems();
答案 1 :(得分:1)
AutoValue Gson不为数组生成Gson类型的适配器(至少从我从其源代码中看到的)。因此Gson期望一个List实例。请注意,列表数据模型与Gson默认值以及AutoValue Gson生成的内容冲突。你有两个解决方案。
PojoItemList
原因:数组/列表不需要itemsList()
之类的内容。我不确定您是否会在PojoItemList
中获得除itemList()
之外的任何其他自动生成的值。 List<PojoItem>
足以让它发挥作用。因此,有效地使用列表的原始Gson代码:
final Gson gson = new GsonBuilder()
.registerTypeAdapterFactory(AutoValueGsonFactory.create())
.create();
final TypeToken<List<PojoItem>> pojoItemListTypeToken = new TypeToken<List<PojoItem>>() {
};
out.println(gson.<List<PojoItem>>fromJson(JSON, pojoItemListTypeToken.getType()));
据我了解,Retrofit会将该类型传递给Gson本身,因此,在这种情况下,您的Retrofitted服务不得使用PojoItemList
,并使用List<PojoItem>
:
interface IService {
List<PojoItem> getPojoItems();
}
请注意,您必须为PojoItem
添加可由AutoValue Gson生成的类型适配器:
@AutoValue
public abstract class PojoItem {
...
public static TypeAdapter<PojoItem> typeAdapter(final Gson gson) {
return new AutoValue_PojoItem.GsonTypeAdapter(gson);
}
}
如果未生成并注册类型适配器,Gson将无法创建PojoItem
实例:
java.lang.RuntimeException:无法调用没有args的公共q42240399.PojoItem()
如果由于某种原因你想使用PojoItemList
,那么你必须编写自定义TypeAdapter
因为,正如我上面提到的,AutoValue Gson不会生成数组类型适配器(我无法做到)但是,请参阅任何beginArray
次调用。
@AutoValue
public abstract class PojoItemList {
public abstract List<PojoItem> itemList();
public static TypeAdapter<PojoItemList> typeAdapter(final Gson gson) {
// Get the original PojoItem type adapter you can use below
final TypeAdapter<PojoItem> pojoItemTypeAdapter = gson.getAdapter(PojoItem.class);
return new TypeAdapter<PojoItemList>() {
@Override
public void write(final JsonWriter out, final PojoItemList pojoItemList) {
out.beginArray();
for ( final PojoItem pojoItem : pojoItemList.itemList() ) {
pojoItemTypeAdapter.write(out, pojoItem);
}
out.endArray();
}
@Override
public PojoItemList read(final JsonReader in)
throws IOException {
final List<PojoItem> pojoItems = new ArrayList<>();
// The first token must be [
in.beginArray();
// And read until ] is found
while ( in.peek() != END_ARRAY ) {
// Delegate parsing to the PojoItem type adapter for each array element
pojoItems.add(pojoItemTypeAdapter.read(in));
}
// The last token must be ]
in.endArray();
// Construct the PojoItemList value
return new AutoValue_PojoItemList(pojoItems);
}
};
}
}
您可能想要求AutoValue Gson扩展作者实现符合阵列的扩展。但是,我认为解决方案#1因为几个原因而好得多。
两种解决方案都有效并将产生:
List<PojoItem>
:[PojoItem{field1=10, id=0, field2=22}, PojoItem{field1=11, id=1, field2=23}]
PojoItemList
:PojoItemList{itemList=[PojoItem{field1=10, id=0, field2=22}, PojoItem{field1=11, id=1, field2=23}]}
答案 2 :(得分:0)
我可以在有/没有RxJava的情况下使其工作 这有两种方式:
为了说清楚,我将提供用于实现该目标的API和完整的改造代码:
AppApi:
public interface AppApi {
@GET("path/path")
Observable<List<PojoItem>> getItemsbyRxJava();
@GET("path/path")
Call<List<PojoItem>> getItemsbyRetrofit();
}
使用RxJava解决方案:
GsonConverterFactory gsonConverterFactory = GsonConverterFactory.create(new GsonBuilder().registerTypeAdapterFactory(AutoValueGsonFactory.create()).create());
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
Retrofit retrofitClient = new Retrofit.Builder()
.baseUrl("http://[domain]/path/")
.addConverterFactory(gsonConverterFactory)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(httpClient.build())
.build();
AppApi appApi = retrofitClient.create(AppApi.class);
appApi.getItemsbyRxJava()
.subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<List<PojoItem>>() {
@Override
public void onCompleted() {
Log.d(TAG, "completed");
}
@Override
public void onError(Throwable e) {
Log.e(TAG, e.getMessage());
}
@Override
public void onNext(List<PojoItem> list) {
for (PojoItem pojoItem : list) {
Log.d(TAG, pojoItem.field1() + "," + pojoItem.field2());
}
}
});
仅限改装的解决方案:
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
Retrofit retrofitClient = new Retrofit.Builder()
.baseUrl("http://[domain]/path/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(httpClient.build())
.build();
AppApi appApi = retrofitClient.create(AppApi.class);
Call<List<PojoItem>> call = appApi.getItemsbyRetrofit();
call.enqueue(new Callback<List<PojoItem>>() {
@Override
public void onResponse(Call<List<PojoItem>> call, Response<List<PojoItem>> response) {
for (PojoItem pojoItem : response.body()) {
Log.d(TAG, pojoItem.field1() + "," + pojoItem.field2());
}
}
@Override
public void onFailure(Call<List<PojoItem>> call, Throwable t) {
Log.e(TAG, t.getMessage());
}
});
我希望这会对某人有所帮助
祝你好运,'。