每天记录学习的新知识 :TypeAdapter

    技术2023-12-29  72

    参考地址

    参考和转载地址:你真的会用Gson吗?Gson使用指南(四) 参考地址:Gson全解析(中)-TypeAdapter的使用

    TypeAdapter

    TypeAdapter 是Gson自2.0(源码注释上说的是2.1)开始版本提供的一个抽象类,用于接管某种类型的序列化和反序列化过程,包含两个注要方法 write(JsonWriter,T) 和 read(JsonReader) 其它的方法都是final方法并最终调用这两个抽象方法。

    API

    public abstract class TypeAdapter<T> { //序列化 public abstract void write(JsonWriter out, T value) throws IOException; //方法名称指明了需要做的业务,参数则提供了更通用的入参类型Writer。 //该方法可以把对象输出到Writer类型的输出流中。内部实现上使用包装类JsonWtiter完成输出格式的转换 public final void toJson(Writer out, T value) throws IOException {...} public final TypeAdapter<T> nullSafe() {...} //方法不指定输出参数,默认返回json格式的String类型结果。 //实际上使用的是StringWriter完成输出流转换的,具体操作是,创建StringWriter之后,调用前面的方法。 //从而完成json数据格式转换 public final String toJson(T value) {...} //解析json数据,从JsonReader中读取json数据,并完成对象创建和属性赋值,从而恢复出完成的数据对象 public final JsonElement toJsonTree(T value) {...} //反序列化 public abstract T read(JsonReader in) throws IOException; //对read方法的扩展,接受更加通用的Reader格式输入,内部实现使用JsonReader对Reader包装, //完成输入流格式转换,并调用前一个方法,达到从输入流恢复出对象的目的 public final T fromJson(Reader in) throws IOException {...} //从json字符串恢复对象属性,使用StringReader对String类型的输入数据进行包装,并且调用前面的方法,达成对象赋值的目的 public final T fromJson(String json) throws IOException {...} //从JsonElement中恢复对象信息,使用JsonTreeReader对JsonElement类型的输入数据进行包装,然后调用前面的方法恢复出数据对象 public final T fromJsonTree(JsonElement jsonTree) {...} }

    例子

    转载自:Gson全解析(中)-TypeAdapter的使用

    public class Book { private String[] authors; private String isbn; private String title; ... } public class BookTypeAdapter extends TypeAdapter<Book> { @Override public void write(JsonWriter out, Book value) throws IOException { out.beginObject(); out.name("isbn").value(value.getIsbn()); out.name("title").value(value.getTitle()); out.name("authors").value(value.getAuthors()[0] + ";yoshin"); out.endObject(); } @Override public Book read(final JsonReader in) throws IOException { final Book book = new Book(); in.beginObject(); while (in.hasNext()) { switch (in.nextName()) { case "isbn": book.setIsbn(in.nextString()); break; case "title": book.setTitle(in.nextString()); break; case "authors": book.setAuthors(in.nextString().split(";")); break; } } in.endObject(); return book; } }

    调用

    public void main() { final GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.registerTypeAdapter(Book.class, new BookTypeAdapter()); gsonBuilder.setPrettyPrinting(); final Gson gson = gsonBuilder.create(); final Book book = new Book(); book.setAuthors(new String[]{"Joshua Bloch", "Neal Gafter"}); book.setTitle("Java Puzzlers: Traps, Pitfalls, and Corner Cases"); book.setIsbn("978-0321336781"); final String json = gson.toJson(book); System.out.println("Serialised"); System.out.println(json); final Book parsedBook = gson.fromJson(json, Book.class); System.out.println("\nDeserialised"); System.out.println(parsedBook); }

    输出:

    I/System.out: Serialised I/System.out: { I/System.out: "isbn": "978-0321336781", I/System.out: "title": "Java Puzzlers: Traps, Pitfalls, and Corner Cases", I/System.out: "authors": "Joshua Bloch;yoshin" I/System.out: } I/System.out: Deserialised I/System.out: Book{authors=[Joshua Bloch, yoshin], isbn='978-0321336781', title='Java Puzzlers: Traps, Pitfalls, and Corner Cases'}

    分析:

    Serialised 是序列化后的结果;Deserialised是反序列后的结果。

    TypeAdapter内包含序列化和反序列化两个自定义步骤。 其中write是序列化后的过程;read是反序列化的过程。

    2.1 序列化

    @Override public void write(JsonWriter out, Book value) throws IOException { out.beginObject(); out.name("isbn").value(value.getIsbn()); out.name("title").value(value.getTitle()); out.name("authors").value(value.getAuthors()[0] + ";yoshin"); out.endObject(); }

    以上是序列化的自定义过程。

    其中,如果想输出Object类型,则:out.beginObject();和 out.endObject();成对出现; 如果需要输出Array,则: out.beginArray();和 out.endArray();成对出现。

    最终Book会输出成JsonWriter。

    2.2 反序列化

    @Override public Book read(final JsonReader in) throws IOException { final Book book = new Book(); in.beginObject(); while (in.hasNext()) { switch (in.nextName()) { case "isbn": book.setIsbn(in.nextString()); break; case "title": book.setTitle(in.nextString()); break; case "authors": book.setAuthors(in.nextString().split(";")); break; } } in.endObject(); return book; }

    以上是自定义反序列化的过程。

    接收Object类型需要:in.beginObject();和 in.endObject(); 接收Array类型需要: in.beginArray();和 in.endArray();

    这是一个由JsonReader 转化成Book数据的过程。

    JsonReader 提供的方法: 有没有数据:in.hasNext() 下一个KEY名:in.nextName()

    总结

    TypeAdapter是泛型设计,提供了基本的接口(序列化和反序列化)封装,但是核心的reader和writer接口还需要子类实现。

    如果想把序列化和反序列化分开,只做其一操作,可以实现JsonSerializer 和JsonDeserializer。 不用像TypeAdapter一样,必须要实现序列化和反序列化的过程,你可以据需要选择,如只接管序列化的过程就用 JsonSerializer ,只接管反序列化的过程就用 JsonDeserializer。

    工作原理(转载自)

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

    Processed: 0.009, SQL: 9