Java序列化與JSON序列化大比拼

1、背景

有項目須要傳輸Map結構的數據,有人傾向用Java序列化來作,有人傾向用JSON的序列化來作。因此咱們仍是比比吧。 java

Java觀點:Object2Object,使用時簡單快速。 apache

JSON觀點:JSON格式與語言無關,擴展性強,速度也應該不慢。 json

你們可能對Java序列化都有一個錯誤的認識,認爲Java序列化比JSON的序列化效率高而且序列化的數據小,其實實際上並不必定是這樣,我此次就想經過實際測試來解開這個謎團 數據結構

2、測試方式

測試同一個Map<String,Object>並序列化爲byte[],並再將byte[]反序列化爲Map<String,Object>的過程。Object中包括String,Integer,Long,Boolean,Float,Double常規類型的數據。 ide

序列化:Map<String,Object> -> byte[] 性能

反序列化:byte[] -> Map<String,Object> 測試

測試各類大小不一樣的Map,並循環執行同一操做N次,來獲得一個相對穩定的線性結果。 this

3、比較的對象

JAVA:

手寫Java(1.6.0_32)與Common Lang3(3.1)的SerializationUtils。 google

JSON:

將採用Gson(2.2.2)與json-smart(2.0-RC2)兩種不一樣的JSON解析器。json-smart號稱是速度最快的JSON解析器。 spa

、比較結果

Map大小(10-100)循環10萬次

序列化時間比較(y爲序列化時間ms)

反序列化時間比較(y爲反序列化時間ms)


序列化時間彙總比較(y爲序列化與反序列化總時間ms)

序列化後byte大小比較(因爲同類線重合顯示爲2條線)

Map大小(100-1000)循環1萬次

序列化時間比較(y爲序列化時間ms)

反序列化時間比較(y爲反序列化時間ms)

序列化時間彙總比較(y爲序列化與反序列化總時間ms)

序列化後byte大小比較(因爲同類線重合顯示爲2條線)

比較總結

Map在小於100時:
Java的反序列化時的性能要比Java序列化時性能差不少,1.5倍左右差距。
JSON序列化性能明顯因爲Java序列化性能,尤爲是反序列化過程。而且序列化後的數據大小也是JSON格式的小。

Map在大於100小於1000時:
Java的反序列化時的性能並無隨Map的大小變化而變差。
JSON陣營中Gson在序列化過程當中,比Java只快了那麼一點點。在反序列化過程當中Gson開始領先與Java,但在Map的大小過700多之後,Gson的反序列化性能
比Java要慢。但JSON陣營中的json-smart依然表現出色徹底是兩個級別。

並非Java的序列化速度老是最快體積最小,Java須要考慮對象類型,屬性類型與內部對象信息等一系列對數據自己並不相關的內容的處理。JSON以固定的格式,穩定簡單的數據結構大大簡化了序列化過程,雖然也要建立新的Java數據對象但並不會比Java反序列化的速度慢。

從測試結果上看JSON的json-smart更適合項目的須要。

5、測試代碼源碼

SerializationTest接口

package org.noahx.javavsjson;

import java.util.Map;

/**
 * Created with IntelliJ IDEA.
 * User: noah
 * Date: 3/8/13
 * Time: 9:59 PM
 * To change this template use File | Settings | File Templates.
 */
public interface SerializationTest {

    public String getTestName();

    public Map<String, Object> testBytes2Map(byte[] bytes);

    public byte[] testMap2Bytes(Map<String, Object> map);
}


JavaSerializationTest

package org.noahx.javavsjson;

import java.io.*;
import java.util.Map;

/**
 * Created with IntelliJ IDEA.
 * User: noah
 * Date: 3/8/13
 * Time: 10:05 PM
 * To change this template use File | Settings | File Templates.
 */
public class JavaSerializationTest implements SerializationTest {

    @Override
    public String getTestName() {
        return "Java";
    }

