关于Gson

解析列表数据时如遇到后台数据传值为 "" 解决方式

public class BookDeserializer implements JsonDeserializer<Book>{
  @Override
  public Book deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
    ...
    JsonElement jsonAuthors = jsonObject.get("authors");
    if(jsonAuthors.isJsonArray()){
      ...
      book.setAuthors(authors);
    }else{
      book.setAuthors(null);
    }
    ...
  }
}

GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Book.class, new BookDeserializer());
...
Gson gson = gsonBuilder.create();

TypeAdapter的工作原理分析

JsonParser final类,解析成JsonElement对象(可以解析String串、Reader输入流、JsonReader输入流)

Stream.parser(JsonReader reader){...}
TypeAdapter.JSON_ELEMENT.reader(reader){...}

// 递归调用read方法将json串封装成JsonElement对象供我们使用
public static final TypeAdapter<JsonElement> JSON_ELEMENT = new TypeAdapter<JsonElement>() {
      /****
      *该方法的主要作用就是让json串封装成你希望的对象,在这里是把json串
      */
    @Override public JsonElement read(JsonReader in) throws IOException {
   //调用peek()方法对json传进行读取和解析,并返回对应的JsonToke类型
      switch (in.peek()) {
      case STRING://如果是字符类型,封装并返回之
        return new JsonPrimitive(in.nextString());
      case NUMBER://数字类型,例如double,long,int
        String number = in.nextString();
        return new JsonPrimitive(new LazilyParsedNumber(number));
      case BOOLEAN://boolean 类型:true or false
        return new JsonPrimitive(in.nextBoolean());
      case NULL://null
        in.nextNull();
        return JsonNull.INSTANCE;
      case BEGIN_ARRAY://数组类型
         //解析此数组,并添加到array中去
        JsonArray array = new JsonArray();
        in.beginArray();
        //循环遍历数组,并调用read方法解析成JsonElement对象,添加到array中去
        while (in.hasNext()) {
          array.add(read(in));
        }
        in.endArray();
        return array;//返回之
      case BEGIN_OBJECT://如果只json对象,例如{"name":"value"}
        JsonObject object = new JsonObject();
        in.beginObject();
        //解析该json对象,并获取name 和value放入object中
        //注意value可能是JsonElement,所以要调用read(in)
        while (in.hasNext()) {
          object.add(in.nextName(), read(in));
        }
        in.endObject();
        return object;
      case END_DOCUMENT:
      case NAME:
      case END_OBJECT:
      case END_ARRAY:
      default:
        throw new IllegalArgumentException();
      }
    }
}

// TypeAdapter抽象类解析json串为指定对象
/***
*匿名内部类的完美应用
**/
 public final TypeAdapter<T> nullSafe() {
    return new TypeAdapter<T>() {
      @Override public void write(JsonWriter out, T value) throws IOException {
        if (value == null) {
          out.nullValue();
        } else {
          TypeAdapter.this.write(out, value);
        }
      }
      @Override public T read(JsonReader reader) throws IOException {
        if (reader.peek() == JsonToken.NULL) {
          reader.nextNull();
          return null;
        }
        return TypeAdapter.this.read(reader);
      }
    };
  }

Gson gson = new GsonBuilder().registerTypeAdapter(Foo.class,
      new TypeAdapter<Foo>() {
        public Foo read(JsonReader in) throws IOException {
          // read a Foo from in and return it
       }
        public void write(JsonWriter out, Foo src) throws IOException {
          // write src as JSON to out
        }
      }.nullSafe()).create();

fromJson(String,Class)–>fromJson(String,Type) (Type包含了class的报名和类名 class package.className)–>fromJson(Reader,Type)–>fromJson(JsonReader,Type);最终调用了fromJson(Jsonreader,Type)

自定义Adapter要让Gson使用,registerTypeAdapter,注册

通过GsonBuilder注册TypeAdapter,并把TypeAdapter封装成TypeAdpterFactory对象;
将封装成的TypeAdapterFactory通过GsonBuilder的create传入Gson对象中并返回;
调用gson.fromJson方法,调用getTypeAdapter方法返回你自定义的Adapter,并调用其reader方法进行处理。

JsonDeserializer的工作方式

将JsonDesrializer封装成TypeAdapterFactory;
在Factory的create方法 返回TypeAdapter的时候,需要再次将JsonDesrializer封装成TypeAdapter;
然后在Gson的getTypeAdapter 方法,返回封装过后的TypeAdapter,并调用read方法;
JsonDesrializer在TypeAdapter起到代理的作用,在reader方法执行的时候实际上调用的是JsonDesrializer的deserializer方法;

Gson解析原理

如果是通过GsonBuilder创建的Gson对象,那么就用自定义的TyperAdapter来完成json的解析;
如果是通过new Gson()创建的Gson对象,那么就用Java反射机制来完成json的解析。

通过Gson的factories(List) 这个对象add TypeAdapterFactory的顺序来控制的!当是用第一种方式来创建Gson对象的时候,把自定一个TypeAdapter或者TypeAdapterFactory添加在factories靠前的位置,然后在getAdapter方法中遍历factories的每一个TypeAdapterFactory,如果当前循环中的TypeAdapterFactory.create 返回的TypeAdapter!=null,就返回该Adapter退出了factories的遍历.因为自定义的TypeAdapter位置在factories中靠前这样就优先与ReflectiveTypeAdapterFactory 遍历到,所以就避免了用Gson的反射机制来解析json了。

1186243-018dc2ea175df9bb.png
image.png

Gson的反射解析机制

Gson解析成Java对象:①注册TypeAdapter;②将TypeAdapter封装成TypeAdapterFactory,加至列表factories;③fromJson,getAdapter,factory的create方法创建TypeAdapter;④Typeadapter的read方法完成转换

对于每一个Java的基本类型或者集合类型,Gson都提供了与之相对应的TypeAdapter类型(如CHARACTER_FACTORY)

1186243-282ceab1975ce28a.png
image.png

猜你喜欢

转载自blog.csdn.net/weixin_34049032/article/details/87576822
今日推荐