android基础---->JSON数据的解析 企

时间:2022-10-16 20:15:48

上篇博客,我们谈到了XML两种常用的解析技术,详细可以参见我的博客(android基础---->XMl数据的解析)。www.xzpxxw.com网络传输另外一种数据格式JSON就是我们今天要讲的,它是比XML体积更小的数据格式,在网络上传输的时候可以更省流量。JSON解析的框架有很多,我们就讲使用JSONObject和Gson两种,好了我们开始Json的讲解。

 

目录导航:

  1.  JSONObject常见的使用
  2.  JSONObject的实现原理
  3.  Gson常见的使用
  4.  JSON的使用实例
  5.  友情链接

 

JSONObject的使用

 一、 JSON对象的使用:

String content = "{'username': 'linux', 'password': '123456'}";
JSONObject jsonObject
= new JSONObject(content);
String username
= jsonObject.getString("username");
String password
= jsonObject.getString("password");

 

二、 JSON数组的使用:

android基础---->JSON数据的解析 企
String jsonContent = "[{'user': '刘力', 'age': 21, 'femal': true}, "
                        + "{'user': 'chen', 'age': 20, 'femal': false}]";
JSONArray jsonArray = new JSONArray(jsonContent);
for (int i = 0; i < jsonArray.length(); i++) {
      JSONObject object = jsonArray.getJSONObject(i);
      System.out.print(object.getString("user") + " ");
      System.out.print(object.getInt("age") + " ");
      System.out.print(object.getBoolean("femal") + " ");
      System.out.println();
}www.xzpxxw.com
android基础---->JSON数据的解析 企

 

三、 JSON数组与JSON对象混合使用

android基础---->JSON数据的解析 企
String jsonString = "[{'user': 'tomhu', 'age': 21, " + "'info': {'adress': 'hubai', 'sex': 'femal'}}, "
+ "{'user': 'chen', 'age': 20, " + "'info': {'adress': 'hunan', 'sex': 'male'}}]";
JSONArray jsonArrays
= new JSONArray(jsonString);
for (int i = 0; i < jsonArrays.length(); i++) {
JSONObject objects
= jsonArrays.getJSONObject(i);
System.out.print(objects.getString(
"user") + " ");
System.out.print(objects.getInt(
"age") + " ");
System.out.print(objects.getJSONObject(
"info").getString("adress") + " ");
System.out.print(objects.getJSONObject(
"info").getString("sex") + " ");
System.out.println();
}
android基础---->JSON数据的解析 企

 

四、 JSON数组中存储对象

android基础---->JSON数据的解析 企
Person person = new Person();
person.setUsername(
"linux" );
person.setPassword(
"123456" );
JSONArray jsonArray
= new JSONArray();
jsonArray.put(
0, person );
jsonArray.put(
1, "I love you" );

// String username = jsonArray.getJSONObject(0).getString("username"); www.xzpxxw.com 错误的写法
Person user = (Person) jsonArray.get(0);
System.out.println(
"username: " + user.getUsername());
android基础---->JSON数据的解析 企

 

JSONObject的原理

JsonObject的存储与取出

一、 JSONObject里面维护了一个LinkedHashMap,当生成一个无参数的JSONObject,实质是初始化了一个Map:

private final LinkedHashMap<String, Object> nameValuePairs;
public JSONObject() {
nameValuePairs
= new LinkedHashMap<String, Object>();
}

 

 二、 当JSONObject增加数据,实质上把数据的键值对方法存放在上述的Map中:

public JSONObject put(String name, boolean value) throws JSONException {
nameValuePairs.put(checkName(name), value);
return this;
}

 

三、 从JSONObject中取出数据,很容易想到的就是从Map取出了:

android基础---->JSON数据的解析 企
public String getString(String name) throws JSONException {
Object object
= get(name); // get()方法就是执行Object result = nameValuePairs.get(name);
String result
= JSON.toString(object);
if (result == null) {
throw JSON.typeMismatch(name, object, "String");
}
return result;
}
android基础---->JSON数据的解析 企

 

JsonObject的解析过程

一、 JsonObject还有一个带参数的构造函数:www.xzpxxw.com常用的是传递一个String类型的参数

public JSONObject(String json) throws JSONException {
this(new JSONTokener(json));
}

 

二、 跟进去,发现主要执行的是JSONTokener的nextValue()方法,在这个方法中主要是对数据进行解析;

