JSON解析

来源:互联网 发布:自学编程看什么书 编辑:程序博客网 时间:2024/05/01 02:21

原生org.json.JSONObject;

1.创建

对于程序员来说,大多数都是解析JSON数据,但是创建JSON数据也是很有必要了解一下的。

(1)对象包含对象

public class CreateJSON {public static void main(String[] args) throws Exception {// 创建一个空白的obj对象JSONObject obj = new JSONObject();// 给obj存放信息obj.put("id",001);obj.put("name", "张三");obj.put("sex", "男");obj.put("score", 99.5);System.out.println(obj);//一个对象包含另一个对象JSONObject schooloobj = new JSONObject();schooloobj.put("schoolName", "北京大学");schooloobj.put("address", "不知道");schooloobj.put("student", obj);System.out.println(schooloobj);}}
打印结果:
{"score":99.5,"sex":"男","name":"张三","id":1}
{"address":"不知道","student":{"score":99.5,"sex":"男","name":"张三","id":1},"schoolName":"北京大学"}
放入顺序和显示顺序不同,原因在于底层使用Map存储方式,其实服务器就是这样给客户端提供数据的,只需要把syso改成write即可。

(2)对象包含数组的

public class CreateJSON {public static void main(String[] args) throws Exception {JSONObject schooloobj = new JSONObject();schooloobj.put("schoolName", "北京大学");schooloobj.put("address", "不知道");//存放数组JSONArray array = new JSONArray();for(int i=0;i<3;i++){JSONObject obj = new JSONObject();obj.put("id", i);obj.put("name", "李四"+i);obj.put("age", 15+i);array.put(obj);}schooloobj.put("student", array);System.out.println(schooloobj);}}
打印结果:

{"address":"不知道","student":[{"name":"李四0","id":0,"age":15},{"name":"李四1","id":1,"age":16},{"name":"李四2","id":2,"age":17}],"schoolName":"北京大学"}

由于是键值对形式存放,所以Values不能为null,但实际需求中往往存在很多空   解决方案:obj.put("key","null");或obj.put("key","");,



2.解析

JSON的解析数据千奇百怪,没有一个例子能够完全说明,只能通过他们的特点来解析,下面来看一下简单

例子1

public class ParseJSON {public static void main(String[] args) throws JSONException {String json = "{persons:[{name:'zhangsan',age:20},"+ "{name:'lisi',age:21}," + "{name:'wangwu',age:22}]}";JSONObject obj = new JSONObject(json);JSONArray array = obj.getJSONArray("persons");for(int i=0;i<array.length();i++){JSONObject obj2 = array.getJSONObject(i);String name = obj2.getString("name");int age = obj2.getInt("age");System.out.println(name+"\t"+age);}}}
打印结果:

zhangsan 20
lisi 21
wangwu 22


例子2:

public class ParseJSON {public static void main(String[] args) throws JSONException {String json = "[{name:'张三',scores:{en:90,math:99,cn:89}},"+ "{name:'李四',scores:{en:80,math:90,cn:99}}]";JSONArray arr = new JSONArray(json);for(int i=0;i<arr.length();i++){JSONObject obj2 = arr.getJSONObject(i);String name = obj2.getString("name");JSONObject scores = obj2.getJSONObject("scores");String en = scores.getString("en");//JSON数据给出的是int型数据,这里用String也是可以解析的int math = scores.getInt("math");int cn = scores.getInt("cn");System.out.println(name+"\t"+en+"\t"+math+"\t"+cn);}}}
打印结果:

张三 90 99 89
李四 80 9099


解析的小技巧:

解析的时候先看最外面的是{}还是[],前者就JSONObject 后者就JSONArray按照此规律一直往下扒,到了{"student":[{"name":"zhangsan"},{"name",lisi}]}的时候obj.getJSONArray("student")得到的是数组,数字再次循环遍历得到object对象就可以了。在实际解析过程中经常出现空指针异常,这很大的原因的解析的数据为null,JSON数据为空有三种,"" , "null"  , null  上述三种可以使用都是空,但只有null报错,可以使用isNull(key)判断,不等于空的时候在取值,另外getString有没有值都拿 而 optString 在没有值的情况下给你默认值,int 是0,字符串不是null,是""。

阿里com.alibaba.fastjson

1.创建 to

fastjson解析和创建必须有实体类的支持,并且JSON字符串的Key和实体类的属性一一对应,并且必须有get set方法,如果没有get set方法,就算有实体类也无法创建JSON字符串

下面是一一对应的例子1(未给出实体类)

public class ParseJSON {public static void main(String[] args) throws JSONException {Student s = new Student(1, "张三", "nan");Object object = JSON.toJSON(s);System.out.println(object.toString());}}

例子2:

public class CreateJsonString {public static void main(String[] args) {//生成集合的json字符串List<Student> list=new ArrayList<Student>();for (int i = 0; i < 5; i++) {Student ss=new Student(i,"张三"+i,"男");list.add(ss);}//对象套集合{    []}School s=new School();s.setName("清华");s.setAddress("不知道");s.setNumber(1000);s.setStudents(list);String jsonString=JSON.toJSONString(s);System.out.println(jsonString);}}

2.解析 parse

如果实体类是属性比JSON字符串的key少,那么属性有多少存多少,其他忽视,如果实体类的属性比JSON字符串的Key多,那么JSON字符串的Key有多少给实体类存多少,其他的是类属性的默认值。fastjson解析相对来说容易了许多,构建相同的实体类即可,这里只给出Test.java类,源码下载地址:http://download.csdn.net/detail/u010829905/8877673

例子1:
Test.java
public class ParseJSON {public static void main(String[] args) throws JSONException {String url = "http://weather.xcyh.org/json/7";HttpUtil.getImage(url, new CallBack() {@Overridepublic void getByteImage(byte[] b) {String stu = new String(b,Charset.forName("GBK"));String newstu = decodeUnicode(stu);Beijing object = JSON.parseObject(newstu, Beijing.class);System.out.println(object.getData().get(1).getTemperature());//至此解析完成了}});}//网络请求是unicode编码,下面方法的解决的//方法来源:http://ruixiazun.blog.163.com/blog/static/906879182013112439117/ public static String decodeUnicode(String theString) {          char aChar;          int len = theString.length();          StringBuffer outBuffer = new StringBuffer(len);          for (int x = 0; x < len;) {              aChar = theString.charAt(x++);              if (aChar == '\\') {                  aChar = theString.charAt(x++);                  if (aChar == 'u') {                      // Read the xxxx                      int value = 0;                      for (int i = 0; i < 4; i++) {                          aChar = theString.charAt(x++);                          switch (aChar) {                          case '0':                          case '1':                          case '2':                          case '3':                          case '4':                          case '5':                          case '6':                          case '7':                          case '8':                          case '9':                              value = (value << 4) + aChar - '0';                              break;                          case 'a':                          case 'b':                          case 'c':                          case 'd':                          case 'e':                          case 'f':                              value = (value << 4) + 10 + aChar - 'a';                              break;                          case 'A':                          case 'B':                          case 'C':                          case 'D':                          case 'E':                          case 'F':                              value = (value << 4) + 10 + aChar - 'A';                              break;                          default:                              throw new IllegalArgumentException(                                      "Malformed   \\uxxxx   encoding.");                          }                            }                      outBuffer.append((char) value);                  } else {                      if (aChar == 't')                          aChar = '\t';                      else if (aChar == 'r')                          aChar = '\r';                      else if (aChar == 'n')                          aChar = '\n';                      else if (aChar == 'f')                          aChar = '\f';                      outBuffer.append(aChar);                  }              } else                  outBuffer.append(aChar);          }          return outBuffer.toString();      }}

由于上述链接请求下来的JSON数据是unicode编码格式,普通的转换无法完成,所以找了上述方法 public static String decodeUnicode(String theString)该方法来源:http://ruixiazun.blog.163.com/blog/static/906879182013112439117/

例子2:

{
    "date": "20150708",
    "stories": [
        {
            "images": [
                "http://pic4.zhimg.com/f926183839b3fadfbdaf4fb82fbc4da3.jpg"
            ],

            "type": 0,
            "id": 4849292,
            "ga_prefix": "070817",
            "title": "饿了 · 完全不关乎厨艺,好做到想笑的冬荫功汤"
        },

]

  "top_stories": [
        {
            "image": "http://pic2.zhimg.com/010646d8235df4bbf959a83069283f25.jpg",
            "type": 0,
            "id": 4849730,
            "ga_prefix": "070813",
            "title": "我是参加这次救火行动的某券商交易员"
        },

]

}

蓝色字体代表两个数组,数组内容大致相同(不同也可以,建实体类的时候取交集),两个数组JSON.parseArray();两次就能得到全部数据

紫色字体代表解析的关键点,既数组内无{}而是""  在解析的时候把他当成{},st变量进行增强for遍历的时候st就是去除[]的URL了  images实体类为List<String> images;

public class JSON两个差不多的解析 {public static void main(String[] args) {String url="http://news-at.zhihu.com/api/4/stories/latest";HttpUtil.getByte(url, new CallBack() {//该回调方法将得到的entity返回 byte[] @Overridepublic void getByte(byte[] b) {try {//解析storiesString strJSON = new String(b,"utf-8");JSONObject obj = new JSONObject(strJSON);String strstories= obj.getString("stories");List<Story> arr = JSON.parseArray(strstories,Story.class);for (Story s : arr) {System.out.println("ID:"+s.getId());System.out.println("标题:"+s.getTitle());List<String> images = s.getImages();for (String st : images) {System.out.println("URL:"+st);}}//解析top_storiesString top_stories = obj.getString("top_stories");arr=JSON.parseArray(top_stories, Story.class);System.out.println("分割线----------------------------------------------------------------");for (Story s : arr) {System.out.println("ID:"+s.getId());System.out.println("标题:"+s.getTitle());System.out.println("图片:"+s.getImage());}} catch (UnsupportedEncodingException e) {e.printStackTrace();} catch (JSONException e) {// TODO Auto-generated catch blocke.printStackTrace();}}});}}
其实通过上面的例子可以看出,fast-json 有相对应的key和value最好,没有对应属性则该实体类无法得到值,属性多余key时为默认值,并且跟类名无关,上面解析的key为stories,而类名为Story。


总结:

1.解析完成的数据存入实体类或者Map集合,没有实体类的时候用Map集合。但fastjson无法完成Map集合

2.原生JSON一层一层解析,虽然麻烦点,但是灵活度相对较高,不依赖实体类。

fastjson解析方便,代码简洁,缺点必须依赖实体类,

3.二者相结合使用很方便。


1 0