一 、各个JSON技术的简介和优劣
- json-lib
json-lib最开始的也是应用最广泛的json解析工具,json-lib 不好的地方确实是依赖于很多第三方包,
包括commons-beanutils.jar,commons-collections-3.2.jar,commons-lang-2.6.jar,commons-logging-1.1.1.jar,ezmorph-1.0.6.jar,
对于复杂类型的转换,json-lib对于json转换成bean还有缺陷,比如一个类里面会出现另一个类的list或者map集合,json-lib从json到bean的转换就会出现问题。
json-lib在功能和性能上面都不能满足现在互联网化的需求。
- 开源的Jackson
相比json-lib框架,Jackson所依赖的jar包较少,简单易用并且性能也要相对高些。
而且Jackson社区相对比较活跃,更新速度也比较快。
Jackson对于复杂类型的json转换bean会出现问题,一些集合Map,List的转换出现问题。
Jackson对于复杂类型的bean转换Json,转换的json格式不是标准的Json格式
- Google的Gson
Gson是目前功能最全的Json解析神器,Gson当初是为因应Google公司内部需求而由Google自行研发而来,
但自从在2008年五月公开发布第一版后已被许多公司或用户应用。
Gson的应用主要为toJson与fromJson两个转换函数,无依赖,不需要例外额外的jar,能够直接跑在JDK上。
而在使用这种对象转换之前需先创建好对象的类型以及其成员才能成功的将JSON字符串成功转换成相对应的对象。
类里面只要有get和set方法,Gson完全可以将复杂类型的json到bean或bean到json的转换,是JSON解析的神器。
Gson在功能上面无可挑剔,但是性能上面比FastJson有所差距。
- 阿里巴巴的FastJson
Fastjson是一个Java语言编写的高性能的JSON处理器,由阿里巴巴公司开发。
无依赖,不需要例外额外的jar,能够直接跑在JDK上。
FastJson在复杂类型的Bean转换Json上会出现一些问题,可能会出现引用的类型,导致Json转换出错,需要制定引用。
FastJson采用独创的算法,将parse的速度提升到极致,超过所有json库。
综上4种Json技术的比较:在项目选型的时候可以使用Google的Gson和阿里巴巴的FastJson两种并行使用,
如果只是功能要求,没有性能要求,可以使用google的Gson,
如果有性能上面的要求可以使用Gson将bean转换json确保数据的正确,使用FastJson将Json转换Bean
二、Google的Gson包的使用简介。
2.1 主要类介绍
Gson类:解析json的最基础的工具类
JsonParser类:解析器来解析JSON到JsonElements的解析树
JsonElement类:一个类代表的JSON元素
JsonObject类:JSON对象类型
JsonArray类:JsonObject数组
TypeToken类:用于创建type,比如泛型List>
2.2 maven依赖
com.google.code.gson
gson
2.8.0
2.3 bean转换json
Gson gson = new Gson();
String json = gson.toJson(obj);
//obj是对象
2.4 json转换bean
Gson gson = new Gson();
String json = "{\"id\":\"2\",\"name\":\"Json技术\"}";
Book book = gson.fromJson(json, Book.class);
2.5 json转换复杂的bean,比如List,Set
将json转换成复杂类型的bean,需要使用TypeToken
Gson gson = new Gson();
String json = "[{\"id\":\"1\",\"name\":\"Json技术\"},{\"id\":\"2\",\"name\":\"java技术\"}]";
//将json转换成List
List list = gson.fromJson(json,new TypeToken() {}.getType());
//将json转换成Set
Set set = gson.fromJson(json,new TypeToken() {}.getType());
2.6 通过json对象直接操作json以及一些json的工具
a) 格式化Json
String json = "[{\"id\":\"1\",\"name\":\"Json技术\"},{\"id\":\"2\",\"name\":\"java技术\"}]";
Gson gson = new GsonBuilder().setPrettyPrinting().create();
JsonParser jp = new JsonParser();
JsonElement je = jp.parse(json);
json = gson.toJson(je);
b) 判断字符串是否是json,通过捕捉的异常来判断是否是json
String json = "[{\"id\":\"1\",\"name\":\"Json技术\"},{\"id\":\"2\",\"name\":\"java技术\"}]";
boolean jsonFlag;
try {
new JsonParser().parse(str).getAsJsonObject();
jsonFlag = true;
} catch (Exception e) {
jsonFlag = false;
}
c) 从json串中获取属性
String json = "{\"id\":\"1\",\"name\":\"Json技术\"}";
String propertyName = 'id';
String propertyValue = "";
try {
JsonParser jsonParser = new JsonParser();
JsonElement element = jsonParser.parse(json);
JsonObject jsonObj = element.getAsJsonObject();
propertyValue = jsonObj.get(propertyName).toString();
} catch (Exception e) {
propertyValue = null;
}
d) 除去json中的某个属性
String json = "{\"id\":\"1\",\"name\":\"Json技术\"}";
String propertyName = 'id';
JsonParser jsonParser = new JsonParser();
JsonElement element = jsonParser.parse(json);
JsonObject jsonObj = element.getAsJsonObject();
jsonObj.remove(propertyName);
json = jsonObj.toString();
e) 向json中添加属性
String json = "{\"id\":\"1\",\"name\":\"Json技术\"}";
String propertyName = 'desc';
Object propertyValue = "json各种技术的调研";
JsonParser jsonParser = new JsonParser();
JsonElement element = jsonParser.parse(json);
JsonObject jsonObj = element.getAsJsonObject();
jsonObj.addProperty(propertyName, new Gson().toJson(propertyValue));
json = jsonObj.toString();
f) 修改json中的属性
String json = "{\"id\":\"1\",\"name\":\"Json技术\"}";
String propertyName = 'name';
Object propertyValue = "json各种技术的调研";
JsonParser jsonParser = new JsonParser();
JsonElement element = jsonParser.parse(json);
JsonObject jsonObj = element.getAsJsonObject();
jsonObj.remove(propertyName);
jsonObj.addProperty(propertyName, new Gson().toJson(propertyValue));
json = jsonObj.toString();
g) 判断json中是否有属性
String json = "{\"id\":\"1\",\"name\":\"Json技术\"}";
String propertyName = 'name';
boolean isContains = false ;
JsonParser jsonParser = new JsonParser();
JsonElement element = jsonParser.parse(json);
JsonObject jsonObj = element.getAsJsonObject();
isContains = jsonObj.has(propertyName);
h) json中日期格式的处理
GsonBuilder builder = new GsonBuilder();
builder.setDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
Gson gson = builder.create();
然后使用gson对象进行json的处理,如果出现日期Date类的对象,就会按照设置的格式进行处理
i) json中对于Html的转义
Gson gson = new Gson();
这种对象默认对Html进行转义,如果不想转义使用下面的方法
GsonBuilder builder = new GsonBuilder();
builder.disableHtmlEscaping();
Gson gson = builder.create();
三、阿里巴巴的FastJson包的使用简介。
3.1 maven依赖
com.alibaba
fastjson
1.2.46
3.2 基础转换类
同上
3.3 bean转换json
将对象转换成格式化的json
JSON.toJSONString(obj,true);
将对象转换成非格式化的json
JSON.toJSONString(obj,false);
obj设计对象
对于复杂类型的转换,对于重复的引用在转成json串后在json串中出现引用的字符,比如 [0].books[1]
Student stu = new Student();
Set books= new HashSet();
Book book = new Book();
books.add(book);
stu.setBooks(books);
List list = new ArrayList();
for(int i=0;i<5;i++)
list.add(stu);
String json = JSON.toJSONString(list,true);
3.4 json转换bean
String json = "{\"id\":\"2\",\"name\":\"Json技术\"}";
Book book = JSON.parseObject(json, Book.class);
3.5 json转换复杂的bean,比如List,Map
String json = "[{\"id\":\"1\",\"name\":\"Json技术\"},{\"id\":\"2\",\"name\":\"java技术\"}]";
//将json转换成List
List list = JSON.parseObject(json,new TypeReference(){});
//将json转换成Set
Set set = JSON.parseObject(json,new TypeReference(){});
3.6 通过json对象直接操作json
a) 从json串中获取属性
String propertyName = 'id';
String propertyValue = "";
String json = "{\"id\":\"1\",\"name\":\"Json技术\"}";
JSONObject obj = JSON.parseObject(json);
propertyValue = obj.get(propertyName));
b) 除去json中的某个属性
String propertyName = 'id';
String propertyValue = "";
String json = "{\"id\":\"1\",\"name\":\"Json技术\"}";
JSONObject obj = JSON.parseObject(json);
Set set = obj.keySet();
propertyValue = set.remove(propertyName);
json = obj.toString();
c) 向json中添加属性
String propertyName = 'desc';
Object propertyValue = "json的玩意儿";
String json = "{\"id\":\"1\",\"name\":\"Json技术\"}";
JSONObject obj = JSON.parseObject(json);
obj.put(propertyName, JSON.toJSONString(propertyValue));
json = obj.toString();
d) 修改json中的属性
String propertyName = 'name';
Object propertyValue = "json的玩意儿";
String json = "{\"id\":\"1\",\"name\":\"Json技术\"}";
JSONObject obj = JSON.parseObject(json);
Set set = obj.keySet();
if(set.contains(propertyName))
obj.put(propertyName, JSON.toJSONString(propertyValue));
json = obj.toString();
e) 判断json中是否有属性
String propertyName = 'name';
boolean isContain = false;
String json = "{\"id\":\"1\",\"name\":\"Json技术\"}";
JSONObject obj = JSON.parseObject(json);
Set set = obj.keySet();
isContain = set.contains(propertyName);
f) json中日期格式的处理
Object obj = new Date();
String json = JSON.toJSONStringWithDateFormat(obj, "yyyy-MM-dd HH:mm:ss.SSS");
使用JSON.toJSONStringWithDateFormat,该方法可以使用设置的日期格式对日期进行转换
四、json-lib包的使用简介。
4.1 maven依赖
//json-lib 为官方api,只需java jdk >jdk15即可。需要依赖一下jar包
commons-beanutils
commons-beanutils
1.8.0
commons-collections
commons-collections
3.2.1
commons-lang
commons-lang
2.6
commons-logging
commons-logging
1.2
4.2 基础转换类
同上
4.3 bean转换json
a)将类转换成Json,obj是普通的对象,不是List,Map的对象
String json = JSONObject.fromObject(obj).toString();
b) 将List,Map转换成Json
String json = JSONArray.fromObject(list).toString();
String json = JSONArray.fromObject(map).toString();
4.4 json转换bean
String json = "{\"id\":\"1\",\"name\":\"Json技术\"}";
JSONObject jsonObj = JSONObject.fromObject(json);
Book book = (Book)JSONObject.toBean(jsonObj,Book.class);
4.5 json转换List,对于复杂类型的转换会出现问题
String json = "[{\"id\":\"1\",\"name\":\"Json技术\"},{\"id\":\"2\",\"name\":\"Java技术\"}]";
JSONArray jsonArray = JSONArray.fromObject(json);
JSONObject jsonObject;
T bean;
int size = jsonArray.size();
List list = new ArrayList(size);
for (int i = 0; i < size; i++) {
jsonObject = jsonArray.getJSONObject(i);
bean = (T) JSONObject.toBean(jsonObject, beanClass);
list.add(bean);
}
4.6 json转换Map
String jsonString = "{\"id\":\"1\",\"name\":\"Json技术\"}";
JSONObject jsonObject = JSONObject.fromObject(jsonString);
Iterator keyIter = jsonObject.keys();
String key;
Object value;
Map valueMap = new HashMap();
while (keyIter.hasNext()) {
key = (String) keyIter.next();
value = jsonObject.get(key).toString();
valueMap.put(key, value);
}
4.7 json对于日期的操作比较复杂,需要使用JsonConfig,比Gson和FastJson要麻烦多了
创建转换的接口实现类,转换成指定格式的日期
class DateJsonValueProcessor implements JsonValueProcessor{
public static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd HH:mm:ss.SSS";
private DateFormat dateFormat;
public DateJsonValueProcessor(String datePattern) {
try {
dateFormat = new SimpleDateFormat(datePattern);
} catch (Exception ex) {
dateFormat = new SimpleDateFormat(DEFAULT_DATE_PATTERN);
}
}
public Object processArrayValue(Object value, JsonConfig jsonConfig) {
return process(value);
}
public Object processObjectValue(String key, Object value,
JsonConfig jsonConfig) {
return process(value);
}
private Object process(Object value) {
return dateFormat.format[1];
Map birthDays = new HashMap();
birthDays.put("WolfKing",new Date());
JSONObject jsonObject = JSONObject.fromObject(birthDays, jsonConfig);
String json = jsonObject.toString();
System.out.println(json);
}
}
4.8 JsonObject 对于json的操作和处理
a) 从json串中获取属性
String jsonString = "{\"id\":\"1\",\"name\":\"Json技术\"}";
Object key = "name";
Object value = null;
JSONObject jsonObject = JSONObject.fromObject(jsonString);
value = jsonObject.get(key);
jsonString = jsonObject.toString();
b) 除去json中的某个属性
String jsonString = "{\"id\":\"1\",\"name\":\"Json技术\"}";
Object key = "name";
Object value = null;
JSONObject jsonObject = JSONObject.fromObject(jsonString);
value = jsonObject.remove(key);
jsonString = jsonObject.toString();
c) 向json中添加和修改属性,有则修改,无则添加
String jsonString = "{\"id\":\"1\",\"name\":\"Json技术\"}";
Object key = "desc";
Object value = "json的好东西";
JSONObject jsonObject = JSONObject.fromObject(jsonString);
jsonObject.put(key,value);
jsonString = jsonObject.toString();
d) 判断json中是否有属性
String jsonString = "{\"id\":\"1\",\"name\":\"Json技术\"}";
boolean containFlag = false;
Object key = "desc";
JSONObject jsonObject = JSONObject.fromObject(jsonString);
containFlag = jsonObject.containsKey(key);
五、注意事项
fastjson 和 jackson 在把对象序列化成json字符串的时候,是通过反射遍历出该类中的所有getter方法;
Gson 是通过反射遍历该类中的所有属性。
所以,在定义POJO中的布尔类型的变量时,不要使用isSuccess这种形式,而要直接使用success 。
六、示例
以上为网上摘抄,以下为实际项目中使用结果。
实体类为BaseVO.java
:
package com.zr.workflow.activiti.entity;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import com.alibaba.fastjson.JSONObject;
import com.zr.workflow.activiti.util.DateFormatUtil;
public class BaseVO implements Serializable {
private static final long serialVersionUID = 6165121688276341503L;
protected int id;
protected String createId;// 创建人
protected String createName;
protected String createTime;// 流程的创建时间
protected String endTime;// 流程的结束时间
protected String reason;
protected String owner;// 拥有者
// 申请的标题
protected String title;
// 业务类型
protected String businessType;
protected String deploymentId;// 流程部署id
protected String processInstanceId;// 流程实例id
protected String deleteReason;// 删除原因
protected String handledTaskId;// 已处理任务id
protected String handledTaskDefinitionKey;// 已处理节点
protected String handledTaskName;// 已处理节点名称
protected String assignedId;// 已处理节点的受理人
protected String assignedName;// 已处理节点的受理人
protected String toHandleTaskId;// 当前节点的任务id
protected String taskDefinitionKey;// 当前节点key
protected String toHandleTaskName;// 当前节点点名
protected String assign;// 当前节点的受理人
protected String assignName;// 当前节点的受理人
protected String description;// 描述
protected String businessKey;// 对应业务的id
protected String startTime;// 任务的开始时间
protected String operateTime;// 任务的结束时间(处理时间)
protected String claimTime;// 任务的签收时间
protected boolean isEnd;// 流程是否结束
protected boolean isSuspended;// 是否挂起
protected String processDefinitionId;// 流程定义id
protected String processDefinitionName;// 流程名称
protected String processDefinitionKey;// 流程key,任务跳转用
protected String processStatus;// 流程状态:待审批、审批通过、审批退回、归档、结束
protected int version;// 流程版本号
protected JSONObject contentInfo;// 流程的业务相关
private String candidate_ids;//下一节点执行人,多个用逗号隔开
private String candidate_names;//下一节点执行人,多个用逗号隔开
private List comments;//评论列表
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCreateId() {
return createId;
}
public void setCreateId(String createId) {
this.createId = createId;
}
public String getCreateName() {
return createName;
}
public void setCreateName(String createName) {
this.createName = createName;
}
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
public String getOwner() {
if (this.owner == null) {
this.owner = (null == task) ? "" : task.getOwner();
}
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public String getEndTime() {
if (this.endTime == null) {
Date endDate = (null == historicProcessInstance) ? null : historicProcessInstance.getEndTime();
endTime = endDate == null ? "" : DateFormatUtil.format(endDate);
}
return endTime;
}
public void setEndTime(String endTime) {
this.endTime = endTime;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getBusinessType() {
return businessType;
}
public void setBusinessType(String businessType) {
this.businessType = businessType;
}
public String getDeploymentId() {
if (this.deploymentId == null) {
this.deploymentId = (null == processInstance) ? "" : processInstance.getDeploymentId();
}
return deploymentId;
}
public void setDeploymentId(String deploymentId) {
this.deploymentId = deploymentId;
}
public String getProcessInstanceId() {
if (this.processInstanceId == null || "".equals(this.processInstanceId)) {
if (historicTaskInstance != null) {
this.processInstanceId = historicTaskInstance.getProcessInstanceId();
} else if (processInstance != null) {
this.processInstanceId = processInstance.getId();
} else {
this.processInstanceId = (null == historicProcessInstance) ? "" : historicProcessInstance.getId();
}
}
return processInstanceId;
}
public void setProcessInstanceId(String processInstanceId) {
this.processInstanceId = processInstanceId;
}
public String getDeleteReason() {
if (this.deleteReason == null) {
this.deleteReason = (null == historicTaskInstance) ? "" : historicTaskInstance.getDeleteReason();
}
return deleteReason;
}
public void setDeleteReason(String deleteReason) {
this.deleteReason = deleteReason;
}
public String getHandledTaskId() {
if (this.handledTaskId == null) {
this.handledTaskId = (null == historicTaskInstance) ? "" : historicTaskInstance.getId();
}
return handledTaskId;
}
public void setHandledTaskId(String handledTaskId) {
this.handledTaskId = handledTaskId;
}
public String getHandledTaskDefinitionKey() {
if (this.handledTaskDefinitionKey == null) {
this.handledTaskDefinitionKey = (null == historicTaskInstance) ? ""
: historicTaskInstance.getTaskDefinitionKey();
}
return handledTaskDefinitionKey;
}
public void setHandledTaskDefinitionKey(String handledTaskDefinitionKey) {
this.handledTaskDefinitionKey = handledTaskDefinitionKey;
}
public String getHandledTaskName() {
if (this.handledTaskName == null) {
this.handledTaskName = (null == historicTaskInstance) ? "" : historicTaskInstance.getName();
}
return handledTaskName;
}
public void setHandledTaskName(String handledTaskName) {
this.handledTaskName = handledTaskName;
}
public String getAssignedId() {
if (this.assignedId == null) {
this.assignedId = (null == historicTaskInstance) ? "" : historicTaskInstance.getAssignee();
}
return assignedId;
}
public void setAssignedId(String assignedId) {
this.assignedId = assignedId;
}
public String getAssignedName() {
return assignedName;
}
public void setAssignedName(String assignedName) {
this.assignedName = assignedName;
}
public String getToHandleTaskId() {
if (this.toHandleTaskId == null) {
this.toHandleTaskId = (null == task) ? "" : task.getId();
}
return toHandleTaskId;
}
public void setToHandleTaskId(String toHandleTaskId) {
this.toHandleTaskId = toHandleTaskId;
}
public String getTaskDefinitionKey() {
if (this.taskDefinitionKey == null) {
this.taskDefinitionKey = (null == task) ? "" : task.getTaskDefinitionKey();
}
return taskDefinitionKey;
}
public void setTaskDefinitionKey(String taskDefinitionKey) {
this.taskDefinitionKey = taskDefinitionKey;
}
public String getToHandleTaskName() {
if (this.toHandleTaskName == null) {
this.toHandleTaskName = (null == task) ? "" : task.getName();
}
return toHandleTaskName;
}
public void setToHandleTaskName(String toHandleTaskName) {
this.toHandleTaskName = toHandleTaskName;
}
public String getAssign() {
if (this.assign == null) {
this.assign = (null == task) ? "" : task.getAssignee();
}
return assign;
}
public void setAssign(String assign) {
this.assign = assign;
}
public String getAssignName() {
return assignName;
}
public void setAssignName(String assignName) {
this.assignName = assignName;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getBusinessKey() {
return businessKey;
}
public void setBusinessKey(String businessKey) {
this.businessKey = businessKey;
}
public String getStartTime() {
if (this.startTime == null) {
Date startDate = null;
if (historicTaskInstance != null) {
startDate = historicTaskInstance.getStartTime();
} else {
startDate = (null == historicProcessInstance) ? null : historicProcessInstance.getStartTime();
}
startTime = startDate == null ? "" : DateFormatUtil.format(startDate);
}
return startTime;
}
public void setStartTime(String startTime) {
this.startTime = startTime;
}
public String getOperateTime() {
if (this.operateTime == null) {
Date operateDate = (null == historicTaskInstance) ? null : historicTaskInstance.getEndTime();
operateTime = operateDate == null ? "" : DateFormatUtil.format(operateDate);
}
return operateTime;
}
public void setOperateTime(String operateTime) {
this.operateTime = endTime;
}
public String getClaimTime() {
if (this.claimTime == null) {
Date claimDate = (null == historicTaskInstance) ? null : historicTaskInstance.getClaimTime();
claimTime = claimDate == null ? "" : DateFormatUtil.format(claimDate);
}
return claimTime;
}
public void setClaimTime(String claimTime) {
this.claimTime = claimTime;
}
public boolean isEnd() {
return isEnd;
}
public void setEnd(boolean isEnd) {
this.isEnd = isEnd;
}
public boolean isSuspended() {
this.isSuspended = (null == processInstance) ? isSuspended : processInstance.isSuspended();
return isSuspended;
}
public void setSuspended(boolean isSuspended) {
this.isSuspended = isSuspended;
}
public String getProcessDefinitionId() {
if (processDefinitionId == null) {
if (processInstance != null) {
this.processDefinitionId = processInstance.getProcessDefinitionId();
} else {
this.processDefinitionId = (null == historicProcessInstance) ? ""
: historicProcessInstance.getProcessDefinitionId();
}
}
return processDefinitionId;
}
public void setProcessDefinitionId(String processDefinitionId) {
this.processDefinitionId = processDefinitionId;
}
public String getProcessDefinitionName() {
if (processDefinitionName == null) {
this.processDefinitionName = (null == processDefinition) ? "" : processDefinition.getName();
}
return processDefinitionName;
}
public void setProcessDefinitionName(String processDefinitionName) {
this.processDefinitionName = processDefinitionName;
}
public String getProcessDefinitionKey() {
if (processDefinitionKey == null) {
this.processDefinitionKey = (null == processDefinition) ? "" : processDefinition.getKey();
}
return processDefinitionKey;
}
public void setProcessDefinitionKey(String processDefinitionKey) {
this.processDefinitionKey = processDefinitionKey;
}
public String getProcessStatus() {
return processStatus;
}
public void setProcessStatus(String processStatus) {
this.processStatus = processStatus;
}
public int getVersion() {
if(version <= 0) {
version = (null == processDefinition) ? 0 : processDefinition.getVersion();
}
return version;
}
public void setVersion(int version) {
this.version = version;
}
public JSONObject getContentInfo() {
return contentInfo;
}
public void setContentInfo(JSONObject contentInfo) {
this.contentInfo = contentInfo;
}
public String getCandidate_ids() {
return null == candidate_ids ? null : candidate_ids.replaceAll("\\[", "").replaceAll("\"", "").replaceAll("\\]", "");
}
public void setCandidate_ids(String candidate_ids) {
this.candidate_ids = candidate_ids;
}
public String getCandidate_names() {
return null == candidate_names ? null : candidate_names.replaceAll("\\[", "").replaceAll("\"", "").replaceAll("\\]", "");
}
public void setCandidate_names(String candidate_names) {
this.candidate_names = candidate_names;
}
public void setComments(List commentList) {
this.comments = commentList;
}
public List getComments(){
return comments;
}
// 流程任务
public Task task;
// 运行中的流程实例
protected ProcessInstance processInstance;
// 历史的流程实例
protected HistoricProcessInstance historicProcessInstance;
// 历史任务
protected HistoricTaskInstance historicTaskInstance;
// 流程定义
protected ProcessDefinition processDefinition;
public void setTask(Task task) {
this.task = task;
}
public void setProcessInstance(ProcessInstance processInstance) {
this.processInstance = processInstance;
}
public void setHistoricProcessInstance(HistoricProcessInstance historicProcessInstance) {
this.historicProcessInstance = historicProcessInstance;
}
public void setProcessDefinition(ProcessDefinition processDefinition) {
this.processDefinition = processDefinition;
}
public void setHistoricTaskInstance(HistoricTaskInstance historicTaskInstance) {
this.historicTaskInstance = historicTaskInstance;
}
}
用Gson 将该实体类转成json时报以下异常:
java.lang.IllegalArgumentException: class org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity declares multiple JSON fields named key
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:170)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:100)
at com.google.gson.Gson.getAdapter(Gson.java:423)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:115)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:164)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:100)
at com.google.gson.Gson.getAdapter(Gson.java:423)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory.create(CollectionTypeAdapterFactory.java:53)
at com.google.gson.Gson.getAdapter(Gson.java:423)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:115)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:164)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:100)
at com.google.gson.Gson.getAdapter(Gson.java:423)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:56)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:125)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:243)
at com.google.gson.internal.bind.ObjectTypeAdapter.write(ObjectTypeAdapter.java:107)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:97)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:61)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69)
at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.write(MapTypeAdapterFactory.java:208)
at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.write(MapTypeAdapterFactory.java:145)
at com.google.gson.Gson.toJson(Gson.java:669)
at com.google.gson.Gson.toJson(Gson.java:648)
at com.google.gson.Gson.toJson(Gson.java:603)
at com.google.gson.Gson.toJson(Gson.java:583)
at net.northking.activiti.util.JsonUtil.toJson(JsonUtil.java:47)
原因是:子类和父类有相同的字段属性;
解决方法:
(1)重命名重复字段。因为重复的字段在第三方包中,所以该方法在本例中不可行。
(2)将实体类中需要打印的字段加上注解@Expose
,(本例将该类所有有get方法的属性都加上了) :
@Expose
protected int id;
@Expose
protected String createId;// 创建人
@Expose
protected String createName;
新建gson:
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
String json = gson.toJson(obj);
excludeFieldsWithoutExposeAnnotation
排除掉没有Expose注解的属性。
或者在不需要解析的字段前面加上transient
:
// 流程任务
public transient Task task;
// 运行中的流程实例
protected transient ProcessInstance processInstance;
// 历史的流程实例
protected transient HistoricProcessInstance historicProcessInstance;
// 历史任务
protected transient HistoricTaskInstance historicTaskInstance;
// 流程定义
protected transient ProcessDefinition processDefinition;
用该方式,没有报异常了,解析结果(加注解@Expose
或加transient
)如下:
{
"data": [{
"id": 0,
"createId": "admin",
"createName": "系统管理员",
"createTime": "2019-04-11 17:01:46",
"reason": "",
"title": "2019-04-01至2019-04-07工时填报",
"processInstanceId": "70013",
"handledTaskId": "70023",
"handledTaskDefinitionKey": "outsourcerApply",
"handledTaskName": "外包人员申请",
"assignedId": "admin",
"assignedName": "系统管理员",
"toHandleTaskId": "70039",
"taskDefinitionKey": "projectManagerAudit",
"toHandleTaskName": "项目经理审批",
"assign": "215",
"assignName": "郭俊杰",
"description": "您提出2019-04-01至2019-04-07工时填报",
"businessKey": "monthlyreportForProjectProcess:admin:20190401:20190407",
"isEnd": false,
"isSuspended": false,
"processDefinitionId": "monthlyreportForProjectProcess:1:70012",
"processDefinitionName": "工时填报(项目外包/行内人员)",
"processDefinitionKey": "monthlyreportForProjectProcess",
"processStatus": "WAITING_FOR_APPROVAL",
"version": 0,
"contentInfo": {
"contentInfoId": "39a14c350fa64a3ca26a50b4531307c6",
"ssoUser": "1",
"reportId": "39a14c350fa64a3ca26a50b4531307c6",
"createTime": "2019-04-11",
"reportRemark": "",
"reportStatus": "1",
"project": [{
"hoursTime": "5",
"percentTime": "0",
"managerId": "215",
"projectName": "其他",
"projectId": "other"
}],
"startTime": "2019-04-01",
"endTime": "2019-04-07",
"flowFlag": "create",
"userId": "admin"
},
"candidate_ids": "",
"candidate_names": "",
"comments": [{
"id": "70024",
"userId": "admin",
"userName": "系统管理员",
"content": "发起申请",
"taskId": "70023",
"processInstanceId": "70013",
"time": "2019-04-11 17:01:47",
"nextAssign": "215",
"nextAssignName": "郭俊杰"
}]
}],
"type": "success"
}
但从结果来看,那些直接调用第三方api获取值的属性没有解析,因为第三方的类无法加上@Expose注解
,导致这些属性为null
,而Gson默认的规则不会解析为null
的属性,比如:
public String getEndTime() {
if (this.endTime == null) {
Date endDate = (null == historicProcessInstance) ? null : historicProcessInstance.getEndTime();
endTime = endDate == null ? "" : DateFormatUtil.format(endDate);
}
return endTime;
}
(3)换解析方式:使用FastJson。
因为FastJson是通过getter方法获取属性,并把其值序列化成json字符串的,所以这里,我们这个实体类中去掉不想被解析的属性的get方法,变成如下:
public void setTask(Task task) {
this.task = task;
}
public void setProcessInstance(ProcessInstance processInstance) {
this.processInstance = processInstance;
}
public void setHistoricProcessInstance(HistoricProcessInstance historicProcessInstance) {
this.historicProcessInstance = historicProcessInstance;
}
public void setProcessDefinition(ProcessDefinition processDefinition) {
this.processDefinition = processDefinition;
}
public void setHistoricTaskInstance(HistoricTaskInstance historicTaskInstance) {
this.historicTaskInstance = historicTaskInstance;
}
fastJson、JackJson以及Gson序列化对象与get、set以及对象属性之间的关系