Gson 是一个Java库,可用于将Java对象转换为它们的Json 表示形式。它还可以用于将Json 字符串转换为等效的Java对象。Json 的解析和生成的方式很多,在 Android 平台上最常用的类库有 Gson 和 FastJson 两种,这里要介绍的是 Gson。
Gson 的 GitHub 主页点击这里:Gson
Gradle:
dependencies {
implementation 'com.google.code.gson:gson:2.8.9'
}
new Gson().toJson(obj)
类
Object sss= new Gson().fromJson(json, Object.class);
复杂类型
Map ss= new Gson().fromJson(json, new TypeToken
首先我们定义一个场景。
定义Album 类代表专辑,专辑中有很多歌曲Song
public class Album{
private String name;
private float price;
private List songs = new ArrayList();
// generated getters and setters.
...
}
定义Song 类代表歌曲,歌曲附属于专辑Album
public class Song{
private String name;
private int duration;
private Album album;
// generated getters and setters.
...
}
赋值
//先定义一个专辑
Album album = new Album();
album.setName("叶惠美");
album.setPrice(10.00f);
//再定义专辑中的两首歌
Song song1 = new Song();
//song1.setAlbum(album);//此时必须注释,不然引用循环了
song1.setDuration(240);
song1.setName("以父之名");
Song song2 = new Song();
//song2.setAlbum(album);//此时必须注释,不然引用循环了
song2.setDuration(180);
song2.setName("晴天");
//将两首歌都添加为专辑的子项
List songList = new ArrayList<>();
songList.add(song1);
songList.add(song2);
album.setSongs(songList);
String json = new Gson().toJson(album);
得到Json字符串
{
"name":"叶惠美",
"price":10.0,
"songs":
[
{
"duration":240,
"name":"以父之名"
},
{
"duration":180,
"name":"晴天"
}
]
}
此时有个问题,这是把song中的album注释掉才跑通的,但是实际的项目中你不可能在转换为Json字符串之前把album置为null之后再进行Json转换。Gson中有个办法可以解决:增加注释
public class Song{
@Expose
private String name;
@Expose
private int duration;
private Album album;
}
public class Album{
@Expose
private String name;
@Expose
private float price;
@Expose
private List songs = new ArrayList();
}
调用
String json = new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation() //不导出实体中没有用@Expose注解的属性
.create().toJson(album);
如果代码中使用了litepal框架,类就会不可避免的继承LitePalSupport,那么其实这个基类内部就会自己增加一些字段导致反射的时候也会将这些字段反射出来,把这些固定字段反射时跳过就好了
public class MyLitepalGson extends MyGson {
public MyLitepalGson() {
super(customizeGson());
}
private static String[] litepalExcludes = {"baseObjId", "associatedModelsMapWithFK",
"associatedModelsMapWithoutFK", "associatedModelsMapForJoinTable",
"listToClearSelfFK", "listToClearAssociatedFK", "fieldsToSetToDefault"};
private static Gson customizeGson() {
GsonBuilder builder = new GsonBuilder();
// builder.excludeFieldsWithoutExposeAnnotation();
return builder
.serializeNulls() //加个输出空值
.addSerializationExclusionStrategy(new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes f) {
Expose annotation = f.getAnnotation(Expose.class);
// if (annotation == null || (serialize ? !annotation.serialize() : !annotation.deserialize())) {
// return true;
// }
if (annotation != null && !annotation.serialize()) {
return true;
}
for (String exclude : litepalExcludes) {
if (exclude.equals(f.getName())) {
return true;
}
}
return false;
}
@Override
public boolean shouldSkipClass(Class> clazz) {
return false;
}
}).create();
}
}
其实对象转为Json字符串时,顺序是按照首字母a到z的顺序排列的,但有时就是有那么一些特殊的需求需要自定义顺序,使用TypeAdapter,JsonSerializer或者 JsonDeserializer等接口可以自定义序列化
public class AlbumTypeAdapter extends TypeAdapter {
/**
* Writes one JSON value (an array, object, string, number, boolean or null)
* for {@code value}.
*
* @param out
* @param value the Java object to write. May be null.
*/
@Override
public void write(JsonWriter out, Album value) throws IOException {
out.beginObject();
//按自定义顺序输出字段信息
out.name("1").value(value.getName());
out.name("2").value(value.getPrice());
out.name("3");
out.beginArray();
for(int i =0;i
调用
String json = new GsonBuilder()
.registerTypeAdapter(Album.class,new AlbumTypeAdapter());
.create().toJson(album);