序列化与反序列化

492 阅读3分钟
先定义序列化和反序列化接口
public interface ISerializer {
    <T> byte[] serialize(T obj);
    <T> T deserialize(byte[] data);
}

**注意下面的System.out.println("bytes数组长度:" + bytes.length); 其实就是说,很多序列化技术的好坏,是根据序列化后产生的字节数组的大小来看的,如果产生的字节数组大,就表示很占内存,其次也要看序列化的效率和传输的效率 **

序列化技术的选型

1. 序列化空间开销,也就是序列化产生的结果大小,这个影响到传输的性能
2. 序列化过程中消耗的时长,序列化消耗时间过长影响到业务的响应时间
3. 序列化协议是否支持跨平台,跨语言。因为现在的架构更加灵活,如果存在异构系统通信
 需求,那么这个是必须要考虑的
4. 可扩展性/兼容性,在实际业务开发中,系统往往需要随着需求的快速迭代来实现快速更新,
	这就要求我们采用的序列化协议基于良好的可扩展性/兼容性,
	比如在现有的序列化数据结构中新增一个业务字段,不会影响到现有的服务

序列化输出的byte数组里存的是啥

  • protobuf 序列化的byte数组是Ascii码
  • 其他待补

Java实现序列化和反序列化


public class JavaSerializer implements ISerializer{

    //序列化
    @Override
    public <T> byte[] serialize(T obj) {
        ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();

        try {
            ObjectOutputStream outputStream=new ObjectOutputStream(byteArrayOutputStream);
            outputStream.writeObject(obj);
            return byteArrayOutputStream.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new byte[0];
    }

    //反序列化
    @Override
    public <T> T deserialize(byte[] data) {
        ByteArrayInputStream byteArrayOutputStream=new ByteArrayInputStream(data);
        try {
            ObjectInputStream objectInputStream=new ObjectInputStream(byteArrayOutputStream);
            return (T)objectInputStream.readObject();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }
    
}

测试:

public class SerializerMain {

    public static void main(String[] args) {
        ISerializer serializer=new JavaSerializer();
        User user=new User();
        user.setName("小风");
        user.setAge(27);

        byte[] bytes=serializer.serialize(user);
        //实际上这个byte数组 就是对象通过序列化之后转换成的一个二进制流
        System.out.println("bytes数组长度:" + bytes.length);
        for (int i = 0; i < bytes.length; i++) {
            //byte是一个字节8位的二进制存储(不超过256),在输出时是十进制,所以感觉是int
            System.out.print(bytes[i]+ " ");
        }
        System.out.println();
        User userRever=serializer.deserialize(bytes);
        System.out.println(userRever);
	}
    
}

控制台输出:

注意User对象:

/**
 * User对象必须实现Serializable,然后可以不手动生成serialVersionUID=1L或serialVersionUID=一串数字
 * 其实implements Serializable之后,内部默认会生成serialVersionUID的
 */
@Data
public class User implements Serializable
{

//	  private static final long serialVersionUID = -2112105888550168550L;
//    private static final long serialVersionUID = 1L;

    private String name;
    private int age;
}

如果不实现 Serializable,会报错:

XML实现序列化和反序列化

public class XMLSerializer implements ISerializer{

    XStream stream=new XStream(new DomDriver());
    @Override
    public <T> byte[] serialize(T obj) {
        return stream.toXML(obj).getBytes();
    }

    @Override
    public <T> T deserialize(byte[] data) {
        return (T)stream.fromXML(new String(data));
    }
}

Main方法测试:

public class SerializerMain {

    public static void main(String[] args) {
		User user=new User();
        user.setName("小风");
        user.setAge(27);
        ISerializer serializer=new XMLSerializer();
        byte[] bytes=serializer.serialize(user);
        System.out.println("bytes数组长度:" + bytes.length);
        System.out.println(new String(bytes));
        User userRever=serializer.deserialize(bytes);
        System.out.println(userRever);
    }
    
}

控制台输出如下:

Hessian实现序列化

public class HessianSerializer implements ISerializer{
    @Override
    public <T> byte[] serialize(T obj) {
        ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();
        HessianOutput hessianOutput=new HessianOutput(byteArrayOutputStream);
        try {
            hessianOutput.writeObject(obj);
            return byteArrayOutputStream.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new byte[0];
    }

    @Override
    public <T> T deserialize(byte[] data) {
        ByteArrayInputStream byteArrayInputStream=new ByteArrayInputStream(data);
        HessianInput hessianInput=new HessianInput(byteArrayInputStream);
        try {
            return (T)hessianInput.readObject();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

Main方法测试:

  public class SerializerMain {
      public static void main(String[] args) {
          User user=new User();
          user.setName("小风");
          user.setAge(27);
          ISerializer serializer=new HessianSerializer();
          byte[] bytes=serializer.serialize(user);
          System.out.println("bytes数组长度:" + bytes.length);
          System.out.println(new String(bytes));
          User userRever=serializer.deserialize(bytes);
          System.out.println(userRever);
      }
  }

控制台输出:

FastJSON 序列化,反序列化

直接看源代码,其实序列化方式和上面几种有很大的相通性,意会意会吧
JSONObject.toJSONString(accountInfo)
  
//序列号后输出跨平台容易理解的字符串  
public static String toJSONString(Object object, // 
                                    SerializeConfig config, // 
                                    SerializeFilter[] filters, // 
                                    String dateFormat, //
                                    int defaultFeatures, // 
                                    SerializerFeature... features) {
  	//部分代码省略
      SerializeWriter out = new SerializeWriter(null, defaultFeatures, features);
      try {
          JSONSerializer serializer = new JSONSerializer(out, config);
          serializer.write(object);
          return out.toString();
      } finally {
          out.close();
      }
}

public final class SerializeWriter extends Writer {
    private final static ThreadLocal<char[]>         bufLocal      = new ThreadLocal<char[]>();
    private final static ThreadLocal<byte[]>         bytesBufLocal = new ThreadLocal<byte[]>();
     其余代码省略 ...
}