Java序列化與反序列化(原生方式與Jackson方式)

image.png

Java序列化與反序列化

微信公眾號

當兩個進程在進行遠程通信時,彼此可以發送各種類型的數據。無論是何種類型的數據,都會以二進制序列的形式在網絡上傳送。發送方需要把這個Java對象轉換為字節序列,才能在網絡上傳送;接收方則需要把字節序列再恢復為Java對象。

現在主要的序列化方式主要是兩個種。一種是Java原生以流的方法進行的序列化,另外一種就是Json序列化方式。我這里Json的序列化方式主要是以Jackson為例。

1. Java原生序列化

這種方式只能將支持 java.io.Serializable 接口的對象寫入流中。每個 serializable 對象的類都被編碼,編碼內容包括類名和類簽名、對象的字段值和數組值,以及從初始對象中引用的其他所有對象的閉包。

概念

  • 序列化:把Java對象轉換為字節序列的過程。
  • 反序列化:把字節序列恢復為Java對象的過程。

用途

  • 把對象的字節序列永久地保存到硬盤上,通常存放在一個文件中;
  • 在網絡上傳送對象的字節序列。

對象序列化

java.io.ObjectOutputStream代表對象輸出流,它的writeObject(Object obj)方法可對參數指定的obj對象進行序列化,把得到的字節序列寫到一個目標輸出流中。只有實現了Serializable和Externalizable接口的類的對象才能被序列化。

java.io.ObjectInputStream代表對象輸入流,它的readObject()方法從一個源輸入流中讀取字節序列,再把它們反序列化為一個對象,并將其返回。

  • 示例代碼
import java.io.*;
import java.util.Date;

public class ObjectSaver {
    public static void main(String[] args) throws Exception {
        /*其中的  ./objectFile.obj 表示存放序列化對象的文件*/

        
        //序列化對象
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("./objectFile.obj"));
        Customer customer = new Customer("王麻子", 24);    
        out.writeObject("你好!");    //寫入字面值常量
        out.writeObject(new Date());    //寫入匿名Date對象
        out.writeObject(customer);    //寫入customer對象
        out.close();

        
        //反序列化對象
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("./objectFile.obj"));
        System.out.println("obj1 " + (String) in.readObject());    //讀取字面值常量
        System.out.println("obj2 " + (Date) in.readObject());    //讀取匿名Date對象
        Customer obj3 = (Customer) in.readObject();    //讀取customer對象
        System.out.println("obj3 " + obj3);
        in.close();
    }
}

class Customer implements Serializable {
    private String name;
    private int age;
    public Customer(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String toString() {
        return "name=" + name + ", age=" + age;
    }
}

2. 使用Jackson序列化對象

準備工作:

ObjectMapper mapper = new ObjectMapper(); //轉換器
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

將對象序列化

主要使用的是writeValueAsString的函數

String json=mapper.writeValueAsString(user); //將對象轉換成json

將Json字符串對象化(反序列化)

主要使用的是readValue的函數

Map m = mapper.readValue(json, Map.class);

編程實現

  • User類
public class User
{
    private String id; //標識
    private String name;    //姓名
    private int age;    //年齡
    private double pay; //工資
    private boolean valid;  //是否有效
    private char one; //一個字符
    @JsonFormat(pattern = "yyyy-mm-dd")
    private Date birthday;  //生日

    private Link link; //聯系方式,自定義

    private Map map; //測試用
    private List list; //測試用
    private Set set; //測試用

    public String getId()
    {
        return id;
    }
    public void setId(String id)
    {
        this.id = id;
    }
    public String getName()
    {
        return name;
    }
    public void setName(String name)
    {
        this.name = name;
    }
    public int getAge()
    {
        return age;
    }
    public void setAge(int age)
    {
        this.age = age;
    }
    public double getPay()
    {
        return pay;
    }
    public void setPay(double pay)
    {
        this.pay = pay;
    }
    public boolean isValid()
    {
        return valid;
    }
    public void setValid(boolean valid)
    {
        this.valid = valid;
    }
    public char getOne()
    {
        return one;
    }
    public void setOne(char one)
    {
        this.one = one;
    }
    public Date getBirthday()
    {
        return birthday;
    }
    public void setBirthday(Date birthday)
    {
        this.birthday = birthday;
    }
    public Link getLink()
    {
        return link;
    }
    public void setLink(Link link)
    {
        this.link = link;
    }
    public Map getMap()
    {
        return map;
    }
    public void setMap(Map map)
    {
        this.map = map;
    }
    public List getList()
    {
        return list;
    }
    public void setList(List list)
    {
        this.list = list;
    }
    public Set getSet()
    {
        return set;
    }
    public void setSet(Set set)
    {
        this.set = set;
    }
}
  • Link類
public class Link
{
    private String phone; //移動電話
    private String address; //地址
    private String qq; //QQ


