1. 开始
构建maven项目
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.smallbear</groupId>
<artifactId>gson-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8.1</version>
</dependency>
</dependencies>
</project>
实体类
@Data
@Accessors(chain = true)
public class Person {
private String name;
private Boolean isAdult;
private Integer age;
@SerializedName("email_or_phone")
private String emailOTelephone;
private Job job;
private List<Pet> pets;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Job {
private String name;
private BigDecimal salary;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Pet {
private String name;
private String type;
private Integer age;
}
@Data
@Accessors(chain = true)
public class Role {
private String name;
private String username;
private Date createTime;
private BigDecimal money;
private Integer level;
}
2. gson解析对象
/**
* Gson解析对象 object -> json
*/
@Test
public void test01() {
Gson gson = new Gson();
Job job = new Job("teacher", BigDecimal.valueOf(8000.0));
System.out.println(gson.toJson(job)); // {"name":"teacher","salary":8000.0}
}
/**
* 属性重命名 @SerializedName
*在pojo字段上标注@SerializedName可以设置输出json的字段的属性名
*/
@Test
public void test02() {
Gson gson = new Gson();
Person person = new Person()
.setName("小明")
.setIsAdult(true)
.setAge(23)
.setEmailOTelephone("12345678.qq.com");
System.out.println(gson.toJson(person));
// {"name":"小明","isAdult":true,"age":23,"email_or_phone":"12345678.qq.com"}
//gson默认不解析值为null的字段
}
3. gson反序列化
/**
* Gson反序列化 json -> object
*/
@Test
public void test03() {
Gson gson = new Gson();
String s = "{\"name\":\"小明\",\"isAdult\":false,\"age\":14,\"job\":{\"name\":\"teacher\",\"salary\":8000.0},\"pets\":[{\"name\":\"jack\",\"type\":\"mouse\",\"age\":3},{\"name\":\"tom\",\"type\":\"cat\",\"age\":4}]}";
Person person =gson.fromJson(s, Person.class);
System.out.println(person);
// Person(name=小明, isAdult=false, age=14, emailOTelephone=null, job=Job(name=teacher, salary=8000.0), pets=[Pet(name=jack, type=mouse, age=3), Pet(name=tom, type=cat, age=4)])
}
/**
* Gson解析泛型
*/
@Test
public void test04() {
Gson gson = new Gson();
String s = "[{\"name\":\"jack\",\"type\":\"mouse\",\"age\":3},{\"name\":\"tom\",\"type\":\"cat\",\"age\":4}]";
List<Pet> list = gson.fromJson(s, new TypeToken<List<Pet>>() {}.getType());
System.out.println(list);
// [Pet(name=jack, type=mouse, age=3), Pet(name=tom, type=cat, age=4)]
}
4、Gson高级使用
1、GsonBuilder的使用
/**
* 使用GsonBuilder配置解析方式
*/
@Test
public void test05() {
Gson gson = new GsonBuilder()
.serializeNulls() // 序列化null
.setDateFormat("yyyy-MM-dd HH:mm:ss") // 格式化时间
.setPrettyPrinting() // 格式化输出
.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE) // 字段首字母大写
.create();
Role role = new Role()
.setName("魔导师")
.setUsername("tom")
.setCreateTime(new Date())
.setMoney(BigDecimal.valueOf(111111));
System.out.println(gson.toJson(role));
}
/*
{
"Name": "魔导师",
"Username": "tom",
"CreateTime": "2019-11-13 22:05:38",
"Money": 111111,
"Level": null
}
*/
2、@Expose注解设置字段是否解析
@Data
@Accessors(chain = true)
public class Book {
/**
* 被@Expose标记的字段会参与序列化和反序列化
*/
@Expose
private String name;
private String EnglishName;
/**
* serialize和deserialize默认为true,即会参与序列化和反序列化
* author字段会被序列化,但不会反序列化
*/
@Expose(deserialize = false)
private String author;
@Expose
private BigDecimal price;
}
/**
* 注解@Expose
*/
@Test
public void test06() {
Gson gson = new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation()
.create();
Book book = new Book()
.setName("Spring实战")
.setEnglishName("Spring In Action")
.setAuthor("Craig Walls")
.setPrice(BigDecimal.valueOf(89.00));
String json = gson.toJson(book);
System.out.println(json);
Book b = gson.fromJson(json, Book.class);
System.out.println(b);
}
/*
{"name":"Spring实战","author":"Craig Walls","price":89.0}
Book(name=Spring实战, EnglishName=null, author=null, price=89.0)
*/
注意:要是
@Expose
注解起作用一定要采用GsonBuilder
创建Gson并且调用了excludeFieldsWithoutExposeAnnotation()
才起作用。
- 使用TypeAdapter自定义解析方式
@Data
@Accessors(chain = true)
public class User {
private String name;
private Integer age;
private String[] hobbies;
}
public class UserTypeAdapter extends TypeAdapter<User> {
/**
* 序列化
*/
public void write(JsonWriter writer, User user) throws IOException {
writer.beginObject();
writer.name("name").value(user.getName());
writer.name("age").value(user.getAge());
writer.name("hobbies").value(StringUtils.join(user.getHobbies(), ";"));
writer.endObject();
}
/**
* 反序列化
*/
public User read(JsonReader reader) throws IOException {
final User user = new User();
reader.beginObject();
while (reader.hasNext()) {
String s = reader.nextName();
if ("name".equals(s)) {
user.setName(reader.nextString());
} else if ("age".equals(s)) {
user.setAge(reader.nextInt());
} else if ("hobbies".equals(s)) {
user.setHobbies(reader.nextString().split(";"));
}
}
reader.endObject();
return user;
}
}
测试
/**
*
*/
@org.junit.Test
public void test08() {
Gson gson = new GsonBuilder()
.registerTypeAdapter(User.class, new UserTypeAdapter()) // 注册自定义的类型适配器
.setPrettyPrinting()
.create();
User user = new User()
.setName("王八")
.setAge(13)
.setHobbies(new String[] {"游泳", "跑步", "健身"});
System.out.println(gson.toJson(user));
String s = "{\"name\":\"王八\",\"age\":13,\"hobbies\":\"游泳;跑步;健身\"}";
String s2 = "{\"name\":\"李四\",\"age\":53}";
System.out.println(gson.fromJson(s, User.class));
System.out.println(gson.fromJson(s2, User.class));
}
/*
{
"name": "王八",
"age": 13,
"hobbies": "游泳;跑步;健身"
}
User(name=王八, age=13, hobbies=[游泳, 跑步, 健身])
User(name=李四, age=53, hobbies=null)
*/
- TypeAdapter解析复杂对象
@Data
@Accessors(chain = true)
public class Movie {
private String name;
private Double score;
private List<Actor> actors;
@Data
@AllArgsConstructor
@NoArgsConstructor
static class Actor {
private Integer id;
private String name;
}
}
public class MovieTypeAdapter extends TypeAdapter<Movie> {
@Override
public void write(JsonWriter writer, Movie movie) throws IOException {
writer.beginObject();
writer.name("name").value(movie.getName());
writer.name("score").value(movie.getScore());
writer.name("actors").beginArray();
if (movie.getActors() != null) {
for (Movie.Actor actor : movie.getActors()) {
writer.beginObject();
writer.name("id").value(actor.getId());
writer.name("name").value(actor.getName());
writer.endObject();
}
}
writer.endArray();
writer.endObject();
}
@Override
public Movie read(JsonReader reader) throws IOException {
final Movie movie = new Movie();
reader.beginObject();
while (reader.hasNext()) {
String s = reader.nextName();
if ("name".equals(s)) {
movie.setName(reader.nextString());
} else if ("score".equals(s)) {
movie.setScore(reader.nextDouble());
} else if ("actors".equals(s)) {
reader.beginArray();
final List<Movie.Actor> actors = new ArrayList<>();
while (reader.hasNext()) {
reader.beginObject();
final Movie.Actor actor = new Movie.Actor();
while (reader.hasNext()) {
String s2 = reader.nextName();
if ("id".equals(s2)) {
actor.setId(reader.nextInt());
} else if ("name".equals(s2)) {
actor.setName(reader.nextString());
}
}
actors.add(actor);
reader.endObject();
}
movie.setActors(actors);
reader.endArray();
}
}
reader.endObject();
return movie;
}
}
测试
@org.junit.Test
public void test09() {
Gson gson = new GsonBuilder()
.registerTypeAdapter(Movie.class, new MovieTypeAdapter())
// .setPrettyPrinting()
.create();
List<Movie.Actor> actors = new ArrayList<>();
actors.add(new Movie.Actor(1, "贝尔"));
actors.add(new Movie.Actor(2, "希斯.莱杰"));
Movie movie = new Movie()
.setName("黑暗骑士")
.setScore(9.2)
.setActors(actors);
System.out.println(gson.toJson(movie));
Movie movie2 = new Movie()
.setName("千与千寻")
.setScore(9.1);
System.out.println(gson.toJson(movie2));
String s = "{\"name\":\"黑暗骑士\",\"score\":9.2,\"actors\":[{\"id\":1,\"name\":\"贝尔\"},{\"id\":2,\"name\":\"希斯.莱杰\"}]}";
String s2 = "{\"name\":\"千与千寻\",\"score\":9.1,\"actors\":[]}";
System.out.println(gson.fromJson(s, Movie.class));
System.out.println(gson.fromJson(s2, Movie.class));
}
/*
{"name":"黑暗骑士","score":9.2,"actors":[{"id":1,"name":"贝尔"},{"id":2,"name":"希斯.莱杰"}]}
{"name":"千与千寻","score":9.1,"actors":[]}
Movie(name=黑暗骑士, score=9.2, actors=[Movie.Actor(id=1, name=贝尔), Movie.Actor(id=2, name=希斯.莱杰)])
Movie(name=千与千寻, score=9.1, actors=[])
*/
- GsonBuilder方法解释
- setFieldNamingPolicy 设置序列字段的命名策略
UPPER_CAMEL_CASE
(首字母大写)
UPPER_CAMEL_CASE_WITH_SPACES
(首字母大写并且驼峰转空格)
LOWER_CASE_WITH_UNDERSCORES
(大写转小写,驼峰转"_")
LOWER_CASE_WITH_DASHES
LOWER_CASE_WITH_DOTS
- addDeserializationExclusionStrategy 设置反序列化时字段采用策略ExclusionStrategy,如反序列化时不要某字段,当然可以采用@Expore代替。
- excludeFieldsWithoutExposeAnnotation 设置没有@Expore则不序列化和反序列化
addSerializationExclusionStrategy 设置序列化时字段采用策略,如序列化时不要某字段,当然可以采用@Expore代替。 - registerTypeAdapter 为某特定对象设置固定的序列和反序列方式,实现JsonSerializer和JsonDeserializer接口
- setFieldNamingStrategy 设置字段序列和反序列时名称显示,也可以通过@Serializer代替
- setPrettyPrinting 设置gson转换后的字符串为一个比较好看的字符串
- setDateFormat 设置解析时的日期格式
参考链接:
Java 中 Gson的使用
Gson高级使用和GsonBuilder设置
Gson全解析(上)-Gson基础
Gson全解析(中)-TypeAdapter的使用
Gson全解析(下)-Gson性能分析
网友评论