序列化和反序列化_demo
参考:一文搞懂序列化与反序列化 - 知乎 (zhihu.com)
一、jdk序列化和反序列化
module结构:
FactInfo.java
package com.hmb; import java.io.Serial; import java.io.Serializable; public class FactInfo implements Serializable { @Serial private static final long serialVersionUID = 8059875275354456501L; private Integer id; private String name; public FactInfo(Integer id, String name) { this.id = id; this.name = name; } @Override public String toString() { return "[" + id.toString() + name.toString() + "]"; } }
TestBean.java
package com.hmb; import java.io.Serial; import java.io.Serializable; import java.util.Date; import java.util.List; public class TestBean implements Serializable { @Serial private static final long serialVersionUID = -444249457751783736L; private Integer id; private String name; private Date date; private FactInfo factInfo; public void setFactInfos(List<FactInfo> factInfos) { this.factInfos = factInfos; } private List<FactInfo> factInfos; public TestBean(Integer id, String name, Date date, FactInfo factInfo) { this.id = id; this.name = name; this.date = date; this.factInfo = factInfo; } @Override public String toString() { String factinfoStr = ""; for (FactInfo factInfo : factInfos) { factinfoStr += factInfo.toString(); } return id.toString() + name.toString() + date.toString() + factInfo.toString() + factinfoStr; } }
Main.java
package com.hmb; import java.io.*; import java.util.Date; import java.util.LinkedList; import java.util.List; public class Main { public static void main(String[] args) { TestBean testBean = new TestBean(1, "zhangsan", new Date(), new FactInfo(1, "fact1")); List<FactInfo> factInfos = new LinkedList<>(); factInfos.add(new FactInfo(2, "fact2")); factInfos.add(new FactInfo(3, "fact3")); testBean.setFactInfos(factInfos); FileOutputStream fileOutputStream; try { System.out.println(testBean.toString()); fileOutputStream = new FileOutputStream("test.txt"); ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream); objectOutputStream.writeObject(testBean); ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("test.txt")); TestBean testBean1 = (TestBean) objectInputStream.readObject(); System.out.println(testBean1.toString()); } catch (IOException e) { throw new RuntimeException(e); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } }
运行效果:
二、使用Jackson序列化和反序列化
参考:(15条消息) Jackson之ObjectMapper对象的使用_jackson objectmapper_blwinner的博客-CSDN博客
FactInfo.java
package com.hmb; import java.io.Serial; import java.io.Serializable; public class FactInfo implements Serializable { @Serial private static final long serialVersionUID = 8059875275354456501L; private Integer id; private String name; public FactInfo(Integer id, String name) { this.id = id; this.name = name; } public FactInfo() { } public Integer getId() { return id; } public String getName() { return name; } public void setId(Integer id) { this.id = id; } public void setName(String name) { this.name = name; } @Override public String toString() { return "[" + id.toString() + name.toString() + "]"; } }
TestBean.java
package com.hmb; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; import java.io.Serial; import java.io.Serializable; import java.util.Date; import java.util.List; public class TestBean implements Serializable { @Serial private static final long serialVersionUID = -444249457751783736L; private Integer id; private String name; private Date date; private FactInfo factInfo; private List<FactInfo> factInfos; public TestBean(Integer id, String name, Date date, FactInfo factInfo) { this.id = id; this.name = name; this.date = date; this.factInfo = factInfo; } public TestBean() { } // 经测试发现没有set方法也能反序列化 public void setId(Integer id) { this.id = id; } public void setName(String name) { this.name = name; } public void setDate(Date date) { this.date = date; } public void setFactInfo(FactInfo factInfo) { this.factInfo = factInfo; } public Integer getId() { return id; } public String getName() { return name; } public Date getDate() { return date; } public FactInfo getFactInfo() { return factInfo; } public List<FactInfo> getFactInfos() { return factInfos; } public void setFactInfos(List<FactInfo> factInfos) { this.factInfos = factInfos; } @Override public String toString() { String factinfoStr = ""; for (FactInfo factInfo : factInfos) { factinfoStr += factInfo.toString(); } return id.toString() + name.toString() + date.toString() + factInfo.toString() + factinfoStr; } }
Main.java
package com.hmb; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.*; import java.util.Date; import java.util.LinkedList; import java.util.List; public class Main { public static void main(String[] args) { TestBean testBean = new TestBean(1, "lisi", new Date(), new FactInfo(2, "fact")); List<FactInfo> factInfos = new LinkedList<>(); factInfos.add(new FactInfo(3, "fact1")); factInfos.add(new FactInfo(4, "fact2")); testBean.setFactInfos(factInfos); System.out.println(testBean.toString()); byte[] bytes; ObjectMapper objectMapper = new ObjectMapper(); try { String json = objectMapper.writeValueAsString(testBean); System.out.println(json); bytes = json.getBytes("UTF-8"); TestBean testBean1 = objectMapper.readValue(bytes, TestBean.class); System.out.println(testBean1); } catch (JsonProcessingException e) { throw new RuntimeException(e); } catch (IOException e) { throw new RuntimeException(e); } } }
运行结果:
注意事项:
- 如果要序列化的类(包括成员类)没有get方法,或者不是用iDea自动生成的get、set方法,在序列化时会抛出以下错误
Exception in thread "main" java.lang.RuntimeException: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class com.hmb.TestBean and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)
at com.hmb.Main.main(Main.java:26)
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class com.hmb.TestBean and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77)
at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1191)
at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:313)
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:71)
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:33)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319)
at com.fasterxml.jackson.databind.ObjectMapper._configAndWriteValue(ObjectMapper.java:3905)
at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:3219)
at com.hmb.Main.main(Main.java:23)
- 如果没有无参构造函数,在反序列化时会抛出以下错误:
Exception in thread "main" java.lang.RuntimeException: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.hmb.TestBean` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: (byte[])"{"id":1,"name":"lisi","date":1686586930199,"factInfo":{"id":2,"name":"fact"},"factInfos":[{"id":3,"name":"fact1"},{"id":4,"name":"fact2"}]}"; line: 1, column: 2]
at com.hmb.Main.main(Main.java:29)
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.hmb.TestBean` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: (byte[])"{"id":1,"name":"lisi","date":1686586930199,"factInfo":{"id":2,"name":"fact"},"factInfos":[{"id":3,"name":"fact1"},{"id":4,"name":"fact2"}]}"; line: 1, column: 2]
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1452)
at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1028)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1297)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:326)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4013)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3091)
at com.hmb.Main.main(Main.java:26)
- 如果是序列化后,通过网络通信传递字节数组,然后再反序列化的,要确保两边使用的类在项目中绝对路径一致。