一、场景
1、将net.sf.json.JSONObject转为实体对象
2、将实体对象的List属性序列化(List属性的实体类以实现Serializable
接口)
3、序列化报错-java.io.NotSerializableException: net.sf.ezmorph.primitive.CharMorpher
二、报错信息
java.io.NotSerializableException: net.sf.ezmorph.primitive.CharMorpher
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
at java.util.ArrayList.writeObject(ArrayList.java:766)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:1140)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
at java.util.HashMap.internalWriteEntries(HashMap.java:1793)
at java.util.HashMap.writeObject(HashMap.java:1363)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:1140)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
三、代码
1、实体
package com.xxx.entity.serviceflow;
import lombok.Data;
import java.io.Serializable;
@Data
//注意:实体以实现Serializable接口
public class BranchNodeCondition implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private String paramName;
private String judgeType;
private String paramValue;
private Integer paramGroup;
private String pgJudgeType;
}
2、测试
package com.xxx;
import com.xxx.entity.serviceflow.BranchNodeCondition;
import com.xxx.entity.serviceflow.BranchNodeData;
import net.sf.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
//构建对象
BranchNodeData data = new BranchNodeData();
data.setBranchId(1L);
data.setBranchJumpId(10L);
data.setBranchMemo("默认");
data.setBranchType("1");
data.setSeq(0);
//设置conditionList属性
List<BranchNodeCondition> conditionList = new ArrayList<>();
BranchNodeCondition condition = new BranchNodeCondition();
condition.setId(1L);
condition.setJudgeType("0");
condition.setParamGroup(1);
condition.setParamName("name");
condition.setParamValue("盖伦 与 卡特琳娜");
condition.setPgJudgeType("0");
conditionList.add(condition);
data.setConditionList(conditionList);
JSONObject json = JSONObject.fromObject(data);
System.out.println("BranchNodeData转为json字符串:\n" + json);
System.out.println("\n-------------华丽的分割线-------------\n");
//------以下代码为重点,前面的代码只是铺垫------
BranchNodeData o = (BranchNodeData) JSONObject.toBean(json, BranchNodeData.class);
System.out.println("json字符串转为BranchNodeData:\n" + o.toString() + "\n");
//将conditionList序列化(执行到这里报错)
ListUtil.deepCopy(o.getConditionList());
}
}
四、原因
1、从表面上看List集合存储的是BranchNodeCondition
类型的对象,该类确实已经实现Serializable
接口,正常应该是可以序列化的
2、但实际上List集合存储的是net.sf.ezmorph.bean.MorphDynaBean
类型的对象,该类可没有实现Serializable
接口
为什么?
3、JsonObject 对象强转 Java对象,且JsonObject对象中含有数组类型(ArrayList)的属性时会出现这种情况
4、在转换时不会报错,
但是想要拿到转换后的数组进行操作(例如for循环)时会报错java.lang.ClassCastException: net.sf.ezmorph.bean.MorphDynaBean cannot be cast to com.xxx.entity.xxx
,
序列化也会报错java.io.NotSerializableException: net.sf.ezmorph.primitive.CharMorpher
5、以本篇代码为例,可以看到强转后的conditionList
属性类型与原先的属性类型是不一致的(原先类型为:BranchNodeCondition
,转换后却是:net.sf.ezmorph.bean.MorphDynaBean
)
BranchNodeData转为json字符串:
{"branchId":1,"branchJumpId":10,"branchMemo":"默认","branchType":"1","conditionList":[{"id":1,"judgeType":"0","paramGroup":1,"paramName":"name","paramValue":"盖伦 与 卡特琳娜","pgJudgeType":"0"}],"seq":0}
-------------华丽的分割线-------------
json字符串转为BranchNodeData:
BranchNodeData(branchId=1, seq=0, branchType=1, branchMemo=默认, branchJumpId=10, conditionList=[net.sf.ezmorph.bean.MorphDynaBean@396e2f39[
{paramGroup=1, judgeType=0, id=1, paramName=name, paramValue=盖伦 与 卡特琳娜, pgJudgeType=0}
]])
五、解决
JsonObject中含有List属性,所以需要用map映射一下
以本篇为例
//注释掉原先转换的代码
//BranchNodeData o = (BranchNodeData) JSONObject.toBean(json, BranchNodeData.class);
//定义Map映射
Map<String,Class<?>> classMap = new HashMap<>();
//Map-Key为实体对象List属性的属性名称
//Map-Value为实体对象List属性的属性类型
classMap.put("conditionList", BranchNodeCondition.class);
//指定Map映射
BranchNodeData o = (BranchNodeData) JSONObject.toBean(json, BranchNodeData.class, classMap);
使用Map映射之后的List集合就可以序列化了