JSON是什么,有什么用?
跟XML一样,是一种数据的格式规范。
可以理解成是“XML的简化版”,但与XML无关。
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。
基于JS技术发展起来(因此JS对其有更好的支持),但与语言无关,任何语言都可以解析。
对比:
- XML可读性较高,数据量较大;JSON可读性较低(但比自己随意定义的要好),数据量较小;
- XML应用主要有3点;JSON主要用于数据交换(存储也可应用,较少);XML应用、发展更广;
JSON如何定义?
表示“键值对”/对象
最简单的形式:
{"firstName":"Brett"}
这个示例非常简单,而且实际上比等效的传统的“键值对”占用更多的空间:
firstName=Brett
当将多个“键值对”串在一起时,JSON就会体现出它的价值了。
{"firstName":"Brett","lastName":"McLaughlin","email":"aaaa"}
这样,可以明确地表示以上三个值都是同一记录的一部分(一个对象),花括号使这些值有了某种联系。
表示“数组”
{"people":[
{"firstName":"Brett","lastName":"McLaughlin","email":"aaaa"},
{"firstName":"Jason","lastName":"Hunter","email":"bbbb"},
{"firstName":"Elliotte","lastName":"Harold","email":"cccc"}
]
}
或者:
{"programmers":[
{"firstName":"Brett","lastName":"McLaughlin","email":"aaaa"},
{"firstName":"Jason","lastName":"Hunter","email":"bbbb"},
{"firstName":"Elliotte","lastName":"Harold","email":"cccc"}
],
"authors":[
{"firstName":"Isaac","lastName":"Asimov","genre":"science fiction"},
{"firstName":"Tad","lastName":"Williams","genre":"fantasy"},
{"firstName":"Frank","lastName":"Peretti","genre":"christian fiction"}
],
"musicians":[
{"firstName":"Eric","lastName":"Clapton","instrument":"guitar"},
{"firstName":"Sergei","lastName":"Rachmaninoff","instrument":"piano"}
]}
更多格式规范参考 “JSON格式规范.txt” 。
如想校验JSON格式是否正确,可参考 http://www.bejson.com。
如何应用?
JS对JSON数据的操作
JSON是JavaScript原生格式,可以直接应用。
也可使用json.js或jQuery.js这些组件去操作。
Java对JSON数据的操作
使用行业组件Jackson。
JSON格式规范
{"name": "Michael"}
{} 对象
[] 数组
"" 双引号内是属性或值
: 冒号表示后者是前者的值
[{"name": "Michael"},{"name": "Jerry"}]
也可表达成:{"name":["Michael","Jerry"]}
=================================================================================
{"sub_int":"a"} true
{"sub_int":a} false
{"sub_int":100} true,对象
[{"sub_int":100}] true,数组
{123:100} false,属性必须有双引号
{"123":100} true
{"sub_int":123.12} true
{"sub_int":true} true
{"sub_int":null} true
{'sub_int':'a'} false,不能用单引号
JSON 语法是 JavaScript 对象表示法语法的子集。
- 数据在名称/值对中:如 “firstName” : “John”
- 数据由逗号分隔
- 花括号保存对象
- 方括号保存数组
而组成JSON的值可以为以下几种:
- 数字(整数或浮点数)
- 字符串(在双引号中)
- 逻辑值(true 或 false)
- 数组(在方括号中)
- 对象(在花括号中)
- null
传统的JSON解析
最传统的JSON解析莫过于直接使用java中的方法,它通过原生的JSONObject和JSONArray来解析json数据,下面我们就来解析这段json数据吧!json数据如下:
{
"personData": [
{
"age": 12,
"name": "nate",
"schoolInfo": [
{
"School_name": "清华"
},
{
"School_name": "北大"
}
],
"url": "http://pic.yesky.com/uploadImages/2014/345/36/E8C039MU0180.jpg"
},
{
"age": 24,
"name": "jack",
···
}
],
"result": 1
}
分析这段json数据,
•第一层是一个花括号括号,即jsonObect对象,然后这个对象里面有一个personData的JSONArray数组,以及一个result属性
•第二层personData的JSONArray数组,它里面除了属性之外,还有一个schoolInfo的JSONArray数组
•第三次是schoolInfo的JSONArray数组里面的JSONObject对象
这时我们已经将这段数据分析好了,接下来就是写解析方法解析了。
代码如下:
/**
* 从网络中获取JSON字符串,然后解析
* @param json
* @return
*/
private List<Person> jsonParse(String json) {
try {
List<Person> personlist = new ArrayList<Person>();
JSONObject jsonObject = new JSONObject(json);
int result = jsonObject.getInt("result");
if (result == 1) {
JSONArray jsonArray = jsonObject.getJSONArray("personData");
for (int i = 0; i < jsonArray.length(); i++) {
Person person = new Person();
JSONObject personData = jsonArray.getJSONObject(i);
int age = personData.getInt("age");
String url = personData.getString("url");
String name = personData.getString("name");
···
JSONArray schoolInfoArray = personData.getJSONArray("schoolInfo");
for (int j = 0; j < schoolInfoArray.length(); j++) {
JSONObject schoolInfojson = schoolInfoArray.getJSONObject(j);
String schoolName = schoolInfojson.getString("School_name");
···
}
···
}
return personlist;
} else {
Toast.makeText(context, "erro", Toast.LENGTH_SHORT).show();
}
} catch (JSONException e) {
e.printStackTrace();
Log.e("JsonParseActivity", "json解析出现了问题");
}
return null;
}
首先是一个大括号,我们直接从传过来的json字符串创建出来的jsonObject就行了,然后就可以通过它获取result参数,代码如下:
JSONObject jsonObject = new JSONObject(json);
int result = jsonObject.getInt("result");
然后就是解析personData这个json数组,我们直接通过数组名称获取,代码如下:
JSONArray jsonArray = jsonObject.getJSONArray("personData");
再接着就是解析这个数组,解析数组都是用循环解析的,然后这个数组里面先是一个花括号,这又是一个jsonObject对象,代码如下:
JSONArray jsonArray = jsonObject.getJSONArray("personData");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject personData = jsonArray.getJSONObject(i);
int age = personData.getInt("age");
String url = personData.getString("url");
String name = personData.getString("name");
···
}
在personData这个JSONObject对象中,又有一个schoolInfo的JSONArray数组,我们继续按照上述方法获得JSONArray,然后通过for循环获得里面的JSONObject,这时已达到最底层,我们就可以直接获取School_name属性的值了,代码如下:
for (int j = 0; j < schoolInfoArray.length(); j++) {
JSONObject schoolInfojson = schoolInfoArray.getJSONObject(j);
String schoolName = schoolInfojson.getString("School_name");
···
}
这样,一个完整的JSON数据就解析好了!
当然,这只是解析一个简单的JSON数据的方法,但是遇到复杂的json数据也可以如此解析,首先是分析JSON数据,然后就是正式解析json。
课后习题:在项目中的res-raw文件夹下,有newjson.txt的json数据,大家可以使用这个来联系一下json解析。当然啦,这个json数据的传统解析方式也在项目里面写好了,如果不懂也可以参考一下!
再举一个例子
解析如下json
{
"name": "scnuyz",
"subject": [
"c",
"java",
"sql"
],
"msg": {
"say": "hello"
}
}
import java.io.IOException;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public class Demo2 {
public static void main(String[] args) throws IOException {
String content = "{\"name\": \"scnuyz\",\"subject\": [\"c\",\"java\",\"sql\"],\"msg\":{\"say\":\"hello\"}}";
try {
JSONObject jsonObject = new JSONObject(content);
String name = jsonObject.getString("name");
JSONArray jsonArray = jsonObject.getJSONArray("subject");
String s1 = (String)jsonArray.get(0);
String s2 = (String)jsonArray.get(1);
String s3 = (String)jsonArray.get(2);
JSONObject aaaJsonObject = jsonObject.getJSONObject("msg");
String say = aaaJsonObject.getString("say");
System.out.println("json:"+content);
System.out.println("name:"+name);
System.out.println("subject:"+s1+","+s2+","+s3);
System.out.println("say:"+say);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
输出:
json:{"name": "scnuyz","subject": ["c","java","sql"],"msg":{"say":"hello"}}
name:scnuyz
subject:c,java,sql
say:hello
JACKSON案例
Jackson提供了三种可选的Json处理方法:
流式API(Streaming API) 、树模型(Tree Model)、数据绑定(Data Binding)。
从使用角度来看,比较一下这三种处理Json的方式的特性:
- Streaming API:是效率最高的处理方式(开销低、读写速度快,但程序编写复杂度高)
- Tree Model:是最灵活的处理方式
- Data Binding:是最常用的处理方式
JACKSON中写一个json文件使用的是JsonGenerator类
package com.jackson;
import java.io.File;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonMappingException;
public class Demo {
public static void main(String[] args) {
try {
JsonFactory jfactory = new JsonFactory();
/*** write to file ***/
JsonGenerator jGenerator = jfactory.createJsonGenerator(new File("c:\\user.json"), JsonEncoding.UTF8);
jGenerator.writeStartObject(); // {
jGenerator.writeStringField("name", "mkyong"); // "name" : "mkyong"
jGenerator.writeNumberField("age", 29); // "age" : 29
jGenerator.writeFieldName("messages"); // "messages" :
jGenerator.writeStartArray(); // [
jGenerator.writeString("msg 1"); // "msg 1"
jGenerator.writeString("msg 2"); // "msg 2"
jGenerator.writeString("msg 3"); // "msg 3"
jGenerator.writeEndArray(); // ]
jGenerator.writeEndObject(); // }
jGenerator.close();
} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
输出为:
{
"name":"mkyong",
"age":29,
"messages":["msg 1","msg 2","msg 3"]
}
解析JSON
package com.jackson;
import java.io.File;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.JsonMappingException;
public class ParseJSON {
public static void main(String[] args) {
try {
JsonFactory jfactory = new JsonFactory();
/*** read from file ***/
JsonParser jParser = jfactory.createJsonParser(new File("c:\\user.json"));
// loop until token equal to "}"
while (jParser.nextToken() != JsonToken.END_OBJECT) {
String fieldname = jParser.getCurrentName();
if ("name".equals(fieldname)) {
//当前结点为name
jParser.nextToken();
System.out.println(jParser.getText()); // 输出 mkyong
}
if ("age".equals(fieldname)) {
// 当前结点为age
// move to next, which is "name"'s value
jParser.nextToken();
System.out.println(jParser.getIntValue()); // display 29
}
if ("messages".equals(fieldname)) {
jParser.nextToken();
while (jParser.nextToken() != JsonToken.END_ARRAY) {
// display msg1, msg2, msg3
System.out.println(jParser.getText());
}
}
}
jParser.close();
} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
输出:
mkyong
29
msg 1
msg 2
msg 3
GSON解析
Gson 是 Google 提供的用来在 Java 对象和 JSON 数据之间进行映射的 Java 类库。可以将一个 JSON 字符串转成一个 Java 对象,或者反过来。
这是关于GSON的介绍,相对于传统的json解析,使用GSON能够极大的简化了解析流程。
那么该如何使用GSON解析json数据呢?在这里分为以下几步:
1、在eclipse环境下,将gson的jar包复制到libs中,因为这是Google提供的java类库,是不存在java自带的类库中的。
2、获取json数据,并且分析。
3、写出json数据对应的bean类
4、使用gson解析
Gson的基本用法
Gson提供了fromJson() 和toJson() 两个直接用于解析和生成的方法,前者实现反序列化,后者实现了序列化。同时每个方法都提供了重载方法,我常用的总共有5个。
基本数据类型的解析
Gson gson = new Gson();
int i = gson.fromJson("100", int.class); //100
double d = gson.fromJson("\"99.99\"", double.class); //99.99
boolean b = gson.fromJson("true", boolean.class); // true
String str = gson.fromJson("String", String.class); // String
注:不知道你是否注意到了第2、3行有什么不一样没
基本数据类型的生成
Gson gson = new Gson();
String jsonNumber = gson.toJson(100); // 100
String jsonBoolean = gson.toJson(false); // false
String jsonString = gson.toJson("String"); //"String"
POJO类的生成与解析
public class User {
//省略其它
public String name;
public int age;
public String emailAddress;
}
生成JSON:
Gson gson = new Gson();
User user = new User("怪盗kidou",24);
String jsonObject = gson.toJson(user); // {"name":"怪盗kidou","age":24}
解析JSON:
Gson gson = new Gson();
String jsonString = "{\"name\":\"怪盗kidou\",\"age\":24}";
User user = gson.fromJson(jsonString, User.class);
例子:
import com.google.gson.Gson;
public class GsonDemo {
public static String content = "{\"name\": \"scnuyz\",\"subject\": [\"c\",\"java\",\"sql\"]}";
public static void main(String[] args) {
Gson gson = new Gson();
Student student = gson.fromJson(content, Student.class);
String name = student.name;
System.out.println("content:\n"+content);
System.out.println("name:"+name);
String subject[] = student.subject;
for(int i=0;i<subject.length;i++){
System.out.println("第"+(i+1)+"个subject:"+subject[i]);
}
Student student2 = new Student();
student2.setName("zyz");
student2.setSubject(new String[]{"a","b","c"});
String jsonObject = gson.toJson(student2);
System.out.println("stu2:\n"+jsonObject);
}
}
public class Student {
public String name ;
public String[] subject;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String[] getSubject() {
return subject;
}
public void setSubject(String[] subject) {
this.subject = subject;
}
}
FastJSON案例
package com.test;
public class TestPerson {
private int age;
private String name;
public TestPerson(){
}
public TestPerson(int age,String name){
this.age=age;
this.name=name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.test;
import java.util.*;
import com.alibaba.fastjson.*;
public final class TestFastJson {
public static void main(String[] args) {
// TODO Auto-generated method stub
TestPerson json = new TestPerson(19,"李明");
List<TestPerson> list = new ArrayList<TestPerson>();
list.add(json);
list.add(new TestPerson(12,"张三"));
//将集合或者对象序例化成JSON
System.out.println(JSON.toJSON(json));
System.out.println( JSON.toJSON(list) );
//Json串反序列化成对象
TestPerson person = JSON.parseObject("{\"name\":\"李明\",\"age\":19}", TestPerson.class);
System.out.printf("name:%s,age:%d\n",person.getName(),person.getAge());
String str = "[{\"name\":\"李明\",\"age\":19},{\"name\":\"张三\",\"age\":12}]";
//数组对象反序列化成集合
List<TestPerson> listPerson = JSON.parseArray(str,TestPerson.class);
for(TestPerson item : listPerson){
System.out.println( item.getName() );
System.out.println( item.getAge());
}
//没有对象直接解析JSON对象
JSONObject jobj = JSON.parseObject("{\"name\":\"李明\",\"age\":19}");
System.out.printf("name:%s,age:%d\n",jobj.getString("name"),jobj.getBigInteger("age"));
//没有对象直接解析JSON数组
JSONArray jarr = JSON.parseArray("[{\"name\":\"李明\",\"age\":19},{\"name\":\"张三\",\"age\":12}]");
for(int i=0,len=jarr.size();i<len;i++){
JSONObject temp= jarr.getJSONObject(i);
System.out.printf("name:%s,age:%d\n",temp.getString("name"),temp.getBigInteger("age"));
}
for(Object obj:jarr){
System.out.println(obj.toString());
}
}
}
输出:
{"name":"李明","age":19}
[{"name":"李明","age":19},{"name":"张三","age":12}]
name:李明,age:19
李明
19
张三
12
name:李明,age:19
name:李明,age:19
name:张三,age:12
{"name":"李明","age":19}
{"name":"张三","age":12}