问题
I'm using Retrofit in my app. I've got JSON response which looks like this:
{
"data": {
"list": [
{
"id": 58,
"beacon_id": "58",
"bridge_id": null,
"mesh_id": null,
"name": "eon_3c",
"location": "abcdlk",
"mac_address": "3c:cf:82:8a:e7:fe",
"firmware": "2.1",
"pcb_revision": "2.0",
"battery_level": "99",
"password": "0000",
"ib": {
"turn_on": "1",
"major": "33",
"minor": "344",
"tx_power": "7",
"interval": "400",
"uuid": "dae19960-18ea-11e5-8ff0-0002a5d5c521",
"secure_uuid": "0"
},
"euid": {
"turn_on": "0",
"namespace": null,
"instance": null,
"tx_power": null,
"interval": null
},
"eeid": {
"turn_on": "0",
"tx_power": null,
"interval": null
},
"eurl": {
"turn_on": "0",
"tx_power": null,
"interval": null,
"url": null
},
"etlm": {
"turn_on": "0",
"tx_power": null,
"interval": null
},
"assigned_bridge_id": null
},
{
"id": 56,
"beacon_id": "56",
"bridge_id": null,
"mesh_id": null,
"name": "Eon_e6",
"location": "test",
"mac_address": "e6:f5:8a:94:b8:c7",
"firmware": "2.1",
"pcb_revision": "2.0",
"battery_level": null,
"password": "0000",
"ib": {
"turn_on": "1",
"major": "2591",
"minor": "0",
"tx_power": "10",
"interval": "2593",
"uuid": "dae19960-18ea-11e5-8ff0-0002a5d5c521",
"secure_uuid": "0"
},
"euid": {
"turn_on": "0",
"namespace": null,
"instance": null,
"tx_power": null,
"interval": null
},
"eeid": {
"turn_on": "0",
"tx_power": null,
"interval": null
},
"eurl": {
"turn_on": "0",
"tx_power": null,
"interval": null,
"url": null
},
"etlm": {
"turn_on": "0",
"tx_power": null,
"interval": null
},
"assigned_bridge_id": null
},
{
"id": 57,
"beacon_id": "57",
"bridge_id": "13",
"mesh_id": "278",
"name": "Marta B",
"location": "lk",
"mac_address": "e1:4b:64:c3:80:e2",
"firmware": "2.1",
"pcb_revision": "2.0",
"battery_level": "97",
"password": "0000",
"ib": {
"turn_on": "1",
"major": "325",
"minor": "10",
"tx_power": "8",
"interval": "610",
"uuid": "dae19960-18ea-11e5-8ff0-0002a5d5c521",
"secure_uuid": "0"
},
"euid": {
"turn_on": "0",
"namespace": null,
"instance": null,
"tx_power": null,
"interval": null
},
"eeid": {
"turn_on": "0",
"tx_power": null,
"interval": null
},
"eurl": {
"turn_on": "0",
"tx_power": null,
"interval": null,
"url": null
},
"etlm": {
"turn_on": "0",
"tx_power": null,
"interval": null
},
"assigned_bridge_id": null
}
]
},
"ver": 1,
"time": 1475671202,
"status": 1,
"status_msg": ""
}
Here's my response class:
public class BeaconResponse {
@Expose
public Data data;
@Expose
public int ver;
@Expose
public int time;
@Expose
public int status;
@Expose
public String statusMsg;
}
In the Data class I've got List with List objects. I know it's bad naming, sorry.
public class Data extends Model {
@Column
public java.util.List<List> list;
}
And here's my List.class:
public class List {
public Integer id;
public String beaconId;
public String bridgeId;
public String meshId;
public String name;
public String location;
public String macAddress;
public String firmware;
public String pcbRevision;
public String batteryLevel;
public String password;
public Ib ib;
public Euid euid;
public Eeid eeid;
public Eurl eurl;
public Etlm etlm;
public int assignedBridgeId;
}
I think it should work, but it doesn't. When I try to map it to the model class I'm getting 3 objects ResponseList.size = 3 but all fields are null: data, statusMSG and so on. Can you tell me why this is? Thanks in advance for helping :)
My interface :
@GET("/api/mobile/{language}/{apiVersion}/beacons/list")
void beaconsList(Callback<BasicResponse<BeaconsListResponse>> callback);
public class BeaconsListResponse {
@Expose
public List<BeaconResponse> list;
}
Here's my retrofit call:
@Subscribe
public void getUserBeacons(GetBeaconsListCommand command) {
Callback<BasicResponse<BeaconsListResponse>> callback = new Callback<BasicResponse<BeaconsListResponse>>() {
@Override
public void success(BasicResponse<BeaconsListResponse> basicResponse, Response response) {
if (ResponseStatus.SUCCESS.statusCode == basicResponse.status)
EventBus.post(new BeaconsListFetchedEvent(basicResponse.data));
else
EventBus.post(new NetworkFailureEvent(ResponseStatus.getByStatus(basicResponse.status), basicResponse.status_msg));
}
@Override
public void failure(RetrofitError error) {
}
};
service.beaconsList(callback);
}
Main response class:
public class BasicResponse<T> {
@Expose
public T list;
@Expose
public int ver;
@Expose
public long time;
@Expose
public byte status;
@Expose
public String status_msg;
}
回答1:
Perhaps you should create your response class like this:
@SerializedName("list")
@Expose
private List<Data> list = new ArrayList<Data>();
Try creating your Response class through this tool:
http://www.jsonschema2pojo.org/
回答2:
The issue is that your Java classes do not mimic your JSON schema. You Java classes need to match the JSON schema exactly, or GSON will not be able to deserialize the data. This should better represent your schema:
public class StandardResponse<T> {
@SerializedName("data") public T data;
@SerializedName("ver") public Integer version;
@SerializedName("time") public Long time;
@SerializedName("status") public Integer status;
@SerializedName("status_msg") public String statusMessage;
}
Then you can implement a ListData class that contains a List:
public class ListData<T> {
@SerializedName("list") public List<T> list;
}
Then on to your Beacon class:
public class Beacon {
@SerializedName("id") public Integer id;
@SerializedName("beacon_id") public String beaconID;
@SerializedName("bridge_id") public String bridgeID;
@SerializedName("mesh_id") public String meshID;
@SerializedName("name") public String name;
@SerializedName("location") public String location;
@SerializedName("mac_address") public String macAddress;
@SerializedName("firmware") public String firmware;
@SerializedName("pcb_revision") public String pcbRevision;
@SerializedName("battery_level") public String batteryLevel;
@SerializedName("password") public String password;
@SerializedName("ib") public Ib ib;
@SerializedName("euid") public Euid euid;
@SerializedName("eeid") public Eeid eeid;
@SerializedName("eurl") public Eurl eurl;
@SerializedName("etlm") public Etlm etlm;
@SerializedName("assigned_bridge_id") public String assignedBridgeID;
}
I will skip your Ib, Euid, Edid, Eurl and Etlm classes, as they should not be too difficult to implement based on the classes above.
With these classes, your Retrofit Callback should look like this:
@GET("/api/mobile/{language}/{apiVersion}/beacons/list")
void getBeacons(Callback<StandardResponse<ListData<Beacon>> callback);
And finally, you can obtain your list of Beacon objects from the callback like so:
service.getBeacons(new Callback<StandardResponse<ListData<Beacon>>> {
@Override
public void success(StandardResponse<ListData<Beacon>> standard, Response response) {
Log.d(TAG, "Status: " + standard.status + "; with message: " + standard.statusMessage);
List<Beacon> beacons = standard.data.list;
for(Beacon beacon: beacons) {
Log.d(TAG, "Beacon ID: " + beacon.id);
}
}
@Override
public void failure(RetrofitError error) {
// TODO: implement error handling
}
});
Based on your sample JSON, the above code should print the following in logcat:
Status: 1, with message:
Beacon ID: 58
Beacon ID: 56
Beacon ID: 57
Update
Here are the Ib, Euid, Edid, Eurl and Etlm classes:
public class Ib {
@SerializedName("turn_on") public String turnOn;
@SerializedName("major") public String major;
@SerializedName("minor") public String minor;
@SerializedName("tx_power") public String txPower;
@SerializedName("interval") public String interval;
@SerializedName("uuid") public String uuid;
@SerializedName("secure_uuid") public String uuidSecure;
}
public class Euid {
@SerializedName("turn_on") public String turnOn;
@SerializedName("namespace") public String nameSpace;
@SerializedName("instance") public String instance;
@SerializedName("tx_power") public String txPower;
@SerializedName("interval") public String interval;
}
public class Edid {
@SerializedName("turn_on") public String turnOn;
@SerializedName("tx_power") public String txPower;
@SerializedName("interval") public String interval;
}
public class Eurl {
@SerializedName("turn_on") public String turnOn;
@SerializedName("tx_power") public String txPower;
@SerializedName("interval") public String interval;
@SerializedName("url") public String url;
}
public class Etlm {
@SerializedName("turn_on") public String turnOn;
@SerializedName("tx_power") public String txPower;
@SerializedName("interval") public String interval;
}
来源:https://stackoverflow.com/questions/39892816/retrofit-parsing-json-null-exception-at-response