Gson的使用

【前言】最近项目中对数据的解析都使用了Gson,艹蛋的是每次都要手写JavaBean对象很麻烦。抱着能否简化的心态阅读了Gson的部分源码。发现很多以前没有注意到的知识点。

写在前面的话

Gson是一个Java库,可用于将Java对象转换为JSON表示。它也可以用来将JSON字符串转换为等效的Java对象。 Gson可以使用任意Java对象,包括您没有源代码的预先存在的对象。

如何生成Json
JsonObject jsonObject = new JsonObject();
JsonObject jsonArray = new JsonObject();

//addProperty():产生JsonObject
jsonObject.addProperty("testString","7c");
jsonObject.addProperty("testInt",7);
jsonObject.addProperty("testBoolean",true);
jsonObject.addProperty("testCharater","7c");

jsonArray.addProperty("testStringArray","7c");
jsonArray.addProperty("testIntArray",7);
jsonArray.addProperty("testBooleanArray",true);

jsonObject.add("JsonElement",jsonArray);
System.out.println(jsonObject.toString());
//Json结构
{
    "JsonElement": {
        "testBooleanArray": true,
        "testIntArray": 7,
        "testStringArray": "7c"
    },
    "testBoolean": true,
    "testCharater": "7c",
    "testInt": 7,
    "testString": "7c"
}
手动解析Json
try {
            JSONObject originJson = new JSONObject(json);
            ManualresolutionBean manualresolutionBean = new ManualresolutionBean();
            boolean success = originJson.optBoolean("success");
            int failCode = originJson.optInt("failCode");
            JSONArray data = originJson.optJSONArray("data");

            List<ManualresolutionBean.JsonList> jsonLists = new ArrayList();
            manualresolutionBean.setFailCode(failCode);
            manualresolutionBean.setSuccess(success);
            for (int i = 0 ; i < data.length() ; i ++){
                JSONObject jsonObject1 = data.getJSONObject(i);
                JsonList jsonList = new JsonList();
                String check = jsonObject1.optString("check");
                String id = jsonObject1.optString("id");
                int isPoor = jsonObject1.optInt("isPoor");
                String level = jsonObject1.optString("level");
                String model = jsonObject1.optString("model");
                String name = jsonObject1.optString("name");
                String pid = jsonObject1.optString("pid");
                String sort = jsonObject1.optString("sort");
                String supportPoor = jsonObject1.optString("supportPoor");

                jsonList.setCheck(check);
                jsonList.setId(id);
                jsonList.setIsPoor(isPoor);
                jsonList.setLevel(level);
                jsonList.setModel(model);
                jsonList.setName(name);
                jsonList.setPid(pid);
                jsonList.setSort(sort);
                jsonList.setSupportPoor(supportPoor);
                jsonLists.add(jsonList);
            }
            manualresolutionBean.setList(jsonLists);
        } catch (JSONException e) {
            e.printStackTrace();
        }
}
解析图.JPG

【注意】
1.蓝色标记部分手动解析的时候充当JSONObject;【】充当JSONArray。
2.如果你放在main函数中执行会报 java.lang.RuntimeException: Stub!。这是因为你在Java中使用Android包出错。

通过构造器来创建Gson

new Gson()是我们日常开发中经常用来解析数据的方式。熟悉的人员请绕过这部分。

String jsonArray = "[\"U\",\"A\",\"R\",\"T\"]";

Gson gson = new Gson();

 //json与数组的转换

//json转换为数组
String[] strings = gson.fromJson(jsonArray, String[].class);
for (String string : strings){
       System.out.println(string);
 }
//数组转换为json
String s = gson.toJson(strings);
System.out.println(s);
System.out.println("=================================");
//json转换为List
 //new TypeToken<List<String>>(){}.getType()这里为什么需要一个{},查看TypeToken源码可以发现
 //这样一段话TypeToken<List<String>> list = new TypeToken<List<String>>() {};
List<String> list = gson.fromJson(jsonArray, new TypeToken<List<String>>() {
        }.getType());
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){
      String next = iterator.next();
      System.out.println(next);
}
//List转换为json
String listJson = gson.toJson(list,new TypeToken<List<String>>() {
        }.getType());
System.out.println(listJson);

Gson用法进阶

属性重命名
  • 场景:服务端返回的字段名,与我们本地的字段名有出入。
  • 原理及用法:@SerializedName 指示此成员的注释应该以提供的名称值作为其字段名称序列化为JSON。
    @SerializedName("name") String a;
    @SerializedName(value="name1", alternate={"name2", "name3"}) String b;
@SerializedName(value ="name",alternate = {"userName","Name","Kobe"})
public String name;

String json =  "{\"name\": \"Uart\"}";
String json1 =  "{\"userName\": \"Uart\"}";
String json2 =  "{\"Name\": \"Uart\"}";
String json3 =  "{\"Kobe\": \"Uart\"}";

