Gson、FastJson、Jackson、json-lib對比總結(jié)

一 、各個JSON技術(shù)的簡介和優(yōu)劣

  1. json-lib

json-lib最開始的也是應(yīng)用最廣泛的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,
對于復雜類型的轉(zhuǎn)換,json-lib對于json轉(zhuǎn)換成bean還有缺陷,比如一個類里面會出現(xiàn)另一個類的list或者map集合,json-lib從json到bean的轉(zhuǎn)換就會出現(xiàn)問題。
json-lib在功能和性能上面都不能滿足現(xiàn)在互聯(lián)網(wǎng)化的需求。

  1. 開源的Jackson

相比json-lib框架,Jackson所依賴的jar包較少,簡單易用并且性能也要相對高些。
而且Jackson社區(qū)相對比較活躍,更新速度也比較快。
Jackson對于復雜類型的json轉(zhuǎn)換bean會出現(xiàn)問題,一些集合Map,List的轉(zhuǎn)換出現(xiàn)問題。
Jackson對于復雜類型的bean轉(zhuǎn)換Json,轉(zhuǎn)換的json格式不是標準的Json格式

  1. Google的Gson

Gson是目前功能最全的Json解析神器,Gson當初是為因應(yīng)Google公司內(nèi)部需求而由Google自行研發(fā)而來,
但自從在2008年五月公開發(fā)布第一版后已被許多公司或用戶應(yīng)用。
Gson的應(yīng)用主要為toJson與fromJson兩個轉(zhuǎn)換函數(shù),無依賴,不需要例外額外的jar,能夠直接跑在JDK上。
而在使用這種對象轉(zhuǎn)換之前需先創(chuàng)建好對象的類型以及其成員才能成功的將JSON字符串成功轉(zhuǎn)換成相對應(yīng)的對象。
類里面只要有g(shù)et和set方法,Gson完全可以將復雜類型的json到bean或bean到j(luò)son的轉(zhuǎn)換,是JSON解析的神器。
Gson在功能上面無可挑剔,但是性能上面比FastJson有所差距。

  1. 阿里巴巴的FastJson

Fastjson是一個Java語言編寫的高性能的JSON處理器,由阿里巴巴公司開發(fā)。
無依賴,不需要例外額外的jar,能夠直接跑在JDK上。
FastJson在復雜類型的Bean轉(zhuǎn)換Json上會出現(xiàn)一些問題,可能會出現(xiàn)引用的類型,導致Json轉(zhuǎn)換出錯,需要制定引用。
FastJson采用獨創(chuàng)的算法,將parse的速度提升到極致,超過所有json庫。

綜上4種Json技術(shù)的比較:在項目選型的時候可以使用Google的Gson和阿里巴巴的FastJson兩種并行使用,
如果只是功能要求,沒有性能要求,可以使用google的Gson,
如果有性能上面的要求可以使用Gson將bean轉(zhuǎn)換json確保數(shù)據(jù)的正確,使用FastJson將Json轉(zhuǎn)換Bean

二、Google的Gson包的使用簡介。

2.1 主要類介紹
Gson類:解析json的最基礎(chǔ)的工具類
JsonParser類:解析器來解析JSON到JsonElements的解析樹
JsonElement類:一個類代表的JSON元素
JsonObject類:JSON對象類型
JsonArray類:JsonObject數(shù)組
TypeToken類:用于創(chuàng)建type,比如泛型List<?>

2.2 maven依賴

    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.8.0</version>
    </dependency>

2.3 bean轉(zhuǎn)換json

Gson gson = new Gson();
String json = gson.toJson(obj);
//obj是對象

2.4 json轉(zhuǎn)換bean

Gson gson = new Gson();
String json = "{\"id\":\"2\",\"name\":\"Json技術(shù)\"}";
Book book = gson.fromJson(json, Book.class);

2.5 json轉(zhuǎn)換復雜的bean,比如List,Set
將json轉(zhuǎn)換成復雜類型的bean,需要使用TypeToken

Gson gson = new Gson();
String json = "[{\"id\":\"1\",\"name\":\"Json技術(shù)\"},{\"id\":\"2\",\"name\":\"java技術(shù)\"}]";
//將json轉(zhuǎn)換成List
List list = gson.fromJson(json,new TypeToken<LIST>() {}.getType());
//將json轉(zhuǎn)換成Set
Set set = gson.fromJson(json,new TypeToken<SET>() {}.getType());

2.6 通過json對象直接操作json以及一些json的工具

a) 格式化Json

String json = "[{\"id\":\"1\",\"name\":\"Json技術(shù)\"},{\"id\":\"2\",\"name\":\"java技術(shù)\"}]";
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技術(shù)\"},{\"id\":\"2\",\"name\":\"java技術(shù)\"}]";
boolean jsonFlag;
try {
new JsonParser().parse(str).getAsJsonObject();
jsonFlag = true;
} catch (Exception e) {
jsonFlag = false;
}

c) 從json串中獲取屬性

