读写JSON(初学、记录)

作为初学者,尚未就业,就不去如何如何分析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中
提醒:有些地方可能不对,请持怀疑的态度。。。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值