Jackson--反序列化的解析

项目中经常需要调用指定服务的接口,并且对返回的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;
    }


}

 

 

 

posted @ 2020-04-30 09:09  一家人  阅读(4442)  评论(0编辑  收藏  举报