我正在使用Retrofit来获取JSON回复。
以下是我的实施部分 -
@GET("/api/report/list")
Observable<Bills> listBill(@Query("employee_id") String employeeID);
和班级比尔是 -
public static class Bills {
@SerializedName("report")
public ArrayList<BillItem> billItems;
}
BillItem
类如下 -
public static class BillItem {
@SerializedName("id")
Integer entryID;
@SerializedName("employee_id")
Integer employeeDBID;
@SerializedName("type")
String type;
@SerializedName("subtype")
String subtype;
@SerializedName("date")
String date;
@SerializedName("to")
String to;
@SerializedName("from")
String from;
@SerializedName("amount")
Double amount;
@SerializedName("location")
String location;
@SerializedName("remark")
String remark;
@SerializedName("ispaid")
String isPaid;
@SerializedName("created_at")
String createdAt;
@SerializedName("updated_at")
String updateAt;
}
问题是REST API有时返回BillItem
个对象的数组,但有时它只是key-value
对。如何处理这种情况?
收到此回复后,一切正常,因为JSONArray
已映射到ArrayList<BillItem>
-
{
"emp":{
"id":41,
"name":"",
"email":"",
"created_at":"2016-02-01 10:36:38",
"updated_at":"2016-02-01 10:36:38"
},
"report":[
{
"id":175,
"employee_id":41,
"type":"Travel",
"subtype":"Car",
"date":"2016-02-02 00:00:00",
"to":"gaha",
"from":"hshsj",
"amount":"64",
"location":"",
"remark":"shhs",
"ispaid":false,
"created_at":"2016-02-01 13:52:52",
"updated_at":"2016-02-01 13:52:52"
},
{
"id":179,
"employee_id":41,
"type":"Travel",
"subtype":"Car",
"date":"2016-02-01 00:00:00",
"to":"Gsh",
"from":"Dgdh",
"amount":"7646",
"location":"",
"remark":"Shsh",
"ispaid":false,
"created_at":"2016-02-01 14:39:48",
"updated_at":"2016-02-01 14:39:48"
}
]
}
但是,有时响应是这样的,它会给出JsonSyntaxException
-
{
"emp":{
"id":41,
"name":"",
"email":"",
"created_at":"2016-02-01 10:36:38",
"updated_at":"2016-02-01 10:36:38"
},
"report":{
"1":{
"id":175,
"employee_id":41,
"type":"Travel",
"subtype":"Car",
"date":"2016-02-02 00:00:00",
"to":"gaha",
"from":"hshsj",
"amount":"64",
"location":"",
"remark":"shhs",
"ispaid":false,
"created_at":"2016-02-01 13:52:52",
"updated_at":"2016-02-01 13:52:52"
},
"2":{
"id":179,
"employee_id":41,
"type":"Travel",
"subtype":"Car",":"2016-02-01 00:00:00",
"to":"Gsh",
"from":"Dgdh",
"amount":"7646",
"location":"",
"remark":"Shsh",
"ispaid":false,
"created_at":"2016-02-01 14:39:48",
"updated_at":"2016-02-01 14:39:48"
},
"0":{
"id":181,
"employee_id":41,
"type":"Travel",
"subtype":"Car",
"date":"2016-02-01 00:00:00",
"to":"ggg",
"from":"vg",
"amount":"0",
"location":"",
"remark":"cvv",
"ispaid":false,
"created_at":"2016-02-01 17:43:43",
"updated_at":"2016-02-01 17:43:43"
},
"3":{
"id":182,
"employee_id":41,
"type":"Travel",
"subtype":"Car",
"date":"2016-02-01 00:00:00",
"to":"Haha",
"from":"Ahah",
"amount":"0",
"location":"",
"remark":"Ahah",
"ispaid":false,
"created_at":"2016-02-01 17:53:58",
"updated_at":"2016-02-01 17:53:58"
}
}
}
如何处理这样的回复?
答案 0 :(得分:6)
使用Gson反序列化器时,可以检查JsonElement中的类型:
<title><?php if (is_front_page()) { bloginfo('name');echo ' | ';bloginfo('description'); } elseif ( is_category() ) { single_cat_title(); echo ' - ' ; bloginfo('name'); }
elseif (is_single() ) { single_post_title(); }
elseif (is_page() ) { bloginfo('name'); echo ' | '; single_post_title(); }
else { wp_title('',true); } ?></title>
参见示例:Gson deserialization - Trying to parse a JSON to an Object
答案 1 :(得分:1)
正如answer @Gavriel所述,需要编写自定义Deserializer
。
这是我的实现(它可能包含多余的代码) -
实际API
定义 -
public interface ServerAPI {
public static final String ENDPOINT = "http://xyz";
@GET("/api/report/list")
Observable<Bills> listBill(@Query("employee_id") String employeeID);
public static class BillItem {
@SerializedName("id")
public Integer entryID;
@SerializedName("employee_id")
public Integer employeeDBID;
@SerializedName("type")
public String type;
@SerializedName("subtype")
public String subtype;
@SerializedName("date")
public String date;
@SerializedName("to")
public String to;
@SerializedName("from")
public String from;
@SerializedName("amount")
public Double amount;
@SerializedName("location")
public String location;
@SerializedName("remark")
public String remark;
@SerializedName("ispaid")
public String isPaid;
@SerializedName("created_at")
public String createdAt;
@SerializedName("updated_at")
public String updateAt;
}
public static class Bills {
@SerializedName("report") // This seems to serve no purpose.
public ArrayList<BillItem> billItems = new ArrayList<>(); // It was needed to initialize the ArrayList.
public void add(BillItem billItem) {
billItems.add(billItem);
}
}
}
这是我们在收到回复时实际创建BillItem
类的地方。
public class App extends Application {
private static App instance;
private static ServerAPI serverAPI;
public static ServerAPI getServerAPI() {
return serverAPI;
}
@Override
public void onCreate() {
super.onCreate();
Gson gson = new GsonBuilder()
.registerTypeAdapter(BillItem.class, new BillItemDeserializer())
.registerTypeAdapter(Bills.class, new BillsDeserializer())
.create();
instance = this;
serverAPI = new RestAdapter.Builder()
.setEndpoint(ServerAPI.ENDPOINT)
.setConverter(new GsonConverter(gson))
.setLogLevel(RestAdapter.LogLevel.FULL)
.setLog(new RestAdapter.Log() {
@Override
public void log(String message) {
Log.v("Retrofit", message);
}
})
.build().create(ServerAPI.class);
}
// This has nothing inside of it, it still works.
public class BillItemDeserializer implements JsonDeserializer<BillItem> {
@Override
public BillItem deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context) throws
JsonParseException {
return null;
}
}
private class BillsDeserializer implements JsonDeserializer<Bills> {
@Override
public Bills deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context) throws
JsonParseException {
Bills value = new Bills();
Gson gson = new Gson();
json = json.getAsJsonObject().get("report");
if (json.isJsonArray()) {
for (JsonElement element : json.getAsJsonArray()) {
value.add(gson.fromJson(element, BillItem.class));
}
} else {
JsonElement element = json.getAsJsonObject();
Set<Map.Entry<String, JsonElement>> entries = element.getAsJsonObject().entrySet();
for (Map.Entry<String, JsonElement> entry : entries) {
value.add(gson.fromJson(entry.getValue(), BillItem.class));
}
}
return value;
}
}
}
这是我们收到数据的Subscription
对象。
Subscription subscription = App.getServerAPI()
.listBill(String.valueOf(employeeID))
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<ServerAPI.Bills>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
Log.i(TAG, "ERROR: Value returned: " + e.getMessage());
e.printStackTrace();
}
@Override
public void onNext(ServerAPI.Bills bills) {
for (ServerAPI.BillItem item : bills.billItems) {
Log.i(TAG, "onNextBillItem: " + item);
}
}
});