JSON解析

原生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() {
			
			@Override
			public 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[] 
			@Override
			public void getByte(byte[] b) {
				try {
					//解析stories
					String 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_stories
					String 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 block
					e.printStackTrace();
				}
			}
		});
	}

}
其实通过上面的例子可以看出,fast-json 有相对应的key和value最好,没有对应属性则该实体类无法得到值,属性多余key时为默认值,并且跟类名无关,上面解析的key为stories,而类名为Story。


总结:

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

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

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

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


你可能感兴趣的:(json,unicode)