湖畔镇

Gson源码分析

Gson是Google开发的Java API,用于转换Java对象和Json对象

Gson源码分析

Gson

Gson的构造函数接收很多参数,Gson()提供了一些默认的值

主要有两个方法toJson()fromJson()

toJson()最终调用的是下面这个方法

public void toJson(Object src, Type typeOfSrc, JsonWriter writer) throws JsonIOException {
    TypeAdapter adapter = this.getAdapter(TypeToken.get(typeOfSrc));

    boolean oldLenient = writer.isLenient();
    writer.setLenient(true);

    boolean oldHtmlSafe = writer.isHtmlSafe();
    writer.setHtmlSafe(this.htmlSafe);

    boolean oldSerializeNulls = writer.getSerializeNulls();
    writer.setSerializeNulls(this.serializeNulls);

    try {
        adapter.write(writer, src);
    } catch (IOException var12) {
        throw new JsonIOException(var12);
    } finally {
        writer.setLenient(oldLenient);
        writer.setHtmlSafe(oldHtmlSafe);
        writer.setSerializeNulls(oldSerializeNulls);
    }
}

fromJson()最终调用的是下面这个方法

public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException {
    boolean isEmpty = true;
    boolean oldLenient = reader.isLenient();
    reader.setLenient(true);

    TypeAdapter typeAdapter;
    try {
        reader.peek();
        isEmpty = false;
        TypeToken e = TypeToken.get(typeOfT);
        typeAdapter = this.getAdapter(e);
        Object object = typeAdapter.read(reader);
        Object var8 = object;
        return var8;
    } catch (EOFException var14) {
        if(!isEmpty) {
            throw new JsonSyntaxException(var14);
        }

        typeAdapter = null;
    } catch (IllegalStateException var15) {
        throw new JsonSyntaxException(var15);
    } catch (IOException var16) {
        throw new JsonSyntaxException(var16);
    } finally {
        reader.setLenient(oldLenient);
    }

    return typeAdapter;
}

都是通过TypeAdapterread()write()完成

通过getAdapter()方法获得对应类型的适配器

public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {

    //  首先查找缓存,节省时间
    TypeAdapter cached = (TypeAdapter)this.typeTokenCache.get(type);

    if(cached != null) {
        return cached;
    } else {
        //  threadCalls是一个type-adapter表
        Object threadCalls = (Map)this.calls.get();
        boolean requiresThreadLocalCleanup = false;

        if(threadCalls == null) {
            threadCalls = new HashMap();
            this.calls.set(threadCalls);
            requiresThreadLocalCleanup = true;
        }

        //  从列表中拿到对应type的adapter
        Gson.FutureTypeAdapter ongoingCall = (Gson.FutureTypeAdapter)((Map)threadCalls).get(type);
        if(ongoingCall != null) {
            return ongoingCall;
        } else {
            try {
                // 没有就遍历工厂列表,创建一个合适的TypeAdapter
                Gson.FutureTypeAdapter call = new Gson.FutureTypeAdapter();
                ((Map)threadCalls).put(type, call);
                Iterator i$ = this.factories.iterator();
                TypeAdapter candidate;
                do {
                    if(!i$.hasNext()) {
                        throw new IllegalArgumentException("GSON cannot handle " + type);
                    }
                    TypeAdapterFactory factory = (TypeAdapterFactory)i$.next();
                    candidate = factory.create(this, type);
                } while(candidate == null);
                    call.setDelegate(candidate);
                    this.typeTokenCache.put(type, candidate);
                    TypeAdapter var10 = candidate;
                    return var10;
            } finally {
                //  清理:从列表中移除这个type对应的adapter,为什么?
                ((Map)threadCalls).remove(type);
                if(requiresThreadLocalCleanup) {
                    //  为何会在这里做移除?
                    this.calls.remove();
                }

            }
        }
    }
}

这个方法涉及到多线程的处理,不太易懂,使用了一个ThreadLocal来存放Type-Adapter列表

TypeAdapter

public abstract class TypeAdapter<T> {
    public abstract void write(JsonWriter var1, T var2) throws IOException;

    public abstract T read(JsonReader var1) throws IOException;

    ......
}

一个抽象的泛型类,用来执行序列化和反序列化,关键的方法是write()read()

这个东西和创建它的工厂基本是最重要的结构

public interface TypeAdapterFactory {
    <T> TypeAdapter<T> create(Gson var1, TypeToken<T> var2);
}

