我在解析自定义响应时遇到问题,因为我有一个具有本地化属性的响应。
我收到如下所示的回复:
[
{
"id": "dummyID1",
"name.en_US": "dummyNameEn1",
"name.fi_FI": "dummyNameFi1"
},
{
"id": "dummyID2",
"name.en_US": "dummyNameEn2",
"name.fi_FI": "dummyNameFi2"
},
{
"id": "dummyID3",
"name.en_US": "dummyNameEn3",
"name.fi_FI": "dummyNameFi3"
}...
]
为了解析我已经创建了一个自定义类Device.java
:
public class Device {
public String id;
public LocalizedString name;
public Device(String id, LocalizedString name) {
this.id = id;
this.name = name;
}
//Getters and setters
}
现在我们有一个名为 LocalizedString.java
的自定义对象:
public class LocalizedString implements Parcelable {
public static final Creator<LocalizedString> CREATOR = new Creator<LocalizedString>() {
@Override
public LocalizedString createFromParcel(Parcel in) {
return new LocalizedString(in);
}
@Override
public LocalizedString[] newArray(int size) {
return new LocalizedString[size];
}
};
private String en_US;
private String fi_FI;
public LocalizedString(String en, String fi) {
this.en_US = en;
this.fi_FI = fi;
}
protected LocalizedString(Parcel in) {
en_US = in.readString();
fi_FI = in.readString();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(en_US);
dest.writeString(fi_FI);
}
//Getters, setters
}
现在在我的回复中,我想创建一个Device's
列表,但它似乎不明白"本地化字符串"是如何工作的。由于我的请求返回<List<Device>>
因此我也无法真正自定义解析它。
以下是我尝试解析它的方式:
Call<List<Device>> call = getMainActivity().getRestClient().getDevices();
call.enqueue(new Callback<List<Device>>() {
@Override
public void onResponse(Call<List<Device>> call, Response<List<Device>> response) {
if (isAttached()) {
if (response.isSuccessful()) {
// get data
List<Device> items = response.body();
}
}
}
@Override
public void onFailure(Call<List<Device>> call, Throwable t) {
if (isAttached()) {
Logger.debug(getClass().getName(), "Could not fetch installation document devices past orders", t);
getMainActivity().showError(R.string.error_network);
}
}
});
和:
@GET("document/devices")
Call<List<Device>> gettDevices();
在这种情况下,我应该怎么做才能将name
绑定到Device
,然后能够获得en_US
或fi_FI
.
最好你可以这样写
public class Device {
@SerializedName("id")
public String id;
@SerializedName("name.en_US")
public String en;
@SerializedName("name.fi_FI")
public String fi;
public Device(String id, String english, String fi) {
this.id = id;
this.en = english;
this.fi = fi;
}
//Getters and setters
}
如果您可以控制 JSON 的来源,那么修改该 JSON 结构很容易解决您的问题。
如果您不能,我们可以用来解决您的问题的一种方法是使用 Jackson 和自定义反序列化程序:
public class DeviceDeserializer extends StdDeserializer<Device> {
public DeviceDeserializer() {
this(null);
}
public DeviceDeserializer(Class<?> vc) {
super(vc);
}
@Override
public Device deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
JsonNode node = jp.getCodec().readTree(jp);
String id = getStringValue(node, "id");
String en = getStringValue(node, "name.en_EN");
String fi = getStringValue(node, "name.fi_FI");
LocalizedString localized = new LocalizedString(en, fi);
return new Device(id, localizedString);
}
private String getStringValue(JsonNode node, String key) {
// Throws exception or use null is up to you to decide
return Optional.ofNullable(node.get("id"))
.map(JsonNode::asText)
.orElse(null);
}
}
自己手动注册反序列化程序或使用注释:
@JsonDeserialize(using = DeviceDeserializer.class)
public class Device {
...
请注意,您必须启用改装杰克逊转换器插件:(请参阅改造配置部分(
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(JacksonConverterFactory.create())
.build();
阅读以下内容:使用改造使用 GSON 获取嵌套的 JSON 对象