Java Gson 源码分析:JsonWriter


#Java Gson


如何使用 JsonWriter

代码示例:

package org.example;

import com.google.gson.stream.JsonWriter;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.io.StringWriter;

public class TestJsonWriter {

    @Test
    public void test() throws IOException {
        StringWriter stringWriter = new StringWriter();
        JsonWriter jsonWriter = new JsonWriter(stringWriter);
        jsonWriter.beginObject();
        jsonWriter.name("age");
        jsonWriter.value(18);
        jsonWriter.endObject();
        jsonWriter.close();
        System.out.println(stringWriter.toString());
    }
}

执行结果:

{"age":18}

JsonWriter 源码阅读 - 状态机

状态枚举: com.google.gson.stream.JsonScope

JsonWriter 使用下面的堆栈维护状态机:

  private int[] stack = new int[32];
  private int stackSize = 0;

以下面的代码为例,分析下状态机变化:

// 默认将  JsonScope.EMPTY_DOCUMENT 放入堆栈
// 状态机: [] -> [EMPTY_DOCUMENT]
JsonWriter jsonWriter = new JsonWriter(stringWriter);  

// 将 JsonScope.EMPTY_OBJECT 放入堆栈,并写入 "{"
// 状态机: [EMPTY_DOCUMENT] -> [EMPTY_DOCUMENT, EMPTY_OBJECT] 
jsonWriter.beginObject(); 

// 将 "age" 赋值给 deferredName 变量
jsonWriter.name("age");


// 若 indent 变量不为空,写入换行符,写入缩进字符
// 将状态机栈顶状态替换为 JsonScope.DANGLING_NAME
// 状态机: [EMPTY_DOCUMENT, EMPTY_OBJECT]  -> [EMPTY_DOCUMENT, DANGLING_NAME] 
// 写入 deferredName 变量值,即 "age"
// 清空 deferredName 变量值
// 获取栈顶状态为  JsonScope.DANGLING_NAME,写入 ":" ,并将状态机栈顶状态替换为 JsonScope.NONEMPTY_OBJECT
// 状态机: [EMPTY_DOCUMENT, DANGLING_NAME]  -> [EMPTY_DOCUMENT, NONEMPTY_OBJECT] 
jsonWriter.value(18);

// 移除栈顶,发现状态机栈顶状态为 JsonScope.EMPTY_OBJECT, 若 indent 变量不为空,写入换行符,写入缩进字符
// 写入 "}"
// 状态机: [EMPTY_DOCUMENT, NONEMPTY_OBJECT]  -> [EMPTY_DOCUMENT] 
jsonWriter.endObject();

// 清理状态机堆栈
// 状态机: [EMPTY_DOCUMENT]  -> [] 
jsonWriter.close();

JsonWriter 源码阅读 - 缩进 ( indent )

代码示例

import java.io.IOException;
import java.io.StringWriter;

public class TestJsonWriter {

    @Test
    public void test() throws IOException {
        StringWriter stringWriter = new StringWriter();
        JsonWriter jsonWriter = new JsonWriter(stringWriter);
        jsonWriter.setIndent("  ");  // 设置缩进
        jsonWriter.beginObject();
        jsonWriter.name("age");
        jsonWriter.value(18);
        jsonWriter.endObject();
        jsonWriter.close();
        System.out.println(stringWriter.toString());
    }
}

执行结果:

{
  "age": 18
}

原理

jsonWriter.setIndent(" "); 将实例变量 indent 赋值为 " "。在 jsonWriter 的 beginObject、name、value 等操作中,会判断indent 是否有值,根据状态机栈顶的状态判断是否换行,根据状态机堆栈的大小,判断要缩进几次。


( 本文完 )