对于程序员来说,大多数都是解析JSON数据,但是创建JSON数据也是很有必要了解一下的。
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); } }打印结果:
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","");,
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,是""。
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); } }
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.二者相结合使用很方便。