Gson学习-1

原文地址:https://www.jianshu.com/p/e740196225a4

简介:

JSON 是一种轻量级的数据交换格式。 易于人阅读和编写。同时也易于机器解析和生成
Java中最常用的类库有:JSON-Java、Gson、Jackson、FastJson等
注意点
1.一个对象以 {左括号 开始,}右括号 结束
2.一个数组以[左中括号 开始,]右中括号 结束
3.字符串是由双引号包围的任意数量Unicode字符的集合,使用反斜线转义引号。

集成Gson


   com.google.code.gson
   gson
   2.8.5

一、Gson的基本用法

Gson提供了fromJson()toJson()两个直接用于解析和生成的方法,前者实现反序列化,后者实现了序列化。同时每个方法都提供了重载方法,我常用的总共有5个。

下文学习
Gson.toJson(Object);
Gson.fromJson(Reader,Class);
Gson.fromJson(String,Class);
Gson.fromJson(Reader,Type);
Gson.fromJson(String,Type);

基本数据类型的解析

Gson gson = new Gson();
int i = gson.fromJson("100", int.class);              //100
double d = gson.fromJson("\"99.99\"", double.class);  //99.99
boolean b = gson.fromJson("true", boolean.class);     // true
String str = gson.fromJson("String", String.class);   // String

第二行为一个字符串
基本数据类型的生成

Gson gson = new Gson();
String jsonNumber = gson.toJson(100);       // 100
String jsonBoolean = gson.toJson(false);    // false
String jsonString = gson.toJson("String"); //"String"

普通java对象的生成与解析

public class Student {
    public String name;
    public int age;
    public String emailAddress;
    //省略其他
    public Student(String name, int age, String emailAddress) {
        this.name = name;
        this.age = age;
        this.emailAddress = emailAddress;
    }
    public Student() {
    }
}
        Gson gson = new Gson();
        Student student = new Student("星星",22,"[email protected]");
        String jsonObject = gson.toJson(student);
        System.out.println(jsonObject);
        //{"name":"星星","age":22,"emailAddress":"[email protected]"}

二、属性重命名 @SerializedName 注解的使用

默认的json的字段和值是和类中名称和类型是一一对应的
现在想实现

{"name":"星星","age":22,"emailAddress":"[email protected]"}
不想要这样的email,需求下面的样式
{"name":"星星","age":22,"email_address":"[email protected]"}

SerializedName注解的使用

1.@SerializedName("email_address")
public String emailAddress;
解释为把emailAddress变成email_address
上面的代码生成的json就是下面这样的了
{"name":"星星","age":22,"email_address":"[email protected]"}

2.@SerializedName(value = "emailAddress", alternate = {"email", "email_address"})
一个String,一个String数组表示备选属性名
解释为json生成类的时候,遇到email或者email_address都变成emailAddress

三、Gson中使用泛型

1.JSON解析字数组
一般有两种方式:使用数组,使用List。List对于增删都是比较方便的,所以实际使用是还是List比较多。

使用数组
        Gson gson = new Gson();
        String arraystr = "[\"Android\",\"Java\",\"PHP\"]";
        String[] strings = gson.fromJson(arraystr, String[].class);
        System.out.println(Arrays.toString(strings));
        //[Android, Java, PHP]

但对于List将上面的代码中的 String[].class直接改为 List.class是行不通的。对于Java来说ListList 这俩个的字节码文件只一个那就是List.class,这是Java泛型使用时要注意的问题 泛型擦除

为了解决的上面的问题,Gson为我们提供了TypeToken来实现对泛型的支持,所以当我们希望使用将以上的数据解析为List时需要这样写。

        Gson gson = new Gson();
        String arraystr = "[\"Android\",\"Java\",\"PHP\"]";
        List stringList = gson.fromJson(arraystr, new TypeToken>() {}.getType());
        System.out.println(stringList);
        //[Android, Java, PHP]


TypeToken的构造方法是protected修饰的,所以上面才会写成
new TypeToken>() {}.getType()
而不是
new TypeToken>().getType()
2.当返回的数据分为两类或者更多比如:

data是数组
{"code":"0","message":"success","data":[]}
data是对象
{"code":"0","message":"success","data":{}}

现在怎么设计这个大的对象呢?

public class Result {
    public int code;
    public String message;
    public T data;
}

