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_第1张图片
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_第2张图片

看你解析的文件 如果第一个是中括号 代表数组 需要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_第3张图片


二 生成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_第4张图片


下面是极简工具的介绍 就跟上个博客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_第5张图片
在这里插入图片描述
很简单吧 以后简单的使用这个就可以
但复杂的 想跳过不想解析的 想过滤的 就用上面的办法

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

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


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

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


使用这个标记TypeToken

 TypeToken> typeToken = new TypeToken>(){};

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

这句话就好比 我自己写了个类 指定了这个类的类型
在这里插入图片描述

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


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

你可能感兴趣的:(Java)