Gson gson = new Gson();
User user = gson.fromJson(json,new TypeToken<User>(){}.getType());
User user1 = gson.fromJson(json1,new TypeToken<User>(){}.getType());
User user2 = gson.fromJson(json2,new TypeToken<User>(){}.getType());
User user3 = gson.fromJson(json3,new TypeToken<User>(){}.getType());
user.toString();
user1.toString();
user2.toString();
user3.toString();

字段过滤

基于@Expose注解
  • 原理:指示此成员的注释应公开给JSON序列化或反序列化。
  • 注意 :此注释要生效必须调用GsonBuilder的excludeFieldsWithoutExposeAnnotation()方法。
  • 用法:
    @Expose private String firstName;
    @Expose(serialize = false) private String lastName;
    @Expose (serialize = false, deserialize = false) private String emailAddress;
    private String password;
@Expose(serialize = true, deserialize = true)   //序列化和反序列化都生效
private String a;

@Expose(serialize = false, deserialize = true)  //序列化时不生效,反序列化时生效
private String b;

@Expose(serialize = true, deserialize = false)  //序列化时生效,反序列化时不生效
private String c;

@Expose(serialize = false, deserialize = false) //序列化和反序列化都不生效,和不写注解一样
private String d;

private String e;

Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
FilterBean filterBean = new FilterBean("A", "B", "C", "D", "E");

//序列化
System.out.println(gson.toJson(filterBean));

//反序列化
String json = "{\"a\":\"A\",\"b\":\"B\",\"c\":\"C\",\"d\":\"D\",\"e\":\"E\"}";
FilterBean filterBean1 = gson.fromJson(json, FilterBean.class);
System.out.println(filterBean1.toString());

//输出结果
{"a":"A","c":"C"}
FilterBean{a='A', b='B', c='null', d='null', e='null'}
基于版本
  • 原理:@Since自成员或类型出现以来表示版本号的注释。
    @Until表示直到成员或类型应该存在的版本号的注释。
    此注释对于管理Web服务的Json类的版本控制非常有用。
  • 注意:此注释要生效必须调用GsonBuilder的setVersion(double)方法。
  • 用法:
    @Since(1.0) private String emailAddress;
    @Until(1.1) private String emailAddress;
@Since(1.3)
private String a;

@Until(1.9)
private String b;

@Since(1.5)
private String c;

@Until(1.2)
private String d;

private String e;

Gson gson = new GsonBuilder().setVersion(1.3).create();
FilterBean filterBean = new FilterBean("A", "B", "C", "D", "E");

//序列化
System.out.println(gson.toJson(filterBean));

//反序列化
String json = "{\"a\":\"A\",\"b\":\"B\",\"c\":\"C\",\"d\":\"D\",\"e\":\"E\"}";
FilterBean filterBean1 = gson.fromJson(json, FilterBean.class);
System.out.println(filterBean1.toString());

//输出结果
{"a":"A","b":"B","e":"E"}
FilterBean{a='A', b='B', c='null', d='null', e='E'}
基于访问修饰符
  • 原理:excludeFieldsWithModifiers()方法,配置Gson以排除所有具有指定修饰符的类字段。默认,Gson将排除所有标记为瞬态(transient)或静态(static)的字段。此方法将覆盖该行为。
public String publicField = "public";

protected String protectedField = "protected";

private String privateField = "private";

String defaultField = "default";

final String finalField = "final";

static String staticField = "static";

Gson gson2 = new GsonBuilder().excludeFieldsWithModifiers(Modifier.PRIVATE, Modifier.PUBLIC).create();
ModifierBean modifierBean = new ModifierBean();
System.out.println(gson2.toJson(modifierBean));

//输出结果
{"protectedField":"protected","defaultField":"default","finalField":"final","staticField":"static"}
基于策略
  • 原理:GsonBuilder 类包含 setExclusionStrategies(ExclusionStrategy... strategies)方法用于传入不定长参数的策略方法,用于直接排除指定字段名或者指定字段类型。
private String stringField;

private int intField;

private double doubleField;

public StrategiesBean(String stringField, int intField, double doubleField) {
        this.stringField = stringField;
        this.intField = intField;
        this.doubleField = doubleField;
}

Gson gson3 = new GsonBuilder().setExclusionStrategies(new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes f) {
//排除指定字段名
return f.getName().equals("stringField");
 }

 @Override
public boolean shouldSkipClass(Class<?> clazz) {
//排除指定字段类型
return clazz.getName().equals(double.class.getName()); }}).create();

StrategiesBean strategies = new StrategiesBean("stringField", 111, 11.22);
System.out.println();
System.out.println(gson3.toJson(strategies));

String json2 = "{\"stringField\":\"stringField\",\"intField\":111,\"doubleField\":11.22}";
strategies = gson3.fromJson(json2, StrategiesBean.class);
System.out.println();
System.out.println(strategies);

