通过郭神的代码和说明加上这两天查看的资料,学到了很多以前没注意没总结的json知识。通过这篇文章可以了解到以下几点。 A. json数据形式,一般有三种 jsonObject:{key:value},只要是这种形式的json数据,一定要写成key-value。并且如果是这样的数据,不管多复杂,如下图(郭神的数据),如果使用JSONObect解析,第一步一定是将字符串数据变成JSONObject,如下
JSONObject jsonObject = new JSONObject(获取到的string数据);JSONArray:[],这里可以分为两种,[{},{},{}]和[“”,”“,111,true],不管哪一种这数组中一个要至少有一个数据,并且如果要使用JSONArray解析,不管多复杂的数据结构,见下图(郭神的数据),第一步都是使用下面这行代码,
JSONArray jsonArray = new JSONArray(string类型的数据);这是他们的共同点。不同点,是[{},{}]这种类型的JSONArray,{}对象里面一定是JSONObject,即一定要写成key-value形式。 B. 学习到了GSON解析和JSONObject或者JSONArray解析的区别,GSON解析如果要获取整个json数据中某一个字段的数据,(下面有例子),一般通过把bean写好,然后通过方法,直接可以获取字段外面的对象,然后通过对象通过get或者.属性获取数据。但是JSONObject或者JSONArray需要一层层剥洋葱样剥到某个字段的数值,并且要获取最外层对象,还要一层层从里面的对象塞数据,知道塞到我们想要的。 C. 对于一个json数据,我们想要什么字段的数据就在bean里面写好自己想要数据的字段,一定要写准确,如果担心字段的名字不符合我们java定义属性的名字,可以通过GSON库里面SerializedName解决,还是一样,一定要写匹配。如下图,整个json数据中,我只是想要获取,这两个字段的value也是可以的。(下面例子)
"lat":"28.197000","lon":"112.967000"D. 发现一个查看json数据的好工具HiJson 2.1.2_jdk64.exe,可以通过它将复杂的json数据格式化。当然此类的工具很多,在线的也很多,如果,见图。
A. 首先上面我说了很多非常确定的言语,现在验证下。
比较这两个,明显可以知道上面这个不是json数据,放到工具验证,见图 {"a":"bbb","b":2,"c":true,"d"} {"a":"bbb","b":2,"c":true,"d":22.22}还有这种
["a",true,22.2,333,{"aa"}]和["a",true,22.2,333,{"aa":"ccc"}]上面说了,只要是{}里面的一定要是key-value形式,不然一定不是json数据,所以前面的不是json数据,后面的才是,顺便说一句,前面也说了,只要是这种[]形式,如果要用JSONArray解析,通过下标value。 B. 写了个小例子,主要是为了学习,JSONObject和JSONArray解析json数据。数据来源就是上面说的两个 这里写链接内容 这里写链接内容 开始说了,对于第一个数据,我要全部解析出来,并且把省份的名字显示成一个列表。对于第二个数据,我要获取其中两个字段的value。见效果图。 布局代码就不贴了,很简单,两个button和一个listview。并且我这里请求接口用的是okhttp3。 首先去工具看清楚这个json数据。 根据上面的这是[{},{},{}]的数据,更巧的是这{}里面的字段key是一样的,所以可以直接看成一个对象,而这整个是个这个对象的数组。所以我把这个对象写出来为Province,代码如下,这没什么好说的,字段匹配即可。
package guo.com.jsondataparse; import com.google.gson.annotations.SerializedName; /** * Created by ${GuoZhaoHui} on 2017/3/9. * email:guozhaohui628@gmail.com */ public class Province { @SerializedName("id") public int id; @SerializedName("name") public String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }假设我们已经网络请求,获取到这个json字符串了,先写一个方法解析这个数据。前面也说了,只要是[]这种类型的都是先放到JSONArray中,
JSONArray jsonArray = new JSONArray(response);这样就变成了一个json数组了,每个数组的元素都是JSONObject,所以我可以对这个数组循环遍历,
for(int i=0;i<jsonArray.length();i++){ JSONObject jsonObject = jsonArray.getJSONObject(i); Province province = new Province(); province.setId(jsonObject.getInt("id")); province.setName(jsonObject.getString("name")); provinceList.add(province); }只要一个JSONObject接近到字段,都是可以通过JOSNObject.getString(“”)或者其他方法拿到value。我这里选择把循环拿到的value保存到list中。 代码如下:
/** * 从json数据解析成对象 * @param response * @return */ public List<Province> parseJsonProvince(String response){ try { JSONArray jsonArray = new JSONArray(response); List<Province> provinceList = new ArrayList<>(); for(int i=0;i<jsonArray.length();i++){ JSONObject jsonObject = jsonArray.getJSONObject(i); Province province = new Province(); province.setId(jsonObject.getInt("id")); province.setName(jsonObject.getString("name")); provinceList.add(province); } return provinceList; } catch (JSONException e) { e.printStackTrace(); } return null; }接下来的代码大致就是点击按钮,开启线程用okhttp3请求,获取response,用刚才的方法解析成list,对着个list循环遍历,获取list中对象的name属性,保存成为一个list。切换到主线程,用listview加载适配器。代码如下
this.findViewById(R.id.bt).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new Thread(){ @Override public void run() { super.run(); sendOkHttpRequest(URL1, new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { provinceList = parseJsonProvince(response.body().string()); for(Province province:provinceList){ stringList.add(province.getName()); } runOnUiThread(new Runnable() { @Override public void run() { ArrayAdapter arrayAdapter = new ArrayAdapter(MainActivity.this, android.R.layout.simple_list_item_1, stringList); listView.setAdapter(arrayAdapter); } }); } }); } }.start(); } });现在对第二个数据解析,我需要获取到这个数据中的lat和lon两个字段的value,见图 思路:因为是这种形式的{},所以第一步一定是
JSONObject jsonObject = new JSONObject(response);然后可以看到这个key对应的value是个[],所以通过key拿到value,key一定要写对,最好复制
JSONArray jsonArray = jsonObject.getJSONArray("HeWeather");然后再看结构,我们需要的两个value在basic这个字段中,而basic是这个数组中的第一个元素对象中的一个字段,所以如果我们把basic堪称一个对象,则这两个字段就是其中的属性。所以先把basic这个对象定义出来
package guo.com.jsondataparse; import com.google.gson.annotations.SerializedName; /** * Created by ${GuoZhaoHui} on 2017/3/10. * email:guozhaohui628@gmail.com */ public class Basic { @SerializedName("lat") public String lat; @SerializedName("lon") public String log; public String getLat() { return lat; } public void setLat(String lat) { this.lat = lat; } public String getLog() { return log; } public void setLog(String log) { this.log = log; } @Override public String toString() { return "Basic{" + "lat='" + lat + '\'' + ", log='" + log + '\'' + '}'; } }json数据中basic中包含很多字段,但是我们不需要,所以写上两个我们需要的属性。然后我把数组[]中的第一个元素堪称对象weather,所以weather的类就是这样子
package guo.com.jsondataparse; import com.google.gson.annotations.SerializedName; /** * Created by ${GuoZhaoHui} on 2017/3/10. * email:guozhaohui628@gmail.com */ public class Weather { @SerializedName("basic") public Basic basic; }同理,我这里只是定义其中我们需要的属性。 拿到这个[]中的第一个元素,看json我们知道是个{},所以是JSONObject
JSONObject jsonWeather = jsonArray.getJSONObject(0);对于这个JSONObject其实是这养的{“basic”:{“lat”:”28.222”,”lon”:”112.22”}},所以同理我们通过key获取到这个value,这个value也是个JSONObject。
JSONObject jsonBasic = jsonWeather.getJSONObject("basic");到了这一步,这个JSONObject已经接近我们需要的字段了,所以直接通过拿到value。
jsonBasic.getString("lat") jsonBasic.getString("lon")代码如下:
/** * 解析天气json数据中的lat和log两个字段,并将解析出来的数据存到Basic对象中 * @param response * @return */ public Basic parseJsonBasic(String response){ try { Basic basic = new Basic(); JSONObject jsonObject = new JSONObject(response); JSONArray jsonArray = jsonObject.getJSONArray("HeWeather"); //GSON解析方法 // String jsonWeather = jsonArray.getJSONObject(0).toString(); // Weather weather = new Gson().fromJson(jsonWeather,Weather.class); // basic = weather.basic; JSONObject jsonWeather = jsonArray.getJSONObject(0); JSONObject jsonBasic = jsonWeather.getJSONObject("basic"); basic.setLat(jsonBasic.getString("lat")); basic.setLog(jsonBasic.getString("lon")); Log.i(TAG, basic.toString()); return basic; } catch (JSONException e) { e.printStackTrace(); } return null; }接下来的思路和第一个按钮点击一样,首先点击按钮,在里面开启线程获取json数据,通过刚才的方法解析数据,切换到主线程,弹出一个吐司框
this.findViewById(R.id.bt2).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new Thread(){ @Override public void run() { super.run(); sendOkHttpRequest(URL2, new Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { final Basic basic = parseJsonBasic(response.body().string()); runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(MainActivity.this,"经纬度-->"+basic.toString(),Toast.LENGTH_SHORT).show(); } }); } }); } }.start(); } });源码