工厂接口的create()负责创建TypeAdapter

private final List<TypeAdapterFactory> factories;

Gson类中有个工厂的列表,在构造函数中被添加很多的工厂

INTEGER = new TypeAdapter() {
    public Number read(JsonReader in) throws IOException {
        if(in.peek() == JsonToken.NULL) {
            in.nextNull();
            return null;
        } else {
            try {
                return Integer.valueOf(in.nextInt());
            } catch (NumberFormatException var3) {
                throw new JsonSyntaxException(var3);
            }
        }
    }

    public void write(JsonWriter out, Number value) throws IOException {
        out.value(value);
    }
};

INTEGER_FACTORY = newFactory(Integer.TYPE, Integer.class, INTEGER);

上面是解析intTypeAdapter,里面是通过JsonReaderJsonWriter读写

JsonReader

public JsonReader(Reader in);

构造函数接收Reader作为参数

public void beginObject() throws IOException {
    int p = this.peeked;
    if(p == 0) {
        p = this.doPeek();
    }

    if(p == 1) {
        this.push(3);
        this.peeked = 0;
    } else {
        throw new IllegalStateException("Expected BEGIN_OBJECT but was " + this.peek() + " at line " + this.getLineNumber() + " column " + this.getColumnNumber());
    }
}

标记对象的开始,提取,如果是对象开始,则进栈3(PEEKED_BEGIN_ARRAY),如果不是则抛出异常

public void endObject() throws IOException {
    int p = this.peeked;
    if(p == 0) {
        p = this.doPeek();
    }

    if(p == 2) {
        --this.stackSize;
        this.peeked = 0;
    } else {
        throw new IllegalStateException("Expected END_OBJECT but was " + this.peek() + " at line " + this.getLineNumber() + " column " + this.getColumnNumber());
    }
}

标记对象的结束

public void beginArray() throws IOException {
    int p = this.peeked;
    if(p == 0) {
        p = this.doPeek();
    }

    if(p == 3) {
        this.push(1);
        this.peeked = 0;
    } else {
        throw new IllegalStateException("Expected BEGIN_ARRAY but was " + this.peek() + " at line " + this.getLineNumber() + " column " + this.getColumnNumber());
    }
}

标记数组的开始,提取,如果是数组开始,则进栈1(PEEKED_BEGIN_OBJECT),如果不是则抛异常

public void endArray() throws IOException {
    int p = this.peeked;
    if(p == 0) {
        p = this.doPeek();
    }

    if(p == 4) {
        --this.stackSize;
        this.peeked = 0;
    } else {
        throw new IllegalStateException("Expected END_ARRAY but was " + this.peek() + " at line " + this.getLineNumber() + " column " + this.getColumnNumber());
    }
}

标记数组的结束

public boolean hasNext() throws IOException {
    int p = this.peeked;
    if(p == 0) {
        p = this.doPeek();
    }

    return p != 2 && p != 4;
}

判断是否有下一个元素,如果不是对象结束和数组结束则有下一个元素,注意这里在提取后没有this.peeked = 0,所以下一次操作不会再提取一次,而是使用取得的值

public String nextName() throws IOException {
    int p = this.peeked;
    if(p == 0) {
        p = this.doPeek();
    }

    String result;
    if(p == 14) {   //  PEEKED_UNQUOTED_NAME
        result = this.nextUnquotedValue();
    } else if(p == 12) {    //  PEEKED_SINGLE_QUOTED_NAME
        result = this.nextQuotedValue('\'');
    } else {
        if(p != 13) {   //  PEEKED_DOUBLE_QUOTED_NAME
            throw new IllegalStateException("Expected a name but was " + this.peek() + " at line " + this.getLineNumber() + " column " + this.getColumnNumber());
        }

        result = this.nextQuotedValue('\"');
    }

    this.peeked = 0;
    return result;
}

下一个键,三种形式:无引号、单引号、双引号

然后是nextXX()系列函数,读取下一个值,读取完成后会设置this.peeked = 0复位

