JSON学习笔记

来源:互联网 发布:面试淘宝美工常见问题 编辑:程序博客网 时间:2024/04/30 04:32

JSON是什么,有什么用?

      跟XML一样,是一种数据的格式规范。
      可以理解成是“XML的简化版”,但与XML无关。

      JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。
      基于JS技术发展起来(因此JS对其有更好的支持),但与语言无关,任何语言都可以解析。

      对比:

  1. XML可读性较高,数据量较大;JSON可读性较低(但比自己随意定义的要好),数据量较小;
  2. 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:scnuyzsubject:c,java,sqlsay: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();         }      }}

      输出:

mkyong29msg 1msg 2msg 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);              //100double d = gson.fromJson("\"99.99\"", double.class);  //99.99boolean b = gson.fromJson("true", boolean.class);     // trueString str = gson.fromJson("String", String.class);   // String

注:不知道你是否注意到了第2、3行有什么不一样没

      基本数据类型的生成

Gson gson = new Gson();String jsonNumber = gson.toJson(100);       // 100String jsonBoolean = gson.toJson(false);    // falseString 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张三12name:李明,age:19name:李明,age:19name:张三,age:12{"name":"李明","age":19}{"name":"张三","age":12}
0 0