作为初学者,尚未就业,就不去如何如何分析JSON怎么怎么样了,个人的理解都在代码里
写得不好,见谅,并恳求给出你宝贵的意见或更好的方法!
1.首先用到的JSON文件:book.json(豆瓣api摘抄的)
{
"isbn":"7505715666",
"title":"小王子",
"author":["(法)圣埃克苏佩里"],
"translator":["胡雨苏"],
"pubdate":"2000-9-1",
"tags":[
{"count":2416,"name":"小王子"},
{"count":1914,"name":"童话"},
{"count":1185,"name":"圣埃克苏佩里"},
{"count":863,"name":"法国"},
{"count":647,"name":"经典"},
],
"series": {"id": "2065", "title": "新史学&多元对话系列"},
"ebook_price": "12.00"
}
2.对应的实体类:
Book(序列化貌似不需要,没用上,能力不够啊,等网络传输时使用)
package pojo;
import java.io.Serializable;
public class Book implements Serializable {
// 作用:序列化时为了保持版本的兼容性,即在版本升级时反序列化仍保持对象的唯一性
// 如果你的类Serialized存到硬盘上面后,可是后来你却更改了类别的field(增加或减少或改名)
// 当你Deserialize时,就会出现Exception的,这样就会造成不兼容性的问题
private static final long serialVersionUID = 1L;
private String isbn; // ISBN
private String title; // 书名
private String author; // 作者
private String translator; // 翻译
private String pubdate; // 出版时间
private String tags; // 标签,因为一本书有多个标签,标签又有属性
private String series; // 系列
private String price; // 价格
public String getIsbn() {
return isbn;
}
public void setIsbn(String isbn) {
this.isbn = isbn;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getTranslator() {
return translator;
}
public void setTranslator(String translator) {
this.translator = translator;
}
public String getPubdate() {
return pubdate;
}
public void setPubdate(String pubdate) {
this.pubdate = pubdate;
}
public String getTags() {
return tags;
}
public void setTags(String tags) {
this.tags = tags;
}
public String getSeries() {
return series;
}
public void setSeries(String series) {
this.series = series;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
}
3.
MainActivity类(两个按钮,一个生成json,一个解析json,一个TextView用来显示解析出来的结果,ScrollView...)
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import pojo.Book;
import JsonMethod;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity implements OnClickListener {
private Button mReadJson, mWriteJson;
private TextView textView;
private JsonMethod json;
private Book book;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
json = new JsonMethod();
}
private void initView() {
mReadJson = (Button) findViewById(R.id.read_json);
mWriteJson = (Button) findViewById(R.id.write_json);
textView = (TextView) findViewById(R.id.textView);
mReadJson.setOnClickListener(this);
mWriteJson.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.read_json:
readJson();
break;
case R.id.write_json:
writeJson();
break;
}
}
private void readJson() {
InputStream is = null;
try {
is = getAssets().open("book.json");
InputStreamReader isr = new InputStreamReader(is);
BufferedReader reader = new BufferedReader(isr);
StringBuilder builder = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
builder.append(line);
}
book = json.parseJson(builder.toString());
textView.append("解析JSON:\n" + "isbn:" + book.getIsbn()
+ "\n title:" + book.getTitle() + "\n author:"
+ book.getAuthor() + "\n translator:"
+ book.getTranslator() + "\n pubdate:" + book.getPubdate()
+ "\n tags:" + book.getTags() + "\n series:"
+ book.getSeries() + "\n ebook_price:" + book.getPrice());
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void writeJson() {
if (book != null) {
try {
String content = json.serializeJson(book);
writeToFile(content);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/*
* 将获得的json格式的字符串写入json文件中
*/
public void writeToFile(String content) {
try {
FileOutputStream fos = openFileOutput("book.json", MODE_PRIVATE);
fos.write(content.getBytes());
Toast.makeText(MainActivity.this, "生成JSON数据文件成功",
Toast.LENGTH_SHORT).show();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
主要的类,
JsonMethod:提供解析和生成JSON的方法
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import pojo.Book;
public class JsonMethod {
private Book book;
private static final String SPLIT = " ";
// 用于解析对象数组时对象属性之间分隔,例如[{"id":1},{"id":2}]分隔为id-1 id-2
private static final String PROSPLIT = "-";
/*
* 解析JSON
*/
public Book parseJson(String content) throws Exception {
book = new Book();
JSONObject root = new JSONObject(content);
// optXxx()方法在解析时,如果对应字段不存在会返回空值或者0,不会报错
book.setIsbn(root.optString("isbn"));
book.setTitle(root.optString("title"));
book.setAuthor(parseJsonArrayString(root.getJSONArray("author"), SPLIT));
book.setTranslator(parseJsonArrayString(
root.optJSONArray("translator"), SPLIT));
book.setPubdate(root.optString("pubdate"));
book.setTags(parseJsonArrayObject(root.getJSONArray("tags"), SPLIT,
PROSPLIT));
book.setSeries(parseJsonObject(root.getJSONObject("series"), SPLIT));
book.setPrice(root.optString("ebook_price"));
return book;
}
/*
* 将JsonArray对象解析成特定格式的字符串 适用于["1","2"]这种 感觉是处理一个字符串数组
*/
public String parseJsonArrayString(JSONArray array, String split)
throws Exception {
if (array == null || array.length() < 1) {
return null;
}
// StringBuffer线程安全,StringBuilder速度快,线程不安全
StringBuilder builder = new StringBuilder();
for (int i = 0; i < array.length(); i++) {
// TODO 将分隔符放在前面,放在后面出现了把(漏了的情况,即显示的是 法),没有左括号
builder.append(split);
builder.append(array.optString(i));
}
// 删掉在最开始多出来的分隔符
builder.delete(0, split.length());
return builder.toString();
}
/*
* 将JsonArray对象解析成特定格式的字符串 适用于[{"id":1,"name":"xx"},{"id":2,"name":"xxx"}]这种
* 感觉是处理对象数组
*
* @param split用于分隔JSONObject之间的,proSplit用于分隔JSONObject内部属性之间(如1-xx)
*/
public String parseJsonArrayObject(JSONArray array, String split,
String proSplit) throws Exception {
if (array == null || array.length() < 1) {
return null;
}
// StringBuffer线程安全,StringBuilder速度快,线程不安全
StringBuilder builder = new StringBuilder();
for (int i = 0; i < array.length(); i++) {
builder.append(split);
JSONObject json = array.optJSONObject(i);
// 需要先判断是否为null,否则会报空指针异常
if (json != null) {
builder.append(json.optInt("count"));
// 分隔符,用来分割标签属性
builder.append(proSplit);
builder.append(json.optString("name"));
}
}
// 删掉在最开始多出来的分隔符
builder.delete(0, split.length());
return builder.toString();
}
/*
* 将JsonArray对象解析成特定格式的字符串 适用于{"id":1,"name":"xxx"}这种 感觉处理一个对象
*/
public String parseJsonObject(JSONObject json, String split)
throws Exception {
// StringBuffer线程安全,StringBuilder速度快,线程不安全
StringBuilder builder = new StringBuilder();
if (json != null) {
builder.append(json.optString("id"));
// 分隔符,用来分割标签属性
builder.append(split);
builder.append(json.optString("title"));
}
return builder.toString();
}
/*
* 生成JSON数据
*/
public String serializeJson(Book book) throws Exception {
JSONObject root = new JSONObject();
root.put("isbn", book.getIsbn());
root.put("title", book.getTitle());
root.put("author", serializeJSONArrayString(book.getAuthor(), SPLIT));
root.put("translator",
serializeJSONArrayString(book.getTranslator(), SPLIT));
root.put("pubdate", book.getPubdate());
root.put("tags", serializeJsonArrayObject(book.getTags(), SPLIT, PROSPLIT));
root.put("series", serializeJSONObject(book.getSeries(), SPLIT));
root.put("ebook_price", book.getPrice());
return root.toString();
}
/*
* 与解析字符串数组相反的操作
*/
public JSONArray serializeJSONArrayString(String content, String split) {
String[] ss = content.split(split);
JSONArray array = new JSONArray();
for (String s : ss) {
array.put(s);
}
return array;
}
/*
* 将JsonArray对象解析成特定格式的字符串 适用于[{"id":1,"name":"xx"},{"id":2,"name":"xxx"}]这种
* 感觉是处理对象数组
*/
public JSONArray serializeJsonArrayObject(String content, String split,
String proSplit) throws Exception {
JSONArray array = new JSONArray();
// 首先分解出JSONObject的内容,例如上面的分解成 两部分1-xx 2-xxx -为proSplit属性之间的分隔符
String[] object = content.split(split);
for (String obj : object) {
JSONObject json = new JSONObject();
// 再将JSONObject的内容分解成一个个属性,即把1-xx分成 1 xx
String[] property = obj.split(proSplit);
// count值为int型
json.put("count", Integer.parseInt(property[0]));
json.put("name", property[1]);
// 将JSONObject加入到JSONArray
array.put(json);
}
return array;
}
/*
* 与解析一个对象相反的操作
*/
public JSONObject serializeJSONObject(String content, String split) {
String[] ss = content.split(split);
JSONObject object = new JSONObject();
try {
object.put("id", ss[0]);
object.put("title", ss[1]);
} catch (JSONException e) {
e.printStackTrace();
}
return object;
}
}
注:生成的json文件在File Explorer中,导出可查看,其显示的内容和一开始提供的book.json一样,但顺序不同,这是因为JSON本身就是一些name/value组成的无序的集合。怎么解读这些name的顺序,是由不同的解析器自己定义的。
看一下源码:JSONObject.class
public JSONObject() {
nameValuePairs = new LinkedHashMap<String, Object>();
}
说明JSONObject保存数据其实是通过LinkedHashMap保存的,那么再看一下LinkedHashMap源码,有这么一段
public LinkedHashMap() {
init();
accessOrder = false;
}
就字面意思来看,accessOrder是进入顺序的意思,因此个人觉得应该原因就是这个(未验证,纯属个人感觉)
如果想要使保持和book.json顺序一样,可以采取把这个root JSONObject放入JSONArray中
提醒:有些地方可能不对,请持怀疑的态度。。。