android基础---->JSON数据的解析 企
public Object nextValue() throws JSONException {
int c = nextCleanInternal();
switch (c) {
case -1:
throw syntaxError("End of input");

case '{':
return readObject();

case '[':
return readArray();

case '\'':
case '"':
return nextString((char) c);

default:
pos
--;
return readLiteral();
}
}
android基础---->JSON数据的解析 企
  • 在nextCleanInternal方法中,它会从头到尾的逐个字符的解析,对于一些字符做一些处理。例如空格,换行,转义符等!
  • 当解析到[表示开始一个对象的读取,当解析到{表示一个数组的读取

 

三、 在readObject方法中,仍然是调用nextCleanInternal()方法,逐个得到解析的字符,下到解析到}.下面贴出重要代码

android基础---->JSON数据的解析 企
int first = nextCleanInternal(); www.xzpxxw.com // 得到解析的字符
if (first == '}') {
return result;
}
else if (first != -1) {
pos
--;
}
.......
while (true) {
Object name
= nextValue(); // 解析得到键

int separator = nextCleanInternal();
if (separator != ':' && separator != '=') {
throw syntaxError("Expected ':' after " + name);
}
if (pos < in.length() && in.charAt(pos) == '>') {
pos
++;
}

result.put((String) name, nextValue()); // 将解析得到的键值对,存放在map当中

switch (nextCleanInternal()) {
case '}':
return result;
case ';':
case ',':
continue;
default:
throw syntaxError("Unterminated object");
}
}
android基础---->JSON数据的解析 企

 

四、 nextValue方法比较关键,它流转解析的大部分工作!www.xzpxxw.com在nextValue中有一个readLiteral方法,针对一些类型做处理,得到解析之后的结果:

android基础---->JSON数据的解析 企
private Object readLiteral() throws JSONException {
String literal
= nextToInternal("{}[]/\\:,=;# \t\f");

if (literal.length() == 0) {
throw syntaxError("Expected literal value");
}
else if ("null".equalsIgnoreCase(literal)) {
return JSONObject.NULL;
}
else if ("true".equalsIgnoreCase(literal)) {
return Boolean.TRUE;
}
else if ("false".equalsIgnoreCase(literal)) {
return Boolean.FALSE;
}

/* try to parse as an integral type... */
if (literal.indexOf('.') == -1) {
int base = 10;
String number
= literal;
if (number.startsWith("0x") || number.startsWith("0X")) {
number
= number.substring(2);
base
= 16;
}
else if (number.startsWith("0") && number.length() > 1) {
number
= number.substring(1);
base
= 8;
}
try {
long longValue = Long.parseLong(number, base);
if (longValue <= Integer.MAX_VALUE && longValue >= Integer.MIN_VALUE) {
return (int) longValue;
}
else {
return longValue;
}
}
catch (NumberFormatException e) {
/*
* This only happens for integral numbers greater than
* Long.MAX_VALUE, numbers in exponential form (5e-10) and
* unquoted strings. Fall through to try floating point.
*/
}
}

/* ...next try to parse as a floating point... */
try {
return Double.valueOf(literal);
}
catch (NumberFormatException ignored) {
}

/* ... finally give up. We have an unquoted string */
return new String(literal); // a new string avoids leaking memory
}
android基础---->JSON数据的解析 企

 

五、至于JSONArray的解析与JsonObject的解析过程是一样的,它里面维护的是一个List:

android基础---->JSON数据的解析 企
private final List<Object> values;
public
JSONArray(JSONTokener readFrom) throws JSONException { Object object = readFrom.nextValue();
if (object instanceof JSONArray) {
values
= ((JSONArray) object).values;
}
else {
throw JSON.typeMismatch(object, "JSONArray");
}
}
android基础---->JSON数据的解析 企

 

Gson的使用

一、我们在测试当中先加入一个Person类,方便测试:

android基础---->JSON数据的解析 企
package com.tomhu.test;
public class Person { private String name;
private int age;

public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
android基础---->JSON数据的解析 企

 

二、 gson把对象转换成JSON格式

android基础---->JSON数据的解析 企
Gson gson = new Gson();
Person person
= new Person();
person.setName(
"linux");
person.setAge(
23);
String str
= gson.toJson(person);
System.out.println(str);
android基础---->JSON数据的解析 企
  • 打印结果:  {"name":"linux","age":23}

 

三、 gson把json格式解析成对象

String jsonData = "{'name':'刘力','age':19}";
Person person
= gson.fromJson(jsonData, Person.class);
System.out.println(person.getName()
+ ", " + person.getAge());
  • 打印结果: 刘力, 19

 

四、 gson把List对象解析成Json格式:

android基础---->JSON数据的解析 企
Gson gson = new Gson();
List
<Person> persons = new ArrayList<Person>();
for (int i = 0; i < 2; i++) {
Person p
= new Person();
p.setName(
"name" + i);
p.setAge(i
* 5);
persons.add(p);
}
String str
= gson.toJson(persons);
System.out.println(str);
android基础---->JSON数据的解析 企
  • 打印结果: [{"name":"name0","age":0},{"name":"name1","age":5}]

 

五、 gson把Json格式解析成List对象www.xzpxxw.com:

android基础---->JSON数据的解析 企
Gson gson = new Gson();
String str
= "[{'name':'linux','age':10},{'name':'huhx','age':22}]";
List
<Person> ps = gson.fromJson(str, new TypeToken<List<Person>>(){}.getType());
for (int i = 0; i < ps.size(); i++) {
Person person
= ps.get(i);
System.out.print(
"name: " + person.getName() + " age: " + person.getAge());
}
android基础---->JSON数据的解析 企
  • 打印结果:name: linux age: 10 name: huhx age: 22