    @Override
    public Map<String, Object> testBytes2Map(byte[] bytes) {
        Map<String, Object> result = null;
        try {
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
            ObjectInputStream inputStream = new ObjectInputStream(byteArrayInputStream);

            result = (Map<String, Object>) inputStream.readObject();
            inputStream.close();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return result;
    }

    @Override
    public byte[] testMap2Bytes(Map<String, Object> map) {
        byte[] bytes = null;
        try {
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            ObjectOutputStream outputStream = new ObjectOutputStream(byteArrayOutputStream);

            outputStream.writeObject(map);
            outputStream.close();

            bytes = byteArrayOutputStream.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bytes;
    }
}


CommonLang3SerializationTest

package org.noahx.javavsjson;

import org.apache.commons.lang3.SerializationUtils;

import java.io.Serializable;
import java.util.Map;

/**
 * Created with IntelliJ IDEA.
 * User: noah
 * Date: 3/9/13
 * Time: 2:24 AM
 * To change this template use File | Settings | File Templates.
 */
public class CommonLang3SerializationTest implements SerializationTest {
    @Override
    public String getTestName() {
        return "Commons Lang3";
    }

    @Override
    public Map<String, Object> testBytes2Map(byte[] bytes) {
        return (Map<String, Object>) SerializationUtils.deserialize(bytes);
    }

    @Override
    public byte[] testMap2Bytes(Map<String, Object> map) {
        return SerializationUtils.serialize((Serializable) map);
    }
}


GsonSerializationTest

package org.noahx.javavsjson;

import com.google.gson.Gson;

import java.io.UnsupportedEncodingException;
import java.util.Map;

/**
 * Created with IntelliJ IDEA.
 * User: noah
 * Date: 3/8/13
 * Time: 10:02 PM
 * To change this template use File | Settings | File Templates.
 */
public class GsonSerializationTest implements SerializationTest {

    private Gson gson;

    public GsonSerializationTest() {
        gson = new Gson();
    }

    @Override
    public String getTestName() {
        return "Gson";
    }

    @Override
    public Map<String, Object> testBytes2Map(byte[] bytes) {
        Map<String, Object> result = null;
        try {
            result = gson.fromJson(new String(bytes, "UTF-8"), Map.class);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return result;
    }

    @Override
    public byte[] testMap2Bytes(Map<String, Object> map) {
        String str = gson.toJson(map);
        byte[] bytes = null;
        try {
            bytes = str.getBytes("UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return bytes;
    }
}


JsonSmartSerializationTest

package org.noahx.javavsjson;

import net.minidev.json.JSONObject;
import net.minidev.json.JSONValue;
import net.minidev.json.parser.ParseException;

import java.io.UnsupportedEncodingException;
import java.util.Map;

/**
 * Created with IntelliJ IDEA.
 * User: noah
 * Date: 3/9/13
 * Time: 1:30 AM
 * To change this template use File | Settings | File Templates.
 */
public class JsonSmartSerializationTest implements SerializationTest {
    @Override
    public String getTestName() {
        return "Json Smart";
    }

    @Override
    public Map<String, Object> testBytes2Map(byte[] bytes) {
        Map<String, Object> map = null;
        try {
            map = (Map<String, Object>) JSONValue.parseStrict((new String(bytes, "UTF-8")));
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return map;
    }

    @Override
    public byte[] testMap2Bytes(Map<String, Object> map) {
        String str = JSONObject.toJSONString(map);
        byte[] result = null;
        try {
            result = str.getBytes("UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return result;
    }
}

源碼下載:http://sdrv.ms/12ECmgG

P.S.

我也測試過Map<String,String>固定數據類型value只爲String的狀況,這時Java與JSON的性能的差距會減少,但JSON序列化性能與數據大小仍是佔優點,尤爲是反序列化的速度JSON更出色。

Gson在數值反序列化後,由於Object沒法肯定類型,Map中的Long,Integer,Float統一轉爲了Double類型。 json-smart不同,若是整數超過Integer的範圍轉Long,沒有超過轉Integer。浮點Float轉爲Double類型。

相關文章
相關標籤/搜索