zoukankan      html  css  js  c++  java
  • Gson ------ 实例演习

    【本文范围】:

    本文并非JSON知识讲解资料,亦非GSON知识讲解资料,而是通过实例让开发人员了解通过Gson如何使Java对象和Json对象进行相互转换。

    【JSON参考资料】:

    Json快速入门:http://www.w3school.com.cn/json/index.asp

    Json官网:http://www.json.org/

    【GSON参考资料】:

    Gson官网:http://code.google.com/p/google-gson/

    一、JSON基础知识:

    1、Json概念:

    Json全称JavaScript object notation(Javascript对象表示法),是轻量级的文本数据交换格式,它独立于语言和平台,用来描述数据对象,具有自我描述性、容易理解等特性。

    2、举例:

    {“TeamName":"hr", "NewProject":true, "Leader":"wang", "Employee":[{"name":"li", "BelongTo":"train"}, {"name":"kpi", "BelongTo":"Security"}, {"name":"liu", "BelonTo":"service"}]}

    这个Json对象描述了hr项目组。项目组名称为hr,是一个新项目,Leader是wang,有三个员工,分别为负责培训的li,负责Security的kpi和负责服务的liu。

    3、Json语法

    数据以健值对形式描述(如:"TeamName":"hr");

    数据以逗号分隔;

    花括号保存对象(如{"Name":"li", "BelongTo":"train"});

    方括号保存数组(如"csn":[20,21,22,23]);

    4、Json值:

    数字(整数或浮点数);

    字符串(在双引号中);

    逻辑值(true或false);

    数组(在方括号中);

    对象(在花括号中);

    null

    二、实例演习:

    实例1:在查询告警窗口中对告警流水号为2012的记录做“清除”操作

    【思路】:

    假如清除操作的命令码为41,那么向服务端请求的JSON对象应该为{“cmdCode”:41, “csn”:2012}

    【演示代码】:

    1、定义AlarmClearCondition.java

    public class AlarmClearCondition
    {
    private int cmdCode = 0;
    private int csn = 0;
    public void setCmdCode(int cmdCode)
    {
    thisNaNdCode = cmdCode;
    }
    public void setCsn(int csn)
    {
    this.csn= csn;
    }
    }

    2、使用Gson把AlarmClearCondition对象转换为Json对象

    AlarmClearConditioncondition = new AlarmClearCondition();
    condition.setCmdCode(41);
    condition.setCsn(2012);
    Gson gson = newGson();
    String jsonCond= gson.toJson(condition);

    实例2:在查询告警窗口中对告警流水号为2012和2013的记录做“清除”操作

    【思路】:

    与实例1不同,这里的CSN有两个,意味着告警流水号CSN必须是一个数组,那么向服务端请求的JSON对象应该为{“cmdCode”:41, “csn”:[2012, 2013]}

    【演示代码】:

    1、改造AlarmClearCondition.java定义,使csn变成一个集合csnList

    public class AlarmClearCondition
    {
    private int cmdCode = 0;
    private List<Integer> csnList = newArrayList<Integer>();
    public void setCmdCode(int cmdCode)
    {
    thisNaNdCode = cmdCode;
    }
    public void setCsn(int csn)
    {
    csnList.add(csn);
    }
    }

    2、把AlarmClearCondition对象转换为Json对象

    AlarmClearConditioncondition = new AlarmClearCondition();
    condition.setCmdCode(41);
    condition.setCsn(2012);
    condition.setCsn(2013);
    Gson gson = newGson();
    String jsonCond= gson.toJson(condition);

    实例3:若实例2中对流水号2012和2013的两条记录“清除”成功后,服务端返回的结果为{“errorCode”:0, “errorMsg”:“Clear alarmssuccessful!”, “clearedCsn”:[2012, 2013]},则客户端如何把这个结果解析为Java对象?

    【思路】:

    1、直接用硬编码进行解析未尝不可,但代码不够优雅。

    2、与生成Json对象一样定义一个Java类,剩余的转换工作由Gson协助完成。见演示代码。

    【演示代码】:

    1、定义AlarmClearResult

    public class AlarmClearResult
    {
    private int errorCode = 0;
    privateString errorMsg = null;
    private List<Integer> clearedCsn = new ArrayList<Integer>();
    
    public int getErrorCode()
    {
    return errorCode;
    }
    
    public String getErrorMsg()
    {
    return errorMsg;
    }
    
    public List<Integer> getClearedCsn()
    {
    return clearedCsn;
    }
    }

    2、把Json对象转换为AlarmClearResult对象

    AlarmClearResult result =gson.fromJson(jsonObject, AlarmClearResult.class);

    实例4:当前屏最后一条告警记录流水号为44531611,查询下一屏告警记录时与服务端约定请求条件为{“FieldName”:”logId”,”Operator”:”<”, “value”:44531611},使用Gson把Java对象转换为此Json对象,但要求Java的属性字段定义为是“驼峰”风格。

    【思路】:

    1、不考虑属性字段定义“驼峰”风格问题,那只需要把FileNameOperatorvalue作为Java类的属性即可,见演示代码1

    2、为使Java属性字段定义和显示为不同的值,Gson提供了@SerializedName注释,见演示代码2.

    【演示代码1】:

    1、定义EndlessQuery类

    public class EndlessQuery
    {
    private String FieldName = null;
    private String Operator = null;
    private int value = 0;
    
    public void setFieldName(String filedName)
    {
    this.FieldName = fieldName;
    }
    
    public void setOperator(String operator)
    {
    this.Operator = operator;
    }
    
    public void setValue(int value)
    {
    this.value = value;
    }
    }

    2、把AlarmClearResult转换为JSON对象

    EndlessQueryqueryCond = new EndlessQuery();
    queryCond.setFiledName(“logId”);
    queryCond.setOperator(“<”);
    queryCond.setValue(44531611);
    Gson gson = newGson();
    System.out.println(gson.toJson(queryCond));

    【演示代码2】:

    只修改EndlessQuery类的FileName和Operator两个字段即可,其余保持不变,如下:

    public class EndlessQuery
    {
    @SerializedName(“FieldName”)
    private String fieldName= null;
    @SerializedName(“Operator”)
    private String operator= null;
    private int value = 0;
    
    public void setFieldName(String filedName)
    {
    this.fieldName = fieldName;
    }
    
    public void setOperator(String operator)
    {
    this.operator = operator;
    }
    public void setValue(int value)
    {
    this.value = value;
    }
    }

    实例5:列举一个稍微真实的场景,告警监控TOPN是指客户端向任意一个应用服务下发请求后,应用服务从各个数据服务中读取最新上报的TOPN条告警记录,然后再把获取的告警记录按条件进行重排序取TOPN条给客户端。

    假如监控TOPN的命令码为22,每次监控40条最新的告警记录,在获取这40条最新的告警记录时使用的排序条件为“按网元发生时间”和“告警流水号”进行降序排序,其JSON对象为{"CmdCode":22, "Limit":40, "VersionID":0, "SortCond":[{"FieldName":"occurNeTime", "SortOrder":"desc","Priority":1},{"FieldName":"logId", "SortOrder":"desc", "Priority":6}]},则客户端如何生成这个JSON对象?

    【思路】:

    1、直接拼凑字符串代码(不是本文的意图)。

    2、定义属性字段为CmdCode、Limit、VersionID和SortCond的类,但SortCond与其它字段不同之处在于SortCond是一个集合,这个集合中对象类型必须能够描述出按“网元发生时间”和“流水号”进行排序。

    【演示代码】:

    1、定义排序SortConditionBean对象

    public class SortConditionBean
    {
    @SerializedName("FieldName")
    private String fieldName = null;
    @SerializedName("SortOrder")
    private String order = null;
    @SerializedName("Priority")
    private int priority = 0;
    
    public void setFieldName(String fieldName)
    {
    this.fieldName = fieldName;
    }
    public void setOrder(String order)
    {
    this.order = order;
    }
    public void setPriority(int priority)
    {
    this.priority = priority;
    }
    }

    2、定义监控TOPN对象MonitorTopnCond类

    public class MonitorTopnCond
    {
    @SerializedName("CmdCode")
    private int cmdCode = 0;
    @SerializedName("VersionID")
    private int versionID = 0;
    @SerializedName("Limit")
    private int limit = 0;
    @SerializedName("SortCond")
    private List<SortCondtionBean> sortCond = new ArrayList<SortConditionBean>():
    
    public void setCmdCode(int cmdCode)
    {
    this.cmdCode = cmdCode;
    }
    public void setVersionID(int versionID)
    {
    this.versionID = versionID;
    }
    public void setLimit(int limit)
    {
    this.limit = limit;
    }
    public void setSortCond(SortConditionBean sortItem)
    {
    this.sortCond.add(sortItem);
    }
    }

    3、测试方法:

    SortConditionBean occuTime = new SortConditionBean();
    occuTime.setFieldName("occurNeTime");
    occuTime.setOrder("desc");
    occuTime.setPriority(1);
    
    SortConditionBean logID = new SortConditionBean();
    logID.setFieldName("logId");
    logID.setOrder("desc");
    logID.setPriority(6);
    
    MonitorTopnCond topnCond = new MonitorTopnCond();
    topnCond.setCmdCode(22);
    topnCond.setLimit(40);
    topnCond.setVersionID(0);
    topnCond.setSortCond(occuTime);
    topnCond.setSortCond(logID);
    
    Gson gson = new Gson();
    System.out.println(gson.toJson(topnCond));

    实例6:实例5中向应用服务下发监控TopN请求之后,应用服务从各个数据分区读取数据后,再重排序取了Top40条告警记录返回客户端,结果如下(为简单起见这里把40条告警记录改成1条):

    {
    "ErrorMsg": "0",
    "LastVersionId": 0,
    "ResultCode":0,
    "TotalNum":24006,
    "records":
    [
    {
    "Basic":["链路断连","BTS","NE=10009","NE=10009","Location=Test1, m_strPara=1","",-1,19],
    "Paras":[0,0,0,0,0,19,0,0,0,0],
    "intExt":[[0,0,0,0,0,0,0,0,0,0],[134, 13528,0,0,4,199,199]],
    "strExt":[["","",""], ["","","","","127.0.0,1","",""]]
    }
    ]
    }

    客户端如何解析这个Json对象呢?

    【思路】:

    仔细观察返回结果可发现,它由ErrorMsg、LastVersionId、ResultCode、TotalNum、records构成,所以可以定义一个Java类使其包含这五个属性字段。重要的一点records不同于ErrorMsg等属性字段,它又由有Basic、Paras、intExt和strExt构成。

    【演示代码】:

    1、定义告警记录对象AlarmRecord,对应record集合中的一个元素。

    public class AlarmRecord
    {
    @SerializedName("Basic")
    private List<Object> basicField = null;
    @SerializedName("Paras")
    private List<Integer> parasField = null;
    @SerializedName("intExt")
    private int[][] intExtField = null;
    @SerializedName("strExt")
    private String[][] strExtField = null;
    
    public List<Object> getBasicField()
    {
    return basicField;
    }
    
    public List<Integer> getParasField()
    {
    return parasField;
    }
    
    public int[][] getIntExtField()
    {
    return intExtField;
    }
    
    public String[][] getStrExtField()
    {
    return strExtField;
    }
    }

    2、定义结果响应对象AlarmResponseRecord

    public class AlarmResponseRecord
    {
    @SerializedName("ResultCode")
    private int errorCode = 0;
    @SerializedName("ErrorMsg")
    private String errorMessage = null;
    @SerializedName("LastVersionId")
    private int versionID = 0;
    @SerializedName("TotalNum")
    private int totalNum = 0;
    private List<ALarmRecord> records = null;
    
    public int getErrorCode()
    {
    return errorCode;
    }
    public String getErrorMessage()
    {
    return errorMessage;
    }
    
    public int getVersionID()
    {
    return versionID;
    }
    
    public int getTotalNum()
    {
    return totalNum;
    }
    
    public List<AlarmRecord> getRecords()
    {
    return records;
    }
    }

    3、测试方法:

    String result = "{'ErrorMsg':'ccq', 'LastVersionId':0, 'ResultCode':0, 'TotalNum':24006, 'records':[{'Basic':[0,'通讯系统',3,0,0,0,'链路断连'], 'Paras':[0,0,0,19,0,0], 'intExt':[[1,2,3,4,5],[6,7,8,9,11]], 'strExt':[['a','b','c','d'],['','','']]}]}";
    Gson gson = new Gson();
    AlarmResponseRecord almRecords = gson.fromJson(result, AlarmResponseRecord .class);
    System.out.println(almRecords.getRecords());

    实例7:告警监控TOPN请求的JSON对象为:

    {"CmdCode":22,"Limit":40,"VersionID":0,"SortCond":[{"FieldName":"occurNeTime", "SortOrder":"desc", "Priority":1},{"FieldName":"logId", "SortOrder":"desc","Priority":6}]}

    告警无尽列表查询请求的JSON对象为

    {"CmdCode":21,"Limit":41,"SortCond":[{"FieldName":"occurNeTime", "SortOrder":"desc", "Priority":1},{"FieldName":"logId", "SortOrder":"desc","Priority":6}],"EndlessTableCond":[{"FieldName":"occurNeTime", "Operator":"=","value":[1355899366]},{"FieldName":"logId", "Operator":"<","value":[33394632]}]}

    仔细观察会发现这两个请求的JSON对象结构非常类似,如何使用一个Java对象生成这两个Json对象呢?

    【思路】:

    很容易想到的是把相同的数据作为Java的属性字段(如CmdCode、Limit、SortCond),不同的数据作为子类属性字段(如EndlessTableCond、VersionID),使用Java的继承机制可实现。

    【演示代码】:

    1、定义排序对象SortConditionBean

    public class SortConditionBean
    {
    @SerializedName("FieldName")
    private String fieldName = null;
    @SerializedName("SortOrder")
    private String order = null;
    @SerializedName("Priority")
    private int priority = 0;
    
    public void setFieldName(String fieldName)
    {
    this.fieldName = fieldName;
    }
    public void setOrder(String order)
    {
    this.order = order;
    }
    public void setPriority(int priority)
    {
    this.priority = priority;
    }
    }

    2、定义无尽列表查询对象EndlessConditionBean

    public class EndlessConditionBean
    {
    private String FieldName = null;
    private String Operator = null;
    private int value = 0;
    public void setFieldName(String fieldName)
    {
    this.FieldName = fieldName;
    }
    public void setOperator(String operator)
    {
    this.Operator = operator;
    }
    public void setValue(int value)
    {
    this.value = value;
    }
    }

    3、定义公共父类AlarmConditionBean对象

    public class AlarmConditionBean
    {
    @SerializedName("CmdCode")
    private int cmdCode = 0;
    @SerializedName("Limit")
    private int limit = 0;
    @SerializedName("SortCond")
    private List<SortConditionBean> sortCond = new ArrayList<SortConditionBean>();
    
    public void setCmdCode(int cmdCode)
    {
    thisNaNdCode = cmdCode;
    }
    public void setLimit(int limit)
    {
    this.limit = limit;
    }
    public void setSortCond(SortConditionBean sortItem)
    {
    this.sortCond.add(sortItem);
    }
    }

    5、定义监控AlarmMonitorBean类

    public class AlarmMonitorBean extends AlarmConditionBean
    {
    @SerializedName("VersionID")
    private int versionID = 0;
    public void setVersionID(int versionID)
    {
    this.versionID = versionID;
    }
    }

    6、定义查询AlarmQueryBean类

    public class AlarmQueryBean extends AlarmConditionBean
    {
    @SerializedName("EndlessTableCond")
    private List<EndlessConditionBean> queryCond = new ArrayList<EndlessConditionBean>();
    public void setEndlessCond(EndlessConditionBean endlessItem)
    {
    queryCond.add(endlessItem);
    }
    }

    7、测试代码

    测试告警监控TOPN

    SortConditionBean occuTimeSortItem = new SortConditionBean();
    occuTimeSortItem.setFieldName("occurNeTime");
    occuTimeSortItem.setOrder("desc");
    occuTimeSortItem.setPriority(1);
    
    SortConditionBean logIDSortItem = new SortConditionBean();
    logIDSortItem.setFieldName("logId");
    logIDSortItem.setOrder("desc");
    logIDSortItem.setPriority(6);
    
    AlarmMonitorBean monitorCond = new AlarmMonitorBean();
    monitorCond.setCmdCode(22);
    monitorCond.setLimit(40);
    monitorCond.setVersionID(0);
    monitorCond.sortSortCond(occuTimeSortItem);
    monitorCond.sortSortCond(logIDSortItem);
    
    Gson gson = new Gson();
    System.out.println(gson.toJson(monitorCond));

    测试告警无尽列表查询:

    SortConditionBean occuTimeSortItem = new SortConditionBean();
    occuTimeSortItem.setFieldName("occurNeTime");
    occuTimeSortItem.setOrder("desc");
    occuTimeSortItem.setPriority(1);
    
    SortConditionBean logIDSortItem = new SortConditionBean();
    logIDSortItem.setFieldName("logId");
    logIDSortItem.setOrder("desc");
    logIDSortItem.setPriority(6);
    
    EndlessConditionBean occuTimeEndlessItem = new EndlessConditionBean();
    occuTimeEndlessItem.setFieldName("occurNeTime");
    occuTimeEndlessItem.setOperator("=");
    occuTimeEndlessItem.setValue(1355899366);
    
    EndlessConditionBean logIDEndlessItem = new EndlessConditionBean();
    logIDEndlessItem.setFieldName("logId");
    logIDEndlessItem.setOperator("<");
    logIDEndlessItem.setValue(33394632);
    
    AlarmQueryBean queryCond = new AlarmQueryBean();
    queryCond.setCmdCode(21);
    queryCond.setLimit(41);
    queryCond.setSortCond(occuTimeSortItem);
    queryCond.setSortCond(logIDSortItem);
    queryCond.setEndlessCond(occuTimeEndlessItem);
    queryCond.setEndlessCond(logIDEndlessItem);
    
    Gson gson = new Gson();
    System.out.println(gson.toJson(queryCond));

    【备注】:

    关于此例还有一种解决方式,即使用Gson的@Since注释,但这样会影响代码的易读性,不建议使用,有兴趣的读者可以了解一下Gson的API

     

     

    实例8:服务端返回给客户端的数据只是一个数组,如[96301,0,1,"链路断连","BTS","NE=1009"],此时客户端如何解析?

    【思路】:

    JSON对象在定义数据时明确指出数据是一个键值对,但并不表明Gson不能解析,因为这也是一个Json对象,这样做的目的主要是为了减少通讯传输量给带宽带来的拥挤。假如各字段的含义如下:

    96301 0 1 链路断连 BTS NE=1009
    告警流水号 清除状态 确认状态 告警类型 告警源类型 告警源

    【演示代码】:

    1、定义告警记录AlarmRecord类

    final class AlarmSimpleRecord
    {
    private int logID = 0;
    private int clearStatus = 0;
    private int confirmStatus = 0;
    private String alarmType = null;
    private String neType = null;
    private String neFDN = null;
    
    public int getLogID()
    {
    return logID;
    }
    public void setLogID(int logID)
    {
    this.logID = logID;
    }
    
    public int getClearStatus()
    {
    return clearStatus;
    }
    public void setClearStatus(int clearStatus)
    {
    this.clearStatus = clearStatus;
    }
    
    public int getConfirmStatus()
    {
    return confirmStatus;
    }
    public void setConfirmStatus(int confirmStatus)
    {
    this.confirmStatus = confirmStatus;
    }
    
    public String getAlarmType()
    {
    return alarmType;
    }
    public void setAlarmType(String alarmType)
    {
    this.alarmType = alarmType;
    }
    
    public String getNeType()
    {
    return neType;
    }
    public void setNeType(String neType)
    {
    this.neType = neType;
    }
    
    public String getNeFDN()
    {
    return neFDN;
    }
    public void setNeFDN(String neFDN)
    {
    this.neFDN = neFDN;
    }
    }

    2、解析演示

    public class AlarmRecord
    {
    /**
    * 定义各字段的序号
    */
    private static final int LOG_ID = 0;
    private static final int CLEAR_STATUS = 1;
    private static final int CONFIRM_STATUS = 2;
    private static final int ALARM_TYPE = 3;
    private static final int NE_TYPE = 4;
    private static final int NE_FDN = 5;
    
    public static void main(String[] args)
    {
    String result = "[96031, 0 ,1, '链路断连','BTS', 'NE=10009']";
    Gson gson = new Gson();
    JsonElement resultElement = gson.fromJson(result, JsonElement.class);
    if(resultElement.isJsonNull())
    {
    // do nothing.
    return;
    }
    
    AlarmSimpleRecord record = new AlarmSimpleRecord();
    JsonArray elementArray = resultElement.getAsJsonArray();
    record.setLogID(elementArray.get(LOG_ID).getAsInt());
    record.setClearStatus(elementArray.get(CLEAR_STATUS).getAsInt());
    record.setConfirmStatus(elementArray.get(CONFRIM_STATUS).getAsInt());
    record.setAlarmType(elementArray.get(ALARM_TYPE).getAsString());
    record.setNeType(elementArray.get(NE_TYPE).getAsString());
    record.setNeFDN(elementArray.get(NE_FDN).getAsString());
    
    System.out.println(record);
    }
    }

    本文转自:http://qingkechina.blog.51cto.com/5552198/1299025

  • 相关阅读:
    【LeetCode】1248. 统计「优美子数组」
    【LeetCode】200. 岛屿数量
    【LeetCode】53. 最大子序和
    【剑指Offer】面试题42. 连续子数组的最大和
    【剑指Offer】面试题57. 和为s的两个数字
    【LeetCode】55. 跳跃游戏
    【LeetCode】56. 合并区间
    简历HTML网页版
    关于新建Eclipse新建一个WEB项目后创建一个jsp文件头部报错问题?
    jquery选择器 看这个链接吧!2017.6.2
  • 原文地址:https://www.cnblogs.com/sishuiliuyun/p/3458036.html
Copyright © 2011-2022 走看看