項目中經常需要調用指定服務的接口,並且對返回的json結果數據,進行反序列化生成java類。
若是返回的數據格式固定,那么直接按照固定的格式進行反序列化生成java類便可。但是由於
返回的結果數據格式不固定,需要自己編寫反序列化類進行分析。
下面我講展示下項目中遇到的情況。
{ "status": "200", "Goal": { "userId": "17090016", "templateId": "26", "templateName": "測試-營銷通用目標模板", "performance": [ { "id": "8022", "indexCode": "", "name": "執行績效綜合達成率", "category": "New Category", "categoryName": "執行績效", "start": "2019-10-01T00:00:00.000", "due": "2019-10-31T00:00:00.000", "bizxTarget": "", "bizxActual": "", "done": "0.0", "higedone": "", "stateLabel": "重大延遲", "weight": "", "dataSource": "", "lastModified": "2019-12-11T08:45:47.000", "modifier": "17090016", "children": "" }, { "id": "8015", "indexCode": "", "name": "協訪達成率", "category": "Goals", "categoryName": "先決條件", "start": "2019-10-01T00:00:00.000", "due": "2019-10-31T00:00:00.000", "bizxTarget": "47.0", "bizxActual": "73.0", "done": "0.0", "higedone": "100.0", "stateLabel": "重大延遲", "weight": "", "dataSource": "手持", "lastModified": "2019-12-11T13:57:09.000", "modifier": "17090016", "children": { "childDescription": "CS協訪", "childTarget": "15", "childActual": "18", "childDone": "100.0" } }, { "id": "8017", "indexCode": "", "name": "分銷達成率", "category": "New Category", "categoryName": "執行績效", "start": "2019-10-01T00:00:00.000", "due": "2019-10-31T00:00:00.000", "bizxTarget": "100.0", "bizxActual": "23.39", "done": "23.39", "higedone": "100.0", "stateLabel": "重大延遲", "weight": "20.0", "dataSource": "訂單管理", "lastModified": "2019-12-11T14:09:32.000", "modifier": "17090016", "children": [ { "childDescription": "門店數", "childTarget": "", "childActual": "23", "childDone": "" }, { "childDescription": "門店品類數", "childTarget": "", "childActual": "31", "childDone": "" }, { "childDescription": "門店SKU", "childTarget": "", "childActual": "25", "childDone": "" } ] }
}
上面的json格式數據中,其余的字段格式都是比較的固定,但是可以看到children的數據內容出現了3種:
1、字符串內容
2、對象
3、數組
由於children的內容格式不固定,則直接利用jackson進行反序列化會失敗,所以需要我們自己編寫反序列化的實現類。
但是只是children的內容格式不固定,我們只是需要對children編寫反序列化的實現類。
代碼如下;
整個json對應的javabean
package com.shinho.plrs.front.pojo; import com.fasterxml.jackson.annotation.JsonGetter; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.util.List; @Data @ApiModel("指標") @JsonIgnoreProperties(ignoreUnknown = true) public class Target { @ApiModelProperty("id") String id; @ApiModelProperty("指標編碼") String code; @JsonGetter("code") public String getCode() { return this.code; } @JsonSetter(value = "indexCode") public void setCode(String code) { this.code = code; } @ApiModelProperty("指標名稱") String purpose; @ApiModelProperty("指標類型編碼") String category; @ApiModelProperty("指標類型名稱") String categoryName; @JsonProperty("start") @ApiModelProperty("開始日期") String startDate; @JsonProperty("due") @ApiModelProperty("結束日期") String endDate; @ApiModelProperty("目標") String aim; @ApiModelProperty("實際") String acture; @ApiModelProperty("達成率") String done; @ApiModelProperty("達成率封頂值") String higedone; @ApiModelProperty("狀態(文本)") String stateLabel; @ApiModelProperty("權重") String weight; @ApiModelProperty("數據來源") String dataSource; @ApiModelProperty("最近修改時間") String lastModified; @ApiModelProperty("修改人") String modifier; // @ApiModelProperty("子指標數據") // List<Child> childs = new ArrayList<>(); @ApiModelProperty("子指標數據") @JsonDeserialize(using = ChildrenDeserializer.class) List<Child> children; }
package com.shinho.plrs.front.pojo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.experimental.Accessors; @Data @ApiModel("子指標") @Accessors(chain = true) public class Child { @ApiModelProperty("子指標描述") String childDescription; @ApiModelProperty("子指標目標") String childTarget; @ApiModelProperty("子指標完成值") String childActual; @ApiModelProperty("子指標達成率") String childDone; }
反序列化類的實現:
package com.shinho.plrs.front.pojo; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.util.StringUtils; import java.io.IOException; import java.util.ArrayList; import java.util.List; @Slf4j public class ChildrenDeserializer extends StdDeserializer<List<Child>> { public ChildrenDeserializer() { super(List.class); } public ChildrenDeserializer(Class<?> vc) { super(vc); } @Override public List<Child> deserialize(JsonParser parser, DeserializationContext deserializer) throws IOException { List<Child> list = new ArrayList<>(); if (StringUtils.isEmpty(parser.getText())) return list; if (JsonToken.START_ARRAY.equals(parser.getCurrentToken())) { while (!JsonToken.END_ARRAY.equals(parser.getCurrentToken())) { list.add(parseJsonObjectToChild(parser)); parser.nextToken(); } } else if (JsonToken.START_OBJECT.equals(parser.getCurrentToken())) { list.add(parseJsonObjectToChild(parser)); } return list; } /** * 將json數據分析成java對象 * * @param parser * @return */ private Child parseJsonObjectToChild(JsonParser parser) throws IOException { Child child = new Child(); JsonToken token = parser.getCurrentToken(); String fieldName = null; while (!JsonToken.END_OBJECT.equals(token)) { if (!JsonToken.FIELD_NAME.equals(token)) { token = parser.nextToken(); continue; } fieldName = parser.getCurrentName(); token = parser.nextToken(); try { BeanUtils.getPropertyDescriptor(Child.class, fieldName).getWriteMethod().invoke(child, parser.getText()); token = parser.nextToken(); } catch (Exception e) { log.error("反序列化child過程中,出現異常:", e); } } return child; } }