序列化和反序列化_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)

  

  • 如果是序列化后,通过网络通信传递字节数组,然后再反序列化的,要确保两边使用的类在项目中绝对路径一致。
posted @ 2023-06-12 23:10  hemeiwolong  阅读(10)  评论(0编辑  收藏  举报