9、JSON
刚刚上个博客说的XML一般用于做配置文件 数据传输
但是JSON更适合做数据传输
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。 JSON 官方:http://www.json.org
Notation标记
JSON 数据格式的特点
JSON 建构于两种结构:
1、 “名称/值”对的集合
2.、 值的有序列表(数组)
JSON 表示名称 / 值对的方式 :{ "firstName": "vince", "lastName":"ma", "email": "finally_m@foxmail.com" }
花括号在外面
属性用双引号
然后冒号
后面跟值 字符串用双引号 整数小数不需要双引号直接写
间隔用逗号
一个花括号代表一个对象
表示数组 下面是一个完整的对象,它有个属性user 这个属性的值是个数组
{ "user":
[
{ "firstName": "vince", "lastName":"ma", "email": "finally_m@foxmail.com" },
{ "firstName": "lin", "lastName":"jacks", "email": “jacks@qq.com”}
]
}
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文件
name.json
{"firstName":"Vince","lastName":"Ma","email":"1791705739@qq.com"}
names.json
[
{"firstName":"Vince","lastName":"Ma","email":"1791705739@qq.com"},
{"firstName":"Jason","lastName":"Hunter","email":"jason@google.com"}
]
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结果
看你解析的文件 如果第一个是中括号 代表数组 需要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;
}
}
结果
二 生成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","1791705739@qq.com"));
list.add(new Name("jack","wang","jack@qq.com"));
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());
}
}
结果
下面是极简工具的介绍 就跟上个博客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对象
很简单吧 以后简单的使用这个就可以
但复杂的 想跳过不想解析的 想过滤的 就用上面的办法
生成Json对象 就两句话搞定
示例 使用Gson处理数组
把一组JSON对象转换成一个JAVA对象集合,或者把一个JAVA对象集合转换成JSON数组
使用上面的names
有个注意的地方
使用gson.fromJson()时 我们要告诉它我们要转换成什么类型(因为我们不是一个对象 要转成数组类型)
使用这个标记TypeToken
TypeToken<List<Name>> typeToken = new TypeToken<List<Name>>(){};
为什么new一个子类(实现类)呢(就是花括号 虽然什么都没实现)目的就是指定一下这个类的泛型
因为泛型就在类定义的时候才能指定
这句话就好比 我自己写了个类 指定了这个类的类型
指定TypeToken的类型为List类型
List list = gson.fromJson(in, typeToken.getType());
也就是说
当你要给定类型的时候 必须要用TypeToken来进行指定 因为你不指定它不知道你要生成啥类型
结果
同样的转成Json也很简单 也要传类型