Snippets: Java: Gson

 20th August 2020 at 2:19pm

gson 是一个 Google 出品的 JSON 序列化 / 反序列化 Java 库。

序列化

public static <T> String serializeToJson(T object) {
    StringWriter writer = new StringWriter();
    EscapeNonAsciiWriter escapeWriter = new EscapeNonAsciiWriter(writer);

    Gson gson = new GsonBuilder().disableHtmlEscaping().create();
    gson.toJson(object, escapeWriter);
    return writer.toString();
}

Gson 默认会有所谓 Html Escaping,会把诸如 < > ' 等符号转义,为的是让 JSON 安全地嵌入在 HTML / XHTML 中(来源)。我认为这不是现阶段 JSON 的常见用法,不需要开启。

Gson 不对 UTF-8 字符转义成 \uxxxx 形式,而是保留它原始的字节。它认为 JSON 的编码格式应该由用户代码去理解。但是在一些不允许使用非 ASCII 字符的场景(比如 HTTP 头中)会不方便。但是 Gson 提供了用户自定义 writer 的能力,因此我们可以写一个 EscapeNonAsciiWriter 解决这个问题:

// 测试过这个类,对中文有效,对处于 Unicode Plane 1 的字符也有效
public class EscapeNonAsciiWriter extends Writer {
    private final Writer out;

    public EscapeNonAsciiWriter(Writer out) {
        this.out = out;
    }

    @Override
    public void write(char[] buffer, int offset, int count) throws IOException {
        for (int i = 0; i < count; i++) {
            char c = buffer[i + offset];
            if (c <= 0x7f) {
                out.write(c);
            } else {
                out.write(String.format("\\u%04x", (int) c));
            }
        }
    }

    @Override
    public void flush() throws IOException {
        out.flush();
    }

    @Override
    public void close() throws IOException {
        out.close();
    }
}

反序列化

public static SomePojo deserializeFromJson(String buffer) {
    Gson gson = new GsonBuilder().disableHtmlEscaping().create();
    return gson.fromJson(buffer, SomePojo.class);
}

gson.fromJson 的第二个参数,接受一个 class 对象(如 Metadata.class),由于 Java 存在 范型擦除List<String>.class 在字节码上就是 List<>.class),Gson 提供了 TypeToken 来方便指定类型。但是我不知道怎么用。对 Java 理解深了后看看 这篇文章

参考

  1. 你真的会用Gson吗?Gson使用指南(一)
  2. 搞定Gson泛型封装