//输出结果
{"intField":111}

Strategies{stringField='null', intField=111, doubleField=0.0}

感兴趣的小伙伴可以研究一下setFieldNamingStrategy()、addDeserializationExclusionStrategy()、addSerializationExclusionStrategy()这三种方法

自定义配置

输出null

对于 Gson 而言,在序列化时如果某个属性值为 null 的话,那么在序列化时该字段不会参与进来,如果想要显示输出该字段的话,可以通过 GsonBuilder 进行配置。

Gson gson3 = new GsonBuilder()
                .serializeNulls()
                .create();

StrategiesBean strategies = new StrategiesBean(null, 111, 11.22);
System.out.println();
System.out.println(gson3.toJson(strategies));
//输出结果
{"stringField":null,"intField":111,"doubleField":11.22}
格式化输出Json

Gson gson3 = new GsonBuilder()
.serializeNulls()
.setPrettyPrinting()//格式化输出
.create();

StrategiesBean strategies = new StrategiesBean(null, 111, 11.22);
System.out.println();
System.out.println(gson3.toJson(strategies));
//输出结果
{
"stringField": null,
"intField": 111,
"doubleField": 11.22
}

TypeAdapter

  • 作用:将Java对象与JSON进行转换。默认情况下,Gson使用其内置类型将应用程序类转换为JSON适配器。如果Gson的默认JSON转换不适合某种类型,扩展此类以定制转换。
序列化交换位置
@Override
public void write(JsonWriter out, UartBean value) throws IOException {
        //序列化过程
        if(value == null) {
            out.nullValue();
            return;
        }
        String name = value.getName();
        int age = value.getAge();
        value.setName(age + "");
        value.setAge(Integer.valueOf(name));
        out.value(value.getName());
        out.value(value.getAge());
    }

@Override
public UartBean read(JsonReader in) throws IOException {
        //反序列化过程
        if(in.peek() == JsonToken.NULL) {
            in.nextNull();
            return null;
        }
        in.beginObject();
        UartBean uartBean = new UartBean();
        while(in.hasNext()) {
            switch (in.nextName()) {
                case "name" :
                    uartBean.setName(in.nextString());
                    break;
                case "age":
                    uartBean.setAge(in.nextInt());
                    break;
            }
        }
        in.endObject();
        return uartBean;
    }

Gson gson4 = new GsonBuilder().registerTypeAdapter(UartBean.class, new UartAdapter()).create();
UartBean uartBean = new UartBean("10", 20);
System.out.println(gson4.toJson(uartBean));

String json4 = "{\"name\":\"10\",\"age\":24}";
UartBean bean = gson4.fromJson(json4, UartBean.class);
System.out.println();
System.out.println(bean);

//输出结果
"20" 10
UartBean{name='10', age=24}

JsonSerializer 和 JsonDeserializer是TypeAdapter提供的专门针对序列化和反序列化的接口。感兴趣的朋友可以自行了解一下。

更新

 "156": "42F7B18E9C12ACFDC1B9",
 "156": "3247F56244FDE",

针对上述json字符串如何解析?

stationNameInfoList = new ArrayList<EquivalentStationNameInfo>();
        Iterator<String> keys = object.keys();

        while (keys.hasNext()) {
            EquivalentStationNameInfo equivalentStationNameInfo = new EquivalentStationNameInfo();
            String next = keys.next();
            equivalentStationNameInfo.setStationName(next);
            equivalentStationNameInfo.setStationId(object.optString(next));
            for (EquivalentHourInfo info : equivalentHourInfoList) {
                if (info.getStationName().equals(next)) {
                    stationNameInfoList.add(equivalentStationNameInfo);
                }
            }

        }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,056评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,842评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,938评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,296评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,292评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,413评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,824评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,493评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,686评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,502评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,553评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,281评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,820评论 3 305
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,873评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,109评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,699评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,257评论 2 341

推荐阅读更多精彩内容

  • 关于json,gson是最常用到的一个库。平常使用时我通常使用Gson gson = new Gson();的方式...
    黑泥卡阅读 10,053评论 1 14
  • 1.概述2.Gson的目标3.Gson的性能和扩展性4.Gson的使用者5.如何使用Gson 通过Maven来使用...
    人失格阅读 14,184评论 2 18
  • Android中Gson的使用 1 简介 Gson是一个Java库,作用是将Java对象转换成它对应的JSON表示...
    LuckyXiang阅读 19,625评论 2 3
  • 本文为作者根据日常使用结合Gson源码注释及wiki所作的原创内容,转载请注明出处。 该系列其它文章 你真的会用G...
    怪盗kidou阅读 61,085评论 67 141
  • 今天婆婆又在饭桌上当着大家的面教育儿子,我急忙喊妈妈,妈妈,你吃这个。我妈妈最爱机会教育,孩子高高兴兴的的...
    富足喜悦的二小姐阅读 167评论 3 4