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; } }