private int doPeek() throws IOException {
    //  获得当前栈顶
    int peekStack = this.stack[this.stackSize - 1];
    int c;

    if(peekStack == 1) {    //  PEEKED_BEGIN_OBJECT
        //  再次进入切换为结束构造对象
        this.stack[this.stackSize - 1] = 2; //  PEEKED_END_OBJECT
    } else if(peekStack == 2) { //  PEEKED_END_OBJECT
        c = this.nextNonWhitespace(true);
        switch(c) {
        case 44:    //  逗号
            break;
        case 59:    //  分号
            this.checkLenient();
            break;
        case 93:    //  右方括号
            return this.peeked = 4; //  PEEKED_END_ARRAY
        default:
            throw this.syntaxError("Unterminated array");
        }
    } else {
        if(peekStack == 3 || peekStack == 5) {  //  PEEKED_BEGIN_ARRAY || PEEKED_TRUE
        //  切换为结束数组
        //  两种情况,一是目前是开始数组,二是完成一个键值对
            this.stack[this.stackSize - 1] = 4; //  PEEKED_END_ARRAY

            //  完成键值对的情况,可能有更多键值对,可能就结束了
            if(peekStack == 5) {
                c = this.nextNonWhitespace(true);
                switch(c) {
                case 44:    //  逗号
                    break;
                case 59:    //  分号
                    this.checkLenient();
                    break;
                case 125:   //  右大括号
                    return this.peeked = 2; //  PEEKED_END_OBJECT
                default:
                    throw this.syntaxError("Unterminated object");
                }
            }

            c = this.nextNonWhitespace(true);
            switch(c) {
            case 34:    //  双引号
                return this.peeked = 13;    //  PEEKED_DOUBLE_QUOTED_NAME
            case 39:    //  单引号
                this.checkLenient();
                return this.peeked = 12;    //  PEEKED_SINGLE_QUOTED_NAME
            case 125:   //  右大括号
                if(peekStack != 5) {
                    return this.peeked = 2; //  PEEKED_END_OBJECT
                }
                throw this.syntaxError("Expected name");
            default:
                this.checkLenient();
                --this.pos;
                if(this.isLiteral((char)c)) {
                    return this.peeked = 14;    //  PEEKED_UNQUOTED_NAME
                }
                throw this.syntaxError("Expected name");
            }
        }

        if(peekStack == 4) {    //  PEEKED_END_ARRAY
            this.stack[this.stackSize - 1] = 5; //  PEEKED_TRUE
            c = this.nextNonWhitespace(true);
            switch(c) {
            case 58:    //  冒号
                break;
            case 61:    //  逗号
                this.checkLenient();
                if((this.pos < this.limit || this.fillBuffer(1)) && this.buffer[this.pos] == 62) {
                    ++this.pos;
                }
                break;
            default:
                throw this.syntaxError("Expected \':\'");
            }
        } else if(peekStack == 6) { //  PEEKED_FALSE
            if(this.lenient) {
                this.consumeNonExecutePrefix();
            }

            this.stack[this.stackSize - 1] = 7; //  PEEKED_NULL
        } else if(peekStack == 7) { //  PEEKED_NULL
            c = this.nextNonWhitespace(false);
            if(c == -1) {
                return this.peeked = 17;    //  PEEKED_EOF
            }

            this.checkLenient();
            --this.pos;
        } else if(peekStack == 8) { //  PEEKED_SINGLE_QUOTED
            throw new IllegalStateException("JsonReader is closed");
        }
    }

    c = this.nextNonWhitespace(true);
    switch(c) {
    case 34:    //  双引号
        if(this.stackSize == 1) {
            this.checkLenient();
        }

        return this.peeked = 9; //  PEEKED_DOUBLE_QUOTED
    case 39:    //  单引号
        this.checkLenient();
        return this.peeked = 8; //  PEEKED_SINGLE_QUOTED
    case 91:    //  左方括号
        return this.peeked = 3; //  PEEKED_BEGIN_ARRAY
    case 93:    //  右方括号
        if(peekStack == 1) {    //  PEEKED_BEGIN_OBJECT
            return this.peeked = 4; //  PEEKED_END_ARRAY
        }
    case 44:    //  逗号
    case 59:    //  分号
        if(peekStack != 1 && peekStack != 2) {  //  PEEKED_BEGIN_OBJECT && PEEKED_END_OBJECT
            throw this.syntaxError("Unexpected value");
        }

        this.checkLenient();
        --this.pos;
        return this.peeked = 7; //  PEEKED_NULL
    case 123:   //  左大括号
        return this.peeked = 1; //  PEEKED_BEGIN_OBJECT
    default:
        --this.pos;
        if(this.stackSize == 1) {
            this.checkLenient();
        }

        int result = this.peekKeyword();
        if(result != 0) {
            return result;
        } else {
            result = this.peekNumber();
            if(result != 0) {
                return result;
            } else if(!this.isLiteral(this.buffer[this.pos])) {
                throw this.syntaxError("Expected value");
            } else {
                this.checkLenient();
                return this.peeked = 10;
            }
        }
    }
}

