我有一个json格式,我使用Jackson API
转换为Java对象模型。我正在使用Jaxsonxml
2.1.5解析器。 json响应如下所示。
{
"response": {
"name": "states",
"total-records": "1",
"content": {
"data": {
"name": "OK",
"details": {
"id": "1234",
"name": "Oklahoma"
}
}
}
}
}
现在json响应格式已经改变。如果total-records
为1
,则details
将是具有id
和name
属性的对象。但如果total-records
超过1
,则details
将是一个对象数组,如下所示:
{
"response": {
"name": "states",
"total-records": "4",
"content": {
"data": {
"name": "OK",
"details": [
{
"id": "1234",
"name": "Oklahoma"
},
{
"id": "1235",
"name": "Utah"
},
{
"id": "1236",
"name": "Texas"
},
{
"id": "1237",
"name": "Arizona"
}
]
}
}
}
}
我的Java Mapper类看起来像下面的json
响应。
@JsonIgnoreProperties(ignoreUnknown = true)
public class MapModelResponseList {
@JsonProperty("name")
private String name;
@JsonProperty("total-records")
private String records;
@JsonProperty(content")
private Model model;
public Model getModelResponse() {
return model;
}
public void setModel(Model model) {
this.model = model;
}
}
客户代码
package com.test.deserializer;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com..schema.model.Person;
public class TestClient {
public static void main(String[] args) {
String response1="{\"id\":1234,\"name\":\"Pradeep\"}";
TestClient client = new TestClient();
try {
Person response = client.readJSONResponse(response1, Person.class);
} catch (Exception e) {
e.printStackTrace();
}
}
public <T extends Object> T readJSONResponse(String response, Class<T> type) {
ObjectMapper mapper = new ObjectMapper();
mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
T result = null;
try {
result = mapper.readValue(response, type);
} catch (Exception e) {
e.printStackTrace();
}
return (T) result;
}
}
现在基于total-records
如何处理映射到Model
或Model
对象列表。请告诉我。
答案 0 :(得分:1)
您需要自定义反序列化程序。我们的想法是将对象处理与树处理混合和匹配。尽可能解析对象,但使用树(JSONNode
)进行自定义处理。
在MapModelResponseList
上,删除records
属性并添加List<Data>
数组,其中Data
只是id / name对的持有者类。您可以通过返回此列表的大小来获取总记录。
在反序列化器中,执行以下操作:
public final class MapModelDeserializer extends BeanDeserializer {
public MapModelDeserializer(BeanDeserializerBase src) {
super(src);
}
protected void handleUnknownProperty(JsonParser jp, DeserializationContext ctxt, Object beanOrClass, String propName) throws IOException, JsonProcessingException {
if ("content".equals(propName)) {
MapModelResponseList response = (MapModelResponseList) beanOrClass;
// this probably needs null checks!
JsonNode details = (JsonNode) jp.getCodec().readTree(jp).get("data").get("details");
// read as array and create a Data object for each element
if (details.isArray()) {
List<Data> data = new java.util.ArrayList<Data>(details.size());
for (int i = 0; i < details.size(); i++) {
Data d = jp.getCodec().treeToValue(details.get(i), Data.class);
data.add(d);
}
response.setData(data);
}
// read a single object
else {
Data d = jp.getCodec().treeToValue(details, Data.class);
response.setData(java.util.Collections.singletonList(d));
}
super.handleUnknownProperty(jp, ctxt, beanOrClass, propName);
}
请注意,您没有实现deserialize()
- 默认实现用于正常创建MapModelResponseList
。 handleUknownProperty()
用于处理content
元素。由于超级电话中的@JsonIgnoreProperties(ignoreUnknown = true)
,您忽略的其他数据将被忽略。
答案 1 :(得分:0)
这是一个较晚的答案,但是我用另一种方法解决了。可以像这样在Object
中捕获它来工作:
@JsonProperty("details")
public void setDetails(Object details) {
if (details instanceof List) {
setDetails((List) details);
} else if (details instanceof Map) {
setDetails((Map) details);
}
}
public void setDetails(List details) {
// your list handler here
}
public void setDetails(Map details) {
// your map handler here
}