Java基础之JsonReader解析Json数组 196 JsonReader解析复杂Json文件 197 生成JSON数据与GSON工具的使用 198

9、JSON

刚刚上个博客说的XML一般用于做配置文件 数据传输
但是JSON更适合做数据传输

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。 JSON 官方:http://www.json.org
Notation标记

JSON 数据格式的特点
JSON 建构于两种结构:
1、 “名称/值”对的集合
2.、 值的有序列表(数组)

JSON 表示名称 / 值对的方式 :{ "firstName": "vince", "lastName":"ma", "email": "[email protected]" }
花括号在外面
属性用双引号
然后冒号
后面跟值 字符串用双引号 整数小数不需要双引号直接写
间隔用逗号
一个花括号代表一个对象

表示数组 下面是一个完整的对象,它有个属性user 这个属性的值是个数组

{ "user": 
	[
	 { "firstName": "vince", "lastName":"ma", "email": "[email protected]" }, 
	 { "firstName": "lin", "lastName":"jacks", "email": “[email protected]”}
 ]
} 

10、GSON组件的使用

GSON是Google开发的Java API,用于转换Java对象和Json对象。

下载地址:http://www.mvnrepository.com/artifact/com.google.code.gson/gson

解析JSON:JsonReader reader = new JsonReader(new StringReader(jsonData));
生成JSON:
private String createJSON(ArrayList<User> users) {
        JSONObject jsonObject = new JSONObject();JSONArray array = new JSONArray();
        int size = users.size();
        try {for (int i = 0; i < size; i++) {
                User user = users.get(i); JSONObject object = new JSONObject();
                object.put("name", user.name);object.put("age", user.age);array.put(object);}
            jsonObject.put("users",array);
            return jsonObject.toString();
        } catch (JSONException e) {e.printStackTrace();}
        return null;
    }
static class User {String name; int age;//…}

下面是极简工具的介绍 就跟上个博客XML使用的xstream组件似的

  • 使用 Gson 直接把 JSON 数据转换成 Java 对象
public Student parserJSON2(String data){

	Gson gson = new Gson();

	Student s = gson.fromJson(data, Student.class); 
	return s; 
} 
  • 使用 Gson 直接把 JSON 数组转换成 Java 对象
public List<Student> parserJSON3(String data){

	Type type = new TypeToken<ArrayList<Student>>(){}.getType(); 
	Gson gson = new Gson();
	List<Student> list = gson.fromJson(data, type);
	return list; 
} 

11、XML与JSON的比较

从以下6点比较JSON与XML:

  • 1、JSON和XML的数据可读性基本相同
  • 2、JSON和XML同样拥有丰富的解析手段
  • 3、JSON相对于XML来讲,数据的体积小
  • 4、JSON与JavaScript的交互更加方便
  • 5、JSON对数据的描述性比XML较差
  • 6、JSON的速度要远远快于XML

适合的场景:

  • (1)数据传输:JSON要比XML更有优势
  • (2)存储数据:XML描述性更强
  • (3)XML通常用做配置文件(WEB课程中会有详细介绍)

代码示例

一 解析JSON

1.先准备几个JSON文件
Java基础之JsonReader解析Json数组 196 JsonReader解析复杂Json文件 197 生成JSON数据与GSON工具的使用 198
name.json

{"firstName":"Vince","lastName":"Ma","email":"[email protected]"}

names.json

[
  {"firstName":"Vince","lastName":"Ma","email":"[email protected]"},
  {"firstName":"Jason","lastName":"Hunter","email":"[email protected]"}
]

2.然后需要一个对象类name

package com.vince.json;

/**
 * Created by vince on 2017/7/1.
 */
public class Name {
    private String firstName;
    private String lastName;
    private String email;

