文章目录
1. gson
1.1 gson基本用法
回顾gson的使用,并找一些json格式的数据进行解析。
String response="[{img=0.0,name=非会员,qualify_amount=0.0}," +
"{img=1.0,name=一级会员,qualify_amount=100.0}," +
"{img=2.0, name=二级会员,qualify_amount=300.0}]";
由于是数组中有多个对象,所以可以用List的方法进行解析,解析方法如下:
Gson gson=new Gson();
//数组的话可以这么做
List<User>users=gson.fromJson(response,new TypeToken<List<User>>(){
}.getType());
for (User user:users){
System.out.println(user.img+" "+user.name+" "+user.qualify_amount);
1.2 属性重命名
这里参考自Gson用法详解。当我们的接口返回的数据与我们期望的数据不同时,我们可以使用属性重命名。或者下述的json数据中有一个tz,我们怕忘记它的意思想给他改成time,就需要使用@SerializedName 来建立与java字段的联系。
/**
* admin_area : 北京
* tz : +8.00
* location : 北京
* lon : 116.4052887
* parent_city : 北京
* cnty : 中国
* lat : 39.90498734
* cid : CN101010100
*/
private String admin_area;
@SerializedName("tz")
private String time;
SerializedName远比你想象的更强大,假如,json数据如下:userName,user_name,Name,都是指向一个值,此时我们可以使用alternate属性。很奇怪的是,我翻看了我的SerializedName类发现竟然没有alternate这个属性,黑人问号脸,为什么问号它围绕着我?
{
\"userName\":\"leavesC\",\"age\":24,\"sex\":true}
{
\"user_name\":\"leavesC\",\"age\":24,\"sex\":true}
{
\"Name\":\"leavesC\",\"age\":24,\"sex\":true}
@SerializedName(value = "userName", alternate = {
"user_name", "Name"})
private String name;
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.google.gson.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({
ElementType.FIELD})
public @interface SerializedName {
String value();
}
1.3 JsonDeserializer
参考自Gson 解析复杂数据。首先有一个Json对象,表示一本书的基本信息。
{
'title': 'Java Puzzlers: Traps, Pitfalls, and Corner Cases',
'isbn-10': '032133678X',
'isbn-13': '978-0321336781',
'authors': ['Joshua Bloch', 'Neal Gafter']
}
java的变量名不容许有‘-’符号的,我们可以使用@SerializedName注解来处理,不过对于一些复杂情况是难以处理的,所以我们使用JsonDeserializer。我们需要自定义一个JsonDeserializer,然后注册到GsonBuilder,GsonBuilder在解析时就会自动使用我们自定义的JsonDeserializer。
首先我们需要创建一个BookJsonDeserializer。它负责把Book对应的Json对象,解析为Java对象。
public class BookDeserializer implements JsonDeserializer<Book> {
@Override
public Book deserialize(final JsonElement jsonElement, final Type typeOfT, final JsonDeserializationContext context)
throws JsonParseException {
//todo 解析字段
final Book book = new Book();
book.setTitle(title);
book.setIsbn10(isbn10);
book.setIsbn13(isbn13);
book.setAuthors(authors);
return book;
}
}
简单介绍下JsonDeserializer,它需要有一个Type,那肯定是我们的Book。我们要重写deserialize()函数,并在其中解析json数据,最后返回一个Book对象。这里比较重要的是,Gson解析Json对象在内部表示为JsonElement,虽然element是元素的意思,但JsonElement可以表示为下列的任何一种:
1. JsonPrimitive :Java 基本类型的包装类,以及 String
2. JsonObject:类比 Js 中 Object的表示,或者 Java 中的 Map<String, JsonElement>,一个键值对结构。
3. JsonArray:JsonElement 组成的数组,注意:这里是 JsonElement,说明这个数组是混合类型的。
4. JsonNull:值为 null
完整代码如下,根据上述所讲,就可以解释,为什么要用getAsString和getAsJsonArray了。使用getAsString时是这个JsonElement表示为JsonPrimitive。使用getAsJsonArray时,虽然读取的是[‘Joshua Bloch’, ‘Neal Gafter’]这个数组,但表示为JsonElement所以,要给他转化一下。
class BookDeserializer implements JsonDeserializer<Book>{
@Override
public Book deserialize(final JsonElement jsonElement, final Type typeOfT,
final JsonDeserializationContext context)throws JsonParseException{
final JsonObject jsonObject=jsonElement.getAsJsonObject();
JsonElement titleElement=jsonObject.get("title");
final String title=titleElement.getAsString();
JsonElement isbn10Element=jsonObject.get("isbn-10");
final String isbn10=isbn10Element.getAsString();
JsonElement isbn13Element=jsonObject.get("isbn-13");
final String isbn13=isbn13Element.getAsString();
//虽然是个数组,但Gson解析json对象并在内部表示为JsonElement,
// 这里的其实是表示为JsonElement的JsonArray,所以要在get之后用getAsJsonArray();
JsonArray authors=jsonObject.get("authors").getAsJsonArray();
String[]Authors=new String[authors.size()];
//Array中存放的是element
int i=0;
for(JsonElement jsonElement1:authors){
Authors[i++]=jsonElement1.getAsString();
}
//todo 解析字段
final Book book=new Book();
book.setTitle(title);
book.setIsbn10(isbn10);
book.setIsbn13(isbn13);
book.setAuthors(Authors);
return book;
}
Book类
class Book{
private String[] authors;
private String isbn10;
private String isbn13;
private String title;
public String[] getAuthors() {
return authors;
}
public void setAuthors(String[] authors) {
this.authors = authors;
}
public String getIsbn10() {
return isbn10;
}
public void setIsbn10(String isbn10) {
this.isbn10 = isbn10;
}
public String getIsbn13() {
return isbn13;
}
public void setIsbn13(String isbn13) {
this.isbn13 = isbn13;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
@Override
public String toString() {
return "Book{" +
"authors=" + Arrays.toString(authors) +
", isbn10='" + isbn10 + '\'' +
", isbn13='" + isbn13 + '\'' +
", title='" + title + '\'' +
'}';
}
}
这里要注意一下,Book类我们要重写一下toString(),否则的话无法得到我们想要的结果,直接System.out.println(book)就会输出book对应的地址。我们的检验代码如下:
切记不要直接创建Gson,而是要县创建GsonBuilder实例,并通过registerTypeAdapter传入要解析成的类(Book)以及对应的解析器实例(BookDeserializer)去注册解析器,之后通过GsonBuilder创建Gson实例。
public static void main(String[]args){
String response="{\"title\":\"Java Puzzlers: Traps, Pitfalls, and Corner Cases\"," +
"\"isbn-10\":\"032133678X\"," +
"\"isbn-13\":\"978-0321336781\"," +
"\"authors\":[\"Joshua Bloch\"," +
"\"Neal Gafter\"]}";
//使用GsonBuilder来注册BookDeserializer,并创建Gson对象,这样的话,
// 需要解析Book的时候,就会使用BookDeserializer来解析
GsonBuilder gsonBuilder=new GsonBuilder();
gsonBuilder.registerTypeAdapter(Book.class,new BookDeserializer());
Gson gson=gsonBuilder.create();
Book book = gson.fromJson(response, Book.class);
System.out.println(book);
}
最后是解析的过程:
1.将输入的字符串解析为JsonElement
2.找到对应的JsonDeserializer来解析,就找到我们的BookDeserializer
3.传入参数进deserialize()函数,将JsonElement转换成Book对象
4.将Book对象通过fromJson()返回
1.4 对象嵌套
假如数据的结构如下,大类是Book类,其中还包括Author类