    public String getPhone()
    {
        return phone;
    }
    public void setPhone(String phone)
    {
        this.phone = phone;
    }
    public String getAddress()
    {
        return address;
    }
    public void setAddress(String address)
    {
        this.address = address;
    }
    public String getQq()
    {
        return qq;
    }
    public void setQq(String qq)
    {
        this.qq = qq;
    }
}
  • 主函數
public class JacksonTest {
    public static void main(String[] args) throws JsonGenerationException,JsonMappingException,IOException {
        User user=new User();
        user.setId("01");
        user.setName("張三");
        user.setAge(33);
        user.setPay(6666.88);
        user.setValid(true);
        user.setOne('E');
        user.setBirthday(new Date(20l*366*24*3600*1000)); //1990年

        Link link = new Link();
        link.setAddress("河南省濟源市");
        link.setPhone("13899995555");
        link.setQq("123456");
        user.setLink(link);

        Map map=new HashMap();
        map.put("aa", "this is aa");
        map.put("bb", "this is bb");
        map.put("cc", "this is cc");
        user.setMap(map);

        List list=new ArrayList(){};
        list.add("普洱");
        list.add("大紅袍");
        user.setList(list);

        Set set=new HashSet();
        set.add("籃球");
        set.add("足球");
        set.add("乒乓球");
        user.setSet(set);

        ObjectMapper mapper = new ObjectMapper(); //轉換器

        //測試01:對象--json
        String json=mapper.writeValueAsString(user); //將對象轉換成json
        System.out.println(json);
        /* 結果如下:
        {"id":"01","name":"張三","age":33,"pay":6666.88,"valid":true,"one":"E","birthday":1465185448998,
        "link":{"phone":"13899995555","address":"河南省濟源市","qq":"123456"},
        "map":{"aa":"this is aa","bb":"this is bb","cc":"this is cc"},
        "list":["普洱","大紅袍"],
        "set":["乒乓球","足球","籃球"]}

        注意點:(1) 日期--長整型 (2)List、Set均轉成數組
         */

        //測試02:json--map
        Map m = mapper.readValue(json, Map.class); //json轉換成map

        System.out.println("pay:"+m.get("pay").getClass().getName()); //java.lang.Double
        System.out.println("valid:"+m.get("valid").getClass().getName()); //java.lang.Boolean
        System.out.println("birthday:"+m.get("birthday").getClass().getName()); //java.lang.Long
        System.out.println("link:"+m.get("link").getClass().getName()); //java.util.LinkedHashMap
        System.out.println("map:"+m.get("map").getClass().getName()); //java.util.LinkedHashMap
        System.out.println("list:"+m.get("list").getClass().getName()); //java.util.ArrayList
        System.out.println("set:"+m.get("set").getClass().getName()); //java.util.ArrayList
        /*  結果如下:
            pay:java.lang.Double
            valid:java.lang.Boolean
            birthday:java.lang.Long
            link:java.util.LinkedHashMap
            map:java.util.LinkedHashMap
            list:java.util.ArrayList
            set:java.util.ArrayList

            注意點:(1) 日期--長整型  (2)map、子對象均轉換成了LinkedHashMap (3)List、Set均轉成ArrayList
         */

        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
        //測試03:map--json
        json=mapper.writeValueAsString(m); //map轉json
        System.out.println(json); //與之前格式完全相同,說明經過map轉換后,信息沒有丟失

        //測試04:json--對象
        User u=mapper.readValue(json, User.class); //json轉java對象。經測,轉成對象后,一切恢復正常
        System.out.println("pay:"+u.getPay());
        System.out.println("valid:"+u.isValid());
        System.out.println("birthday:"+u.getBirthday());
        System.out.println("link:"+u.getLink().getAddress());
        System.out.println("map:"+u.getMap());
        System.out.println("list:"+u.getList());
        System.out.println("set:"+u.getSet());

        //測試05:其他轉換
        byte[] data=mapper.writeValueAsBytes(u); //對象轉成二進制數組
    }
}
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容