    @Override
    public String toString() {
        return "Name{" +
                "firstName='" + firstName + '\'' +
                ", lastName='" + lastName + '\'' +
                ", email='" + email + '\'' +
                '}';
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Name() {
    }

    public Name(String firstName, String lastName, String email) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
    }
}

3.然后我们解析这个json文件
JSONDemo

package com.vince.json;

import com.google.gson.stream.JsonReader;
import org.junit.Test;

import javax.print.attribute.standard.MediaSize;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;

/**
 * Created by vince on 2017/7/1.
 */
public class JSONDemo {


    /**
     * 解析一个JSON数组
     */
    @Test
    public void parseJSONNames(){
        InputStream is = Thread.currentThread().getContextClassLoader()
                .getResourceAsStream("com/vince/json/names.json");
        InputStreamReader in = new InputStreamReader(is);
        //JSON的解析工具(解析器)
        JsonReader reader = new JsonReader(in);
        ArrayList<Name> list = new ArrayList<>();
        try {
            //开始解析数组
            reader.beginArray();
            while(reader.hasNext()){
                list.add(parseName(reader));
            }
            //结束解析数组
            reader.endArray();
        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println(Arrays.toString(list.toArray()));
    }
    //解析对象 Name
    private Name parseName(JsonReader jsonReader){
        Name name = null;
        try {
            //开始解析对象
            jsonReader.beginObject();
            name = new Name();
            while (jsonReader.hasNext()){
                String attrName = jsonReader.nextName();
                if("firstName".equals(attrName)){
                    name.setFirstName(jsonReader.nextString());
                }else if("lastName".equals(attrName)){
                    name.setLastName(jsonReader.nextString());
                }else if("email".equals(attrName)){
                    name.setEmail(jsonReader.nextString());
                }
            }

            //结束解析对象
            jsonReader.endObject();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return name;
    }
}

一 解析简单的Json文件 names.json结果
Java基础之JsonReader解析Json数组 196 JsonReader解析复杂Json文件 197 生成JSON数据与GSON工具的使用 198

看你解析的文件 如果第一个是中括号 代表数组 需要begin.Arrays
如果是花括号 代表对象 需要begin.Object
然后继续解析 往后走看里面的括号

一直操作的都是JsonReader这个对象 一直在next 指针指向下一个继续操作


解析复杂的json文件

首先准备一个json文件
message.json

[
  {
    "id": 912345678901,
    "text": "How do I read a JSON stream in Java?",
    "geo": null,
    "user": {
      "name": "json_newb",
      "followers_count": 41
    }
  },
  {
    "id": 912345678902,
    "text": "@json_newb just use JsonReader!",
    "geo": [50.454722, -104.606667],
    "user": {
      "name": "jesse",
      "followers_count": 2
    }
  }
]

然后写bean类
Message类

package com.vince.json;

import java.util.ArrayList;

/**
 * Created by vince on 2017/7/1.
 */
public class Message {
    private long id;
    private String text;
    private ArrayList<Double> geo;
    private User user;

    public Message() {
    }

    public Message(long id, String text, ArrayList<Double> geo, User user) {
        this.id = id;
        this.text = text;
        this.geo = geo;
        this.user = user;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    public ArrayList<Double> getGeo() {
        return geo;
    }

    public void setGeo(ArrayList<Double> geo) {
        this.geo = geo;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    @Override
    public String toString() {
        return "Message{" +
                "id=" + id +
                ", text='" + text + '\'' +
                ", geo=" + geo +
                ", user=" + user +
                '}';
    }
}

User类
Message对象里面包含User对象

package com.vince.json;

/**
 * Created by vince on 2017/7/1.
 */
public class User {
    private String name;
    private int followers_count;

    public User() {
    }

    public User(String name, int followers_count) {
        this.name = name;
        this.followers_count = followers_count;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getFollowers_count() {
        return followers_count;
    }

    public void setFollowers_count(int followers_count) {
        this.followers_count = followers_count;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", followers_count=" + followers_count +
                '}';
    }
}

解析类

package com.vince.json;

import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;

/**
 * Created by vince on 2017/7/1.
 */
public class JsonDemo2 {

    /**
     * 使用JsonReader解析复杂的JSON数据
     */
    @Test
    public void parseJSONMessages(){

        InputStream is = Thread.currentThread().getContextClassLoader()
                .getResourceAsStream("com/vince/json/message.json");
        InputStreamReader in = new InputStreamReader(is);
        JsonReader jsonReader = new JsonReader(in);
        ArrayList<Message> list = readMessageArray(jsonReader);
        for (Message m: list){
            System.out.println(m);
        }

    }

    //读取Message数组
    private ArrayList<Message> readMessageArray(JsonReader jsonReader) {
        ArrayList<Message> list = new ArrayList<>();
        try {
            jsonReader.beginArray();
            while(jsonReader.hasNext()){
                list.add(readMessage(jsonReader));
            }
            jsonReader.endArray();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return list;
    }

    //解析一个Message对象
    private Message readMessage(JsonReader jsonReader) {
        Message m = new Message();
        try {
            jsonReader.beginObject();
            while (jsonReader.hasNext()){
                String name = jsonReader.nextName();
                if("id".equals(name)){
                    m.setId(jsonReader.nextLong());
                }else if("text".equals(name)){
                    m.setText(jsonReader.nextString());
                    //peek 意思是取这个值看一下 返回的是一个标记类型 标记这个值为空 或者为数字 或者为字符串等等类型
                    //因为geo有空的 所以这里用peek判断一下  
                }else if("geo".equals(name) && jsonReader.peek()!= JsonToken.NULL){
                    m.setGeo(readGeo(jsonReader));
                }else if("user".equals(name)){
                    m.setUser(readUser(jsonReader));
                }else{
                	//处理null的情况 跳过这个值
                    jsonReader.skipValue();
                }
            }
            jsonReader.endObject();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return m;
    }

    /**
     * 解析User对象
     * @param jsonReader
     * @return
     */
    private User readUser(JsonReader jsonReader) {
        User user = new User();
        try {
            jsonReader.beginObject();
            while (jsonReader.hasNext()){
                String name = jsonReader.nextName();
                if("name".equals(name)){
                    user.setName(jsonReader.nextString());
                }else if("followers_count".equals(name)){
                    user.setFollowers_count(jsonReader.nextInt());
                }else{
                    jsonReader.skipValue();
                }
            }
            jsonReader.endObject();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return user;
    }

    /**
     * 解析GEO
     * @param jsonReader
     * @return
     */
    private ArrayList<Double> readGeo(JsonReader jsonReader) {

        ArrayList<Double> list = new ArrayList<>();
        try {
            jsonReader.beginArray();
            while (jsonReader.hasNext()){
                list.add(jsonReader.nextDouble());
            }
            jsonReader.endArray();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return list;
    }
}

结果
Java基础之JsonReader解析Json数组 196 JsonReader解析复杂Json文件 197 生成JSON数据与GSON工具的使用 198


二 生成JSON

先是使用了最上面的实体类Name

package com.vince.json;

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonToken;
import org.junit.Test;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by vince on 2017/7/1.
 */
public class JsonDemo3 {

    /**
     * 把一组JSON对象转换成一个JAVA对象集合,或者把一个JAVA对象集合转换成JSON数组
     */
    @Test
    public void gson2(){
        Gson gson = new Gson();
        InputStream is = Thread.currentThread().getContextClassLoader()
                .getResourceAsStream("com/vince/json/names.json");
        InputStreamReader in = new InputStreamReader(is);
        TypeToken<List<Name>> typeToken = new TypeToken<List<Name>>(){};
        List<Name> list = gson.fromJson(in, typeToken.getType());
        System.out.println(list);


        String json = gson.toJson(list, typeToken.getType());
        System.out.println(json);
    }

    class MyTypeToken extends TypeToken<List<Name>>{}

    /**
     * 把一个JSON对象转换成JAVA对象,或把一个JAVA对象转换成JSON对象
     */
    @Test
    public void gson1(){
        Gson gson = new Gson();
        InputStream is = Thread.currentThread().getContextClassLoader()
                .getResourceAsStream("com/vince/json/name.json");
        InputStreamReader in = new InputStreamReader(is);
        Name name = gson.fromJson(in, Name.class);
        System.out.println(name);

        String json = gson.toJson(name);
        System.out.println(json);
    }

    @Test
    public void createJSON(){
        List<Name> list = new ArrayList<>();
        list.add(new Name("vince","ma","[email protected]"));
        list.add(new Name("jack","wang","[email protected]"));
        JsonArray array = new JsonArray();
        for (Name n: list){
            JsonObject obj = new JsonObject();
            obj.addProperty("firstName",n.getFirstName());
            obj.addProperty("lastName",n.getLastName());
            obj.addProperty("email",n.getEmail());
            array.add(obj);
        }
        System.out.println(array.toString());
    }
}

结果Java基础之JsonReader解析Json数组 196 JsonReader解析复杂Json文件 197 生成JSON数据与GSON工具的使用 198


下面是极简工具的介绍 就跟上个博客XML使用的xstream组件似的

  • 使用 Gson 直接把 JSON 数据转换成 Java 对象
public Student parserJSON2(String data){

	Gson gson = new Gson();

	Student s = gson.fromJson(data, Student.class); 
	return s; 
} 
  • 使用 Gson 直接把 JSON 数组转换成 Java 对象
public List<Student> parserJSON3(String data){

	Type type = new TypeToken<ArrayList<Student>>(){}.getType(); 
	Gson gson = new Gson();
	List<Student> list = gson.fromJson(data, type);
	return list; 
} 

示例 一个对象的处理方式
把一个JSON对象转换成JAVA对象,或把一个JAVA对象转换成JSON对象
使用上面的name.json文件 生成一个Name对象
Java基础之JsonReader解析Json数组 196 JsonReader解析复杂Json文件 197 生成JSON数据与GSON工具的使用 198
Java基础之JsonReader解析Json数组 196 JsonReader解析复杂Json文件 197 生成JSON数据与GSON工具的使用 198
很简单吧 以后简单的使用这个就可以
但复杂的 想跳过不想解析的 想过滤的 就用上面的办法

生成Json对象 就两句话搞定Java基础之JsonReader解析Json数组 196 JsonReader解析复杂Json文件 197 生成JSON数据与GSON工具的使用 198

Java基础之JsonReader解析Json数组 196 JsonReader解析复杂Json文件 197 生成JSON数据与GSON工具的使用 198


示例 使用Gson处理数组
把一组JSON对象转换成一个JAVA对象集合,或者把一个JAVA对象集合转换成JSON数组
使用上面的names
有个注意的地方
使用gson.fromJson()时 我们要告诉它我们要转换成什么类型(因为我们不是一个对象 要转成数组类型)

Java基础之JsonReader解析Json数组 196 JsonReader解析复杂Json文件 197 生成JSON数据与GSON工具的使用 198
Java基础之JsonReader解析Json数组 196 JsonReader解析复杂Json文件 197 生成JSON数据与GSON工具的使用 198


使用这个标记TypeToken

 TypeToken<List<Name>> typeToken = new TypeToken<List<Name>>(){};

为什么new一个子类(实现类)呢(就是花括号 虽然什么都没实现)目的就是指定一下这个类的泛型
因为泛型就在类定义的时候才能指定

这句话就好比 我自己写了个类 指定了这个类的类型
Java基础之JsonReader解析Json数组 196 JsonReader解析复杂Json文件 197 生成JSON数据与GSON工具的使用 198

指定TypeToken的类型为List类型
List list = gson.fromJson(in, typeToken.getType());
也就是说
当你要给定类型的时候 必须要用TypeToken来进行指定 因为你不指定它不知道你要生成啥类型


结果
Java基础之JsonReader解析Json数组 196 JsonReader解析复杂Json文件 197 生成JSON数据与GSON工具的使用 198
同样的转成Json也很简单 也要传类型
Java基础之JsonReader解析Json数组 196 JsonReader解析复杂Json文件 197 生成JSON数据与GSON工具的使用 198