String json = "{\"id\":\"1\",\"name\":\"Json技術(shù)\"}";
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技術(shù)\"}";
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技術(shù)\"}";
String propertyName = 'desc';
Object propertyValue = "json各種技術(shù)的調(diào)研";
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技術(shù)\"}";
String propertyName = 'name';
Object propertyValue = "json各種技術(shù)的調(diào)研";
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技術(shù)\"}";
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的處理,如果出現(xiàn)日期Date類的對象,就會按照設(shè)置的格式進行處理
i) json中對于Html的轉(zhuǎn)義

Gson gson = new Gson();

這種對象默認對Html進行轉(zhuǎn)義,如果不想轉(zhuǎn)義使用下面的方法

GsonBuilder builder = new GsonBuilder();
builder.disableHtmlEscaping();
Gson gson = builder.create();

三、阿里巴巴的FastJson包的使用簡介。

3.1 maven依賴

    <!-- FastJson將Json轉(zhuǎn)換Bean -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.46</version>
    </dependency>

3.2 基礎(chǔ)轉(zhuǎn)換類
同上
3.3 bean轉(zhuǎn)換json
將對象轉(zhuǎn)換成格式化的json

JSON.toJSONString(obj,true);

將對象轉(zhuǎn)換成非格式化的json

JSON.toJSONString(obj,false);

obj設(shè)計對象
對于復雜類型的轉(zhuǎn)換,對于重復的引用在轉(zhuǎn)成json串后在json串中出現(xiàn)引用的字符,比如 ref":"[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轉(zhuǎn)換bean

String json = "{\"id\":\"2\",\"name\":\"Json技術(shù)\"}";
Book book = JSON.parseObject(json, Book.class);

3.5 json轉(zhuǎn)換復雜的bean,比如List,Map

String json = "[{\"id\":\"1\",\"name\":\"Json技術(shù)\"},{\"id\":\"2\",\"name\":\"java技術(shù)\"}]";
//將json轉(zhuǎn)換成List
List list = JSON.parseObject(json,new TypeReference<ARRAYLIST>(){});
//將json轉(zhuǎn)換成Set
Set set = JSON.parseObject(json,new TypeReference<HASHSET>(){});

3.6 通過json對象直接操作json
a) 從json串中獲取屬性

String propertyName = 'id';
String propertyValue = "";
String json = "{\"id\":\"1\",\"name\":\"Json技術(shù)\"}";
JSONObject obj = JSON.parseObject(json);
propertyValue = obj.get(propertyName));

b) 除去json中的某個屬性

String propertyName = 'id';
String propertyValue = "";
String json = "{\"id\":\"1\",\"name\":\"Json技術(shù)\"}";
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技術(shù)\"}";
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技術(shù)\"}";
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技術(shù)\"}";
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,該方法可以使用設(shè)置的日期格式對日期進行轉(zhuǎn)換

四、json-lib包的使用簡介。

4.1 maven依賴

//json-lib 為官方api,只需java jdk >jdk15即可。需要依賴一下jar包
      <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>1.8.0</version>
        </dependency>
        <dependency>
            <groupId>commons-collections</groupId>
            <artifactId>commons-collections</artifactId>
            <version>3.2.1</version>
        </dependency>
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>

        <!-- slf4j日志依賴 -->
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>

4.2 基礎(chǔ)轉(zhuǎn)換類
同上
4.3 bean轉(zhuǎn)換json
a)將類轉(zhuǎn)換成Json,obj是普通的對象,不是List,Map的對象

String json = JSONObject.fromObject(obj).toString();

b) 將List,Map轉(zhuǎn)換成Json

String json = JSONArray.fromObject(list).toString();
String json = JSONArray.fromObject(map).toString();

4.4 json轉(zhuǎn)換bean

String json = "{\"id\":\"1\",\"name\":\"Json技術(shù)\"}";
JSONObject jsonObj = JSONObject.fromObject(json);
Book book = (Book)JSONObject.toBean(jsonObj,Book.class);

4.5 json轉(zhuǎn)換List,對于復雜類型的轉(zhuǎn)換會出現(xiàn)問題

String json = "[{\"id\":\"1\",\"name\":\"Json技術(shù)\"},{\"id\":\"2\",\"name\":\"Java技術(shù)\"}]";
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轉(zhuǎn)換Map

String jsonString = "{\"id\":\"1\",\"name\":\"Json技術(shù)\"}";
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要麻煩多了
創(chuàng)建轉(zhuǎn)換的接口實現(xiàn)類,轉(zhuǎn)換成指定格式的日期

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<STRING,DATE> birthDays = new HashMap<STRING,DATE>();
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技術(shù)\"}";
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技術(shù)\"}";
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技術(shù)\"}";
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技術(shù)\"}";
boolean containFlag = false;
Object key = "desc";
JSONObject jsonObject = JSONObject.fromObject(jsonString);
containFlag = jsonObject.containsKey(key);

五、注意事項

fastjsonjackson 在把對象序列化成json字符串的時候,是通過反射遍歷出該類中的所有g(shù)etter方法;
Gson 是通過反射遍歷該類中的所有屬性。
所以,在定義POJO中的布爾類型的變量時,不要使用isSuccess這種形式,而要直接使用success

六、示例

