分类 Serialization 下的文章

这周前几天,同事问我,使用Fastjson进行Json的处理,需要转成Json的对象中还有null值,输出成JsonString后,该值和所对应的key都没有了。他的代码是这样的:

Map<String, String> map = new HashMap<String, String>();
map.put("a", "12");
map.put("b", null);
String jsonString = JSONObject.toJSONString(map);
System.out.println(jsonString);

输出为:

{"a":"12"}

b的key没了,value也没了,而对于使用该接口的下游系统来说,有key而value为null与无key是完全不同的概念,所以需要下发该key。

我搜了下,网上有提供方案,使用SerializerFeature.WriteMapNullValue。如下:

Map<String, String> map = new HashMap<String, String>();
map.put("a", "12");
map.put("b", null);
String jsonString = JSONObject.toJSONString(map,
        SerializerFeature.WriteMapNullValue);
System.out.println(jsonString);

输出为:

{"b":null,"a":"12"}

- 阅读剩余部分 -

参考JavaCodeGeeks上个这篇文章 http://www.javacodegeeks.com/2011/12/cloning-of-serializable-and-non.html 作者Craig Flichel

通常开发者都会依赖于第三方的类库来进行开发,这样避免重复制造轮子。特别是在Java的世界中,有着像Apache和Spring这样流行的开源项目。但在实际使用过程,我们总是无法控制这些类的行为,或者是只能控制一点点,叫人不爽。

这有时会带来问题。举个例子,比如说你要深度克隆一个没有提供合适克隆方法的对象,你准备咋整?

通过序列化来克隆

最简单的方法,如果对象实现了Serializable接口,那么直接利用这个就好。Apache Commons库中提供了一个方法去做这个,但为了完整,自己实现的话,代码可能就像下面这样:

public static Serializable cloneThroughSerialize(Serializable ser) throws Exception {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    serializeToOutputStream(ser, bos);
    byte[] bytes = bos.toByteArray();
    ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(
            bytes));
    return (Serializable) ois.readObject();
}

private static void serializeToOutputStream(Serializable ser,
        OutputStream os) throws IOException {
    ObjectOutputStream oos = null;
    try {
        oos = new ObjectOutputStream(os);
        oos.writeObject(ser);
        oos.flush();
    } finally {
        oos.close();
    }
}

// using our custom method
Serializable cloned = cloneThroughSerialize(someObject);

// or with Apache Commons
Object cloned = org.apache.commons.lang.SerializationUtils.clone(someObject);

- 阅读剩余部分 -

参考JavaCodeGeeks上个这篇文章 http://www.javacodegeeks.com/2014/02/serializing-java-objects-with-non-serializable-attributes.html 作者Dustin Marx

有很多原因,使得我们想使用自定义的序列化方法代替Java默认的序列化方法。最普遍的一个原因就是为了提升性能。其他的原因大都是默认的序列化机制不支持。其中一个非常普遍的场景就是,要序列化一个拥有非序列化属性的对象。

下面的代码展示了一个小例子:

SerializationDemonstrator.java
package com.chengjf;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class SerializationDemonstrator {
    public static <T> void serialize(final T objectToSerialize,
            final String fileName) {
        if (fileName == null) {
            throw new IllegalArgumentException(
                    "Name of file to which to serialize object to cannot be null.");
        }
        if (objectToSerialize == null) {
            throw new IllegalArgumentException(
                    "Object to be serialized cannot be null.");
        }
        FileOutputStream fos = null;
        ObjectOutputStream oos = null;
        try {
            fos = new FileOutputStream(fileName);
            oos = new ObjectOutputStream(fos);
            oos.writeObject(objectToSerialize);
            System.out.println("Serialization of object " + objectToSerialize
                    + " completed!");
            oos.close();
            fos.close();
        } catch (IOException ioException) {
            ioException.printStackTrace();
        }
    }

    public static <T> T deserialize(final String fileToSerialize,
            final Class<T> classBeingDeserialized) {
        if (fileToSerialize == null) {
            throw new IllegalArgumentException(
                    "Cannot deserialize from a null filename.");
        }
        if (classBeingDeserialized == null) {
            throw new IllegalArgumentException(
                    "Type of class to be deserialized cannot be null.");
        }
        T objectOut = null;
        FileInputStream fis = null;
        ObjectInputStream ois = null;
        try {
            fis = new FileInputStream(fileToSerialize);
            ois = new ObjectInputStream(fis);
            objectOut = (T) ois.readObject();
            System.out.println("Deserialization of object " + objectOut
                    + " is completed!");
            ois.close();
            fis.close();
        } catch (IOException ioException) {
            ioException.printStackTrace();
        } catch (ClassNotFoundException classNotFoundException) {
            classNotFoundException.printStackTrace();
        }
        return objectOut;
    }
}

- 阅读剩余部分 -

本文Ctrl-V自《Java编程思想》第四版第X章Y小节。

序列化简介

Java的对象序列化将那些实现了Serializable接口的对象转换成一个字节序列,并能够在以后将这个字节序列完全恢复为原来的对象。这一过程甚至可以通过网络进行,这意味着序列化机制能自动弥补不同操作系统之间的差异。也就是说,可以在运行Windows系统的计算机上创建一个对象,将其序列化,通过网络将它发送给一台运行Unix系统的计算机,然后在那里准确地重新组装,而却不必担心数据在不同机器上的表示会不同,也不必关心字节的顺序或者其他任何细节。

就其本身来说,对象的序列化是非常有趣的,因为利用它可以实现轻量级持久性(lightweight persistence)。“持久性”意味着一个对象的生命周期并不取决于程序是否正在执行;它可以生存于程序的调用之间。通过将一个序列化对象写入磁盘,然后在重新调用程序时恢复该对象,就能够实现持久性的效果。之所以称其为“轻量级”,是因为不能用某种“persistent”(持久)关键字来简单地定义一个对象,并让系统自动维护其他细节问题(尽管将来有可能实现)。相反,对象必须在程序中显式地序列化(serialize)和反序列化还原(deserialize)。如果需要一个更严格的持久性机制,可以考虑像Hibernate之类的工具。

- 阅读剩余部分 -