doPeek()分为两个阶段,首先分析栈顶元素,栈顶元素指示了当前的分析阶段,然后如果前面没返回的话则继续分析下一个字符

beginObject会给栈顶赋值PEEKED_BEGIN_ARRAY,表示开始构造数组?

beginArray会给栈顶赋值PEEKED_BEGIN_OBJECT,表示开始构造对象?

流程比较难以理解,首先要了解stack的确切意思

简单的字符串

带数组的字符串

JsonWriter

JsonWriter就简单一些,主要是这些方法:

public JsonWriter beginArray() throws IOException;
public JsonWriter endArray() throws IOException;
public JsonWriter beginObject() throws IOException;
public JsonWriter endObject() throws IOException;
public JsonWriter name(String name) throws IOException;
public JsonWriter value(String value) throws IOException;

GsonBuilder

Gson对象的构造器,可以自己进行配置,最终通过create()获得Gson对象

public GsonBuilder setVersion(double ignoreVersionsAfter);

忽略给定数字之后的版本号

public GsonBuilder excludeFieldsWithModifiers(int... modifiers);

忽略给定的限定符

public GsonBuilder excludeFieldsWithoutExposeAnnotation();

忽略不带Expose注解的域

public GsonBuilder setFieldNamingPolicy(FieldNamingPolicy namingConvention);
public GsonBuilder setFieldNamingStrategy(FieldNamingStrategy fieldNamingStrategy);

设置命名策略

public GsonBuilder setExclusionStrategies(ExclusionStrategy... strategies);

设置排除策略

public GsonBuilder addSerializationExclusionStrategy(ExclusionStrategy strategy);
public GsonBuilder addDeserializationExclusionStrategy(ExclusionStrategy strategy);

对序列化和反序列化分别设置排除策略

public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter);

注册类型适配器,可能是InstanceCreator(这个东西在Gson构造函数中提供给各个TypeAdapter,具体干什么的不清楚)、JsonSerializerJsonDeserializerTypeAdapter

Excluder

这个类实现了TypeAdapterFactory接口,可以做一些排除规则

可以设置版本号、限定符、是否处理内部类、要求暴露

Gson的构造函数里设置了一个默认的Excluder,也可以在GsonBuilder中自己修改

factories.add(new ReflectiveTypeAdapterFactory(this.constructorConstructor, fieldNamingPolicy, excluder));

在构造函数中加入了TypeAdapter工厂列表

明显ReflectiveTypeAdapterFactory就是处理反射相关的东西

ReflectiveTypeAdapterFactory.BoundField field = (ReflectiveTypeAdapterFactory.BoundField)this.boundFields.get(e);
    if(field != null && field.deserialized) {
        field.read(in, instance);
    } else {
        in.skipValue();
    }

上面是read()中的一段,显然skip了一些不想要的域

也有个接口ExclusionStrategy,指定了需要跳过的域和类

public interface ExclusionStrategy {
    boolean shouldSkipField(FieldAttributes var1);

    boolean shouldSkipClass(Class<?> var1);
}

构造的时候可以提供排除策略

public GsonBuilder setExclusionStrategies(ExclusionStrategy... strategies);

调用了下面这个函数

public Excluder withExclusionStrategy(ExclusionStrategy exclusionStrategy, boolean serialization, boolean deserialization)

FieldNamingStrategy

名称映射策略

public interface FieldNamingStrategy {
    String translateName(Field var1);
}

有一个实现的枚举FieldNamingPolicy,提供了五种:

  • IDENTITY
  • UPPER_CAMEL_CASE
  • UPPER_CAMEL_CASE_WITH_SPACES
  • LOWER_CASE_WITH_UNDERSCORES
  • LOWER_CASE_WITH_DASHES

也是在ReflectiveTypeAdapterFactory中被使用

private String getFieldName(Field f) {
    SerializedName serializedName = (SerializedName)f.getAnnotation(SerializedName.class);
    return serializedName == null?this.fieldNamingPolicy.translateName(f):serializedName.value();
}

可以看到,如果没有给出序列化的名字,就使用命名策略来处理,否则使用我们给出的名字

分享