以上為網(wǎng)上摘抄,以下為實際項目中使用結(jié)果。
實體類為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;// 創(chuàng)建人
    protected String createName;
    protected String createTime;// 流程的創(chuàng)建時間
    protected String endTime;// 流程的結(jié)束時間
    protected String reason;
    protected String owner;// 擁有者
    // 申請的標題
    protected String title;
    // 業(yè)務(wù)類型
    protected String businessType;
    protected String deploymentId;// 流程部署id
    protected String processInstanceId;// 流程實例id
    protected String deleteReason;// 刪除原因
    protected String handledTaskId;// 已處理任務(wù)id
    protected String handledTaskDefinitionKey;// 已處理節(jié)點
    protected String handledTaskName;// 已處理節(jié)點名稱
    protected String assignedId;// 已處理節(jié)點的受理人
    protected String assignedName;// 已處理節(jié)點的受理人
    protected String toHandleTaskId;// 當前節(jié)點的任務(wù)id
    protected String taskDefinitionKey;// 當前節(jié)點key
    protected String toHandleTaskName;// 當前節(jié)點點名
    protected String assign;// 當前節(jié)點的受理人
    protected String assignName;// 當前節(jié)點的受理人
    protected String description;// 描述
    protected String businessKey;// 對應(yīng)業(yè)務(wù)的id
    protected String startTime;// 任務(wù)的開始時間
    protected String operateTime;// 任務(wù)的結(jié)束時間(處理時間)
    protected String claimTime;// 任務(wù)的簽收時間
    protected boolean isEnd;// 流程是否結(jié)束
    protected boolean isSuspended;// 是否掛起
    protected String processDefinitionId;// 流程定義id
    protected String processDefinitionName;// 流程名稱
    protected String processDefinitionKey;// 流程key,任務(wù)跳轉(zhuǎn)用
    protected String processStatus;// 流程狀態(tài):待審批、審批通過、審批退回、歸檔、結(jié)束
    protected int version;// 流程版本號
    protected JSONObject contentInfo;// 流程的業(yè)務(wù)相關(guān)
    private String candidate_ids;//下一節(jié)點執(zhí)行人,多個用逗號隔開
    private String candidate_names;//下一節(jié)點執(zhí)行人,多個用逗號隔開

    private List<CommentVO> 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<CommentVO> commentList) {
        this.comments = commentList;
    }

    public List<CommentVO> getComments(){
        return comments;
    }

    // 流程任務(wù)
    public Task task;

    // 運行中的流程實例
    protected ProcessInstance processInstance;

    // 歷史的流程實例
    protected HistoricProcessInstance historicProcessInstance;

    // 歷史任務(wù)
    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 將該實體類轉(zhuǎn)成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,(本例將該類所有有g(shù)et方法的屬性都加上了) :

    @Expose
    protected int id;
    @Expose
    protected String createId;// 創(chuàng)建人
    @Expose
    protected String createName;

新建gson:

Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
String json = gson.toJson(obj);

excludeFieldsWithoutExposeAnnotation排除掉沒有Expose注解的屬性。

或者在不需要解析的字段前面加上transient:


    // 流程任務(wù)
    public transient Task task;

    // 運行中的流程實例
    protected transient ProcessInstance processInstance;

    // 歷史的流程實例
    protected transient HistoricProcessInstance historicProcessInstance;

    // 歷史任務(wù)
    protected transient HistoricTaskInstance historicTaskInstance;

    // 流程定義
    protected transient ProcessDefinition processDefinition;

用該方式,沒有報異常了,解析結(jié)果(加注解@Expose或加transient)如下:

{
    "data": [{
        "id": 0,
        "createId": "admin",
        "createName": "系統(tǒng)管理員",
        "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": "系統(tǒng)管理員",
        "toHandleTaskId": "70039",
        "taskDefinitionKey": "projectManagerAudit",
        "toHandleTaskName": "項目經(jīng)理審批",
        "assign": "215",
        "assignName": "郭俊杰",
        "description": "您提出2019-04-01至2019-04-07工時填報",
        "businessKey": "monthlyreportForProjectProcess:admin:20190401:20190407",
        "isEnd": false,
        "isSuspended": false,
        "processDefinitionId": "monthlyreportForProjectProcess:1:70012",
        "processDefinitionName": "工時填報(項目外包/行內(nèi)人員)",
        "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": "系統(tǒng)管理員",
            "content": "發(fā)起申請",
            "taskId": "70023",
            "processInstanceId": "70013",
            "time": "2019-04-11 17:01:47",
            "nextAssign": "215",
            "nextAssignName": "郭俊杰"
        }]
    }],
    "type": "success"
}

但從結(jié)果來看,那些直接調(diào)用第三方api獲取值的屬性沒有解析,因為第三方的類無法加上@Expose注解,導致這些屬性為null,而Gson默認的規(guī)則不會解析為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以及對象屬性之間的關(guān)系

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,156評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,401評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,069評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,873評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,635評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,128評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,203評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,365評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,881評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,733評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,935評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,475評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,172評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,582評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,821評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,595評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,908評論 2 372

推薦閱讀更多精彩內(nèi)容