• 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;
        }
    
    
    }
    
    
    
     
  • 相关阅读:
    用 Web 实现一个简易的音频编辑器
    TypeScript教程
    他的独,殇情沉醉
    重新拎一遍js的正则表达式
    网络流
    Xmind最新的安装与破解教程
    adb的端口号5037被占用的解决方法
    使用Fiddler模拟弱网测试教程
    web的前台、后台、前端、后端
    常见面试笔试题
  • 原文地址:https://www.cnblogs.com/sunxianbiao/p/12806736.html
Copyright © 2020-2023  润新知