欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Jackson--反序列化的解析

程序员文章站 2022-07-09 19:34:13
项目中经常需要调用指定服务的接口,并且对返回的json结果数据,进行反序列化生成java类。 若是返回的数据格式固定,那么直接按照固定的格式进行反序列化生成java类便可。但是由于 返回的结果数据格式不固定,需要自己编写反序列化类进行分析。 下面我讲展示下项目中遇到的情况。 { "status": ......

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


}