这样用泛型代替
那么对于data字段是User时则可以写为 Result ,当是个列表的时候为 Result>,其它同理。

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import java.lang.reflect.Type;
import java.util.*;
public class Main {
    public static void main(String[] args) {
        Gson gson = new Gson();
//        data是数组
       String str1 =  "{\"code\":\"0\",\"message\":\"success\",\"data\":[{\"name\":\"星星1\",\"age\":\"22\",\"email\":\"[email protected]\"},{\"name\":\"星星2\",\"age\":\"22\",\"email\":\"[email protected]\"}]}";
//        data是对象
        String str2 = "{\"code\":\"0\",\"message\":\"success\",\"data\":{\"name\":\"星星\",\"age\":\"22\",\"email\":\"[email protected]\"}}";
        //data是数组
        Type userListType = new TypeToken>>(){}.getType();
        Result> userListResult = gson.fromJson(str1,userListType);
        System.out.println(gson.toJson(userListResult));
//{"code":0,"message":"success","data":[{"name":"星星1","age":22,"email":"[email protected]"},{"name":"星星2","age":22,"email":"[email protected]"}]}
        //data是对象
        Type userType = new TypeToken>(){}.getType();
        Result userResult = gson.fromJson(str2,userType);
        System.out.println(gson.toJson(userResult));
//{"code":0,"message":"success","data":{"name":"星星","age":22,"email":"[email protected]"}}
    }
}

当data数组里面里面为字符串的时候:

String str1 =  "{\"code\":\"0\",\"message\":\"success\",\"data\":[\"123\",\"456\"]}";
Type userListType = new TypeToken>>(){}.getType();
Result> userListResult = gson.fromJson(str1,userListType);
System.out.println(gson.toJson(userListResult));
尝试为List 失败

四、解析如下奇葩字符串

{
  0={"name":"星星1","age":22,"email":"[email protected]"},
  1={"name":"星星2","age":22,"email":"[email protected]"},
  2={"name":"星星3","age":22,"email":"[email protected]"}
}

这里用到自定义反序列化

利用JsonDeserializer 接口只需要实现一个反序列化方法deserialize 就足够了
1.定义解析成的类型User2

public class User2 {
    Map map;
    class Data {
        public String name;
        public int age;
        public String email;

        @Override
        public String toString() {
            return "Data{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    ", email='" + email + '\'' +
                    '}';
        }
    }
}

2.定义自定义的反序列化

public class MapDeserializer implements JsonDeserializer {
//    当请求将JSON内容反序列成java类型对象的时候,该方法将会被调用。然后,会返回一个
//    由方法自己构造的对象实例。
//    需要注意的是,当JSON为null的时候,该方法该不会被调用,因此,方法不需要去check 该值是否为null
//参数1 是json字符串 参数2 是返回的类型 参数3传递给自定义反序列化器的上下文 抛出错误如果解析的json字符串不包括指定的类型
    @Override
    public User2 deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
//        将指定成员作为JsonObject获取的便捷方法。
        JsonObject jsonObject=jsonElement.getAsJsonObject();
//        返回此对象的一组成员。
        Set> set=jsonObject.entrySet();
//        定义map
        Map map = new HashMap<>();
//        遍历set
        for(Map.Entry s : set){
//            定义一个user2的data
            User2.Data data = jsonDeserializationContext.deserialize(s.getValue().getAsJsonObject(), User2.Data.class);
//            入map s.getKey() 和 data
            map.put(Integer.valueOf(s.getKey()),data);
        }
//        最后返回一个整体User2
        User2 user2 = new User2();
        user2.map=map;
        return user2;
    }
}

3.注册自定义的反序列化并使用

public static void main(String[] args) {

        String str = "{0={\"name\":\"星星1\",\"age\":22,\"email\":\"[email protected]\"},1={\"name\":\"星星2\",\"age\":22,\"email\":\"[email protected]\"},2={\"name\":\"星星3\",\"age\":22,\"email\":\"[email protected]\"}}";
        User2 user2 = new User2();
        Gson gson = new GsonBuilder()
                .registerTypeAdapter(User2.class, new MapDeserializer())//为User2注册MapDeserializer
                .create();
        user2 = gson.fromJson(str,User2.class);
        System.out.println(user2.map.get(1));
//        Data{name='星星2', age=22, email='[email protected]'}
    }

你可能感兴趣的:(Gson学习-1)