解析json

在网络上找了下解析json格式文件的源代码,好久都没找到。 比如得到一个json格式的任意文件,便可以知道其内部的格式和内容。于是便写了一个。下面是自己写的解析内容。

1.如果有不对的地方,还希望大家能帮忙指正。
2.如果有更好的解析json格式的代码,希望能分享下,给下链接,多谢。^_^


注:在代码中需要json源文件的支持,是为了来判断提供的字符串是否是json格式的字符串,下载地址是:[url]http://www.json.org/java/index.html[/url]。


package com.utils;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
*
* 1. what are in the stack:
* two parts: the name of jsonObject or jsonArray, the sign after: [ or {. Such as: data[, observation{.
* the reason for the sign after put into the stack is to know it is a jsonObject or jsonArray.
* what are in the stack are the parent jsonItem that the children will be put into.
* 2. the result.
* you will get one JSONItem object. It is the "outest" JSONObject.
* you can get others by its children and its children's children.
* @author yuanbo han
*
*/
public class JSONParser {
public static final String icons_regex = "[\\{\\}\\[\\]]";
public static final String signs_split_regex = "[:,\\{\\}\\[\\]]";
public static final String all_sign_regex_for_remove = "[:,\"\\{\\}\\[\\]]";
public static final String attribute_regex = "[,\\{\\}\\[\\]]";

private String jsonString;
private Object container;

public JSONParser(String jsonString) {
super();
this.jsonString = jsonString;
}

public JSONItem getOutestJSONItem(){
if(!this.isJsonFormat(jsonString)){
JSONItem item = new JSONItem();
item.setName("format error");
item.setType(null);
item.setChildren(null);
item.setAttributes(null);
return item;
}

List<JSONItem> items = new ArrayList<JSONItem>();
JSONItem outest = new JSONItem();
outest.setName("outest");
outest.setType(JSONItem.OBJECT);
items.add(outest);//put a outest JSONItem. No name for it, so I set outest.

Stack<String> stack = new Stack<String>();
Matcher matcher = Pattern.compile(signs_split_regex).matcher(jsonString);


int last_sign_index = 0;// in order to find what I want, two indexes help to locate where it is. This is the first one.
JSONItem current = outest;
while(matcher.find()){
int sign_index = matcher.start();// in order to find what I want, two indexes help to locate where it is. This is the second one.
String sign = matcher.group();
if(!sign.trim().equals(",")){
if(sign.trim().equals(":")){//the outer jsonObject or jsonArray. The string before the colon is the name. Or the attributes.
if(getCodeBefore(jsonString,sign_index).equals("\"")){
String code_after = getCodeAfter(jsonString,sign_index);//{ , [ or other things.
if(code_after.matches(icons_regex)){//{ or [. jsonArray or jsonObject
String name_origin = jsonString.substring(last_sign_index, sign_index).trim();
String name = removeSigns(name_origin);
JSONItem item = new JSONItem();
item.setName(name);
if(isJsonObjectItem(code_after)){
item.setType(JSONItem.OBJECT);
}else{
item.setType(JSONItem.ARRAY);
}
items.add(item);
current = item;// current jsonItem. This is for the attribute part. to get whose attribute it is.

String parentName = removeSigns(stack.peek());
JSONItem parent = getJSONItem(items,parentName);
if(parent != null){
parent.addChild(item);
}

stack.push(name+code_after);
}else if(isAttribute(jsonString,sign_index)){// attributes
String key_origin = jsonString.substring(last_sign_index, sign_index);
String key = removeSigns(key_origin);
String value = getAttributeValueAfter(jsonString,sign_index);
current.addAttribute(key,value);
}
}
}else{// "[" or "]" or "{" or "}".
if(!stack.empty()){
String header = stack.peek();
if(isPair(header,sign)){
stack.pop();
}else{
if(!getCodeBefore(jsonString,sign_index).equals(":")){// inner child or array. no name.
JSONItem item = new JSONItem();
if(isJsonObjectItem(sign)){
item.setType(JSONItem.OBJECT);
}else{
item.setType(JSONItem.ARRAY);
}
items.add(item);
current = item;

String parentName = removeSigns(header);
JSONItem parent = getJSONItem(items,parentName);
if(parent != null){
parent.addChild(item);
}

stack.push(sign);
}
}
}else{// the first time
stack.push("outest" + sign);
}
}
}

last_sign_index = sign_index;// if the sign is ",", just remember its position. It is the meaning of the sign "," in the process. To ensure that the String between the last_sign_index and the sign_index does not contain ",".
}
JSONItem result = getJSONItem(items,"outest");;
processJSONItem(result);
return result;
}

/**
* to give a name to each child of jsonArray.
* @param item
*/
private void processJSONItem(JSONItem item){
if(item.getChildren() != null && item.getChildren().size() > 0){
int count = 0;
for(JSONItem child : item.getChildren()){
if(child.getName().trim().equals("")){
child.setName(item.getName() + "_" +count + "");
count++;
}
processJSONItem(child);
}
}
}

public static String removeSigns(String origin_name){
if(origin_name != null){
String name = origin_name.replaceAll(all_sign_regex_for_remove, "").trim();
return name;
}
return null;
}

/**
* to find the jsonItem of the give name.
* null if not exist.
* @param JSONItems
* @param name
* @return
*/
public static JSONItem getJSONItem(List<JSONItem> JSONItems, String name){
if(JSONItems != null && name != null && !name.trim().equals("")){
for(JSONItem item : JSONItems){
if(item.getName().trim().equals(name.trim())){
return item;
}
}
}
return null;
}

public static boolean isJsonObjectItem(String sign){
if(sign.trim().equals("{")){
return true;
}
return false;
}

public static boolean isPair(String former, String latter){
if(former.contains("{") && latter.contains("}")
|| former.contains("}") && latter.contains("{")
|| former.contains("[") && latter.contains("]")
|| former.contains("]") && latter.contains("[")){
return true;
}
return false;
}

/**
* Get the one char just right before the index in the content. But the one char does not match "\\s".
* @param content
* @param index
* @return
*/
public static String getCodeBefore(String content, int index){
for(int i=index-1;i>=0;i--){
String sign = String.valueOf(content.charAt(i));
if(!sign.matches("\\s")){
return sign;
}
}
return null;
}


/**
* Get the one char just right after the index in the content. But the one char does not match "\\s".
* @param content
* @param index
* @return
*/
public static String getCodeAfter(String content, int index){
for(int i=index+1;i<content.length();i++){
String sign = String.valueOf(content.charAt(i));
if(!sign.matches("\\s")){
return sign;
}
}
return null;
}

/**
* Get the one char just right before the index in the content. But the one char does not match "\\w" and the one char is not blank.
* @param content
* @param index
* @return
*/
public static String getSignBefore(String content, int index){
for(int i=index-1;i>=0;i--){
String sign = String.valueOf(content.charAt(i));
if(!sign.equals(" ") && !sign.matches("\\w")){
return sign;
}
}
return null;
}

/**
* Get the one char just right after the index in the content. But the one char does not match "\\w" and the one char is not blank.
* @param content
* @param index
* @return
*/
public static String getSignAfter(String content, int index){
for(int i=index+1;i<content.length();i++){
String sign = String.valueOf(content.charAt(i));
if(!sign.equals(" ") && !sign.matches("\\w")){
return sign;
}
}
return null;
}

/**
* the first_quote_bofore_index and second_quote_bofore_index is to find the name of the attribute.
* code_before is to ensure that the sign before the the attribute name is "," or "[" or "{".
* @param content
* @param index
* @return
*/
public static boolean isAttribute(String content, int index){
int first_quote_bofore_index = content.lastIndexOf("\"", index);
if(first_quote_bofore_index == -1){
return false;
}
int second_quote_bofore_index = content.lastIndexOf("\"",first_quote_bofore_index - 1);
if(second_quote_bofore_index == -1){
return false;
}
String code_before = getCodeBefore(content,second_quote_bofore_index);

if(code_before.matches(attribute_regex)){
return true;
}
return false;
}

/**
* the value of the attribute are object, string, or number
* so some are quoted, but some are not.
* @param content
* @param index
* @return
*/
public static String getAttributeValueAfter(String content, int index){
String result = "";
String icon = getSignAfter(content,index);
if(icon.equals("\"")){
int former_quote_index = content.indexOf("\"", index);
int latter_quote_index = content.indexOf("\"", former_quote_index + 1);
result = content.substring(former_quote_index + 1, latter_quote_index);
}else{
int icon_index = content.indexOf(icon, index + 1);
result = content.substring(index+1, icon_index);
}

return result;
}

public boolean isJsonFormat(String string){
try {
new JSONObject(string);
} catch (JSONException e) {
return false;
}
return true;
}

/**
* from the root jsonItem.
* @param root
*/
public static void printJSONItem(JSONItem root){
if(root.getName().trim().equals("")){
System.out.println("inner child, " + root.getType());
}else{
System.out.println(root.getName() + ", " + root.getType());
}
if(root.getAttributes().size() > 0){
for(String key : root.getAttributes().keySet()){
System.out.println("\t key:" + key + ", value:" + root.getAttributes().get(key));
}
}
if(root.getChildren().size() > 0){
for(JSONItem item : root.getChildren()){
printJSONItem(item);
}
}
}


/**
* loop to find the container of the given name in the jsonString
* @param container
* @param outest
* @param name
* @return
*/
private void getContainer(Object container, JSONItem outest, String name){
if(outest != null && container != null && name != null){
if(name.trim().equals("")){
this.container = outest;
}else if(name.equals(outest.getName())){
this.container = container;
}else{
try {
List<JSONItem> children = outest.getChildren();
if(children != null && children.size() > 0){
for(int i=0;i<children.size();i++){

JSONObject jo = null;
JSONArray ja = null;
if(container instanceof JSONObject){
jo = (JSONObject)container;
}else if(container instanceof JSONArray){
ja = (JSONArray)container;
}

JSONItem child = children.get(i);
String child_type = child.getType();
String child_name = child.getName();
if(jo != null){
if(child_type.equals(JSONItem.ARRAY)){
ja = jo.getJSONArray(child_name);
getContainer(ja,child,name);
}else if(child_type.equals(JSONItem.OBJECT)){
jo = jo.getJSONObject(child_name);
getContainer(jo,child,name);
}
}else if(ja != null){
if(child_type.equals(JSONItem.ARRAY)){
ja = ja.getJSONArray(i);
getContainer(ja,child,name);
}else if(child_type.equals(JSONItem.OBJECT)){
jo = ja.getJSONObject(i);
getContainer(jo,child,name);
}
}
}
}
} catch (JSONException e) {

}
}
}
}


public Object getContainerObject(Object container, JSONItem outest, String name) {
this.getContainer(container, outest, name);
return this.container;
}

public void setContainer(Object container) {
this.container = container;
}

public String getJsonString() {
return jsonString;
}

public void setJsonString(String jsonString) {
this.jsonString = jsonString;
}

public static void main(String[] args) throws Exception{
String jsonString = FileUtil.getFileContent("c:\\json.txt");
JSONParser parser = new JSONParser(jsonString);

JSONItem outest = parser.getOutestJSONItem();
JSONObject jo = new JSONObject(jsonString);
String name = "data_5";

Object result = parser.getContainerObject(jo, outest, name);

JSONArray ja_container = null;
JSONObject jo_container = null;
if(result instanceof JSONObject){
jo_container = (JSONObject)result;
}else if(result instanceof JSONArray){
ja_container = (JSONArray)result;
}

if(ja_container != null){
System.out.println(ja_container.length());
}else if(jo_container != null){
System.out.println(jo_container.getInt("sort_order"));
}

}
}




package com.utils;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class JSONItem {
public static final String ARRAY = "arr";
public static final String OBJECT = "obj";
private String name = "";// name
private String type = "";// array or object
private Map<String,String> attributes = new LinkedHashMap<String,String>();
private List<JSONItem> children = new ArrayList<JSONItem>();


public JSONItem() {
super();
}

public JSONItem(String name, String type) {
super();
this.name = name;
this.type = type;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getType() {
return type;
}

public void setType(String type) {
this.type = type;
}

public Map<String, String> getAttributes() {
return attributes;
}

public void setAttributes(Map<String, String> attributes) {
this.attributes = attributes;
}

public void addAttribute(String key, String value){
this.attributes.put(key, value);
}

public List<JSONItem> getChildren() {
return children;
}

public void setChildren(List<JSONItem> children) {
this.children = children;
}

public void addChild(JSONItem child){
this.children.add(child);
}



@Override
public boolean equals(Object obj) {
if(obj == null){
return false;
}

if(obj instanceof JSONItem){
JSONItem item = (JSONItem)obj;
if(item.getName().equals(this.name) && item.getType().equals(this.name)){
return true;
}
}

return false;
}

@Override
public String toString() {
String result = "";
result += ("name: " + name + ", ");
result += ("type: " + type + ", ");
result += ("attributes: " + attributes.toString() + ", ");
result += ("children size: " + children.size());

return result;
}


}



下面是最近经常处理的json格式的文件。地址为:[url]http://www.bom.gov.au/fwo/IDS60801/IDS60801.95655.json[/url]

{
"observations": {
"notice": [
{
"copyright": "Copyright Commonwealth of Australia 2010, Bureau of Meteorology. For more information see: http://www.bom.gov.au/other/copyright.shtml http://www.bom.gov.au/other/disclaimer.shtml",
"copyright_url": "http://www.bom.gov.au/other/copyright.shtml",
"disclaimer_url": "http://www.bom.gov.au/other/disclaimer.shtml",
"feedback_url": "http://www.bom.gov.au/other/feedback"
}
],
"header": [
{
"refresh_message": "Issued at 6:35 pm CST Wednesday 11 August 2010",
"ID": "IDS60801",
"main_ID": "IDS60800",
"name": "Nonning",
"state_time_zone": "SA",
"time_zone": "CST",
"product_name": "Weather Observations",
"state": "South Australia"
}
],
"data": [
{
"sort_order": 0,
"wmo": 95655,
"name": "Nonning",
"history_product": "IDS60801",
"local_date_time": "11/03:00pm",
"local_date_time_full": "20100811150000",
"air_temp": 15.5,
"apparent_t": 12.2,
"cloud": "Partly cloudy",
"cloud_base_m": null,
"cloud_oktas": 4,
"cloud_type": "-",
"cloud_type_id": 30,
"delta_t": 4.5,
"dewpt": 6.3,
"gust_kmh": null,
"gust_kt": null,
"lat": -32.5,
"lon": 136.5,
"press_msl": null,
"press_qnh": null,
"press_tend": "-",
"rain_trace": "0.0",
"rel_hum": 54,
"sea_state": "-",
"swell_dir_worded": "-",
"swell_height": "-",
"swell_length": "-",
"vis_km": "50",
"weather": "Fine",
"wind_dir": "SW",
"wind_spd_kmh": 13,
"wind_spd_kt": 7
},
{
"sort_order": 1,
"wmo": 95655,
"name": "Nonning",
"history_product": "IDS60801",
"local_date_time": "11/09:00am",
"local_date_time_full": "20100811090000",
"air_temp": 9.5,
"apparent_t": 7.8,
"cloud": "Clear",
"cloud_base_m": 2500,
"cloud_oktas": 0,
"cloud_type": "-",
"cloud_type_id": null,
"delta_t": 1.0,
"dewpt": 7.4,
"gust_kmh": null,
"gust_kt": null,
"lat": -32.5,
"lon": 136.5,
"press_msl": null,
"press_qnh": null,
"press_tend": "-",
"rain_trace": "0.4",
"rel_hum": 87,
"sea_state": "-",
"swell_dir_worded": "-",
"swell_height": "-",
"swell_length": "-",
"vis_km": "40",
"weather": "Fine",
"wind_dir": "SW",
"wind_spd_kmh": 6,
"wind_spd_kt": 3
},
{
"sort_order": 2,
"wmo": 95655,
"name": "Nonning",
"history_product": "IDS60801",
"local_date_time": "11/06:00am",
"local_date_time_full": "20100811060000",
"air_temp": 7.0,
"apparent_t": 5.1,
"cloud": "Clear",
"cloud_base_m": 2500,
"cloud_oktas": 0,
"cloud_type": "-",
"cloud_type_id": null,
"delta_t": 1.0,
"dewpt": 4.7,
"gust_kmh": null,
"gust_kt": null,
"lat": -32.5,
"lon": 136.5,
"press_msl": null,
"press_qnh": null,
"press_tend": "-",
"rain_trace": "-",
"rel_hum": 85,
"sea_state": "-",
"swell_dir_worded": "-",
"swell_height": "-",
"swell_length": "-",
"vis_km": "50",
"weather": "Fine",
"wind_dir": "SSW",
"wind_spd_kmh": 4,
"wind_spd_kt": 2
},
{
"sort_order": 3,
"wmo": 95655,
"name": "Nonning",
"history_product": "IDS60801",
"local_date_time": "10/03:00pm",
"local_date_time_full": "20100810150000",
"air_temp": 12.0,
"apparent_t": 10.4,
"cloud": "Mostly cloudy",
"cloud_base_m": null,
"cloud_oktas": 7,
"cloud_type": "-",
"cloud_type_id": 30,
"delta_t": 2.0,
"dewpt": 7.9,
"gust_kmh": null,
"gust_kt": null,
"lat": -32.5,
"lon": 136.5,
"press_msl": null,
"press_qnh": null,
"press_tend": "-",
"rain_trace": "0.4",
"rel_hum": 76,
"sea_state": "-",
"swell_dir_worded": "-",
"swell_height": "-",
"swell_length": "-",
"vis_km": "40",
"weather": "Fine",
"wind_dir": "SSW",
"wind_spd_kmh": 6,
"wind_spd_kt": 3
},
{
"sort_order": 4,
"wmo": 95655,
"name": "Nonning",
"history_product": "IDS60801",
"local_date_time": "10/09:00am",
"local_date_time_full": "20100810090000",
"air_temp": 8.0,
"apparent_t": 6.9,
"cloud": "Mostly cloudy",
"cloud_base_m": null,
"cloud_oktas": 7,
"cloud_type": "-",
"cloud_type_id": 30,
"delta_t": 0.5,
"dewpt": 6.9,
"gust_kmh": null,
"gust_kt": null,
"lat": -32.5,
"lon": 136.5,
"press_msl": null,
"press_qnh": null,
"press_tend": "-",
"rain_trace": "4.0",
"rel_hum": 93,
"sea_state": "-",
"swell_dir_worded": "-",
"swell_height": "-",
"swell_length": "-",
"vis_km": "50",
"weather": "Fine",
"wind_dir": "SW",
"wind_spd_kmh": 2,
"wind_spd_kt": 1
},
{
"sort_order": 5,
"wmo": 95655,
"name": "Nonning",
"history_product": "IDS60801",
"local_date_time": "10/06:00am",
"local_date_time_full": "20100810060000",
"air_temp": 6.5,
"apparent_t": 4.1,
"cloud": "Cloudy",
"cloud_base_m": null,
"cloud_oktas": 8,
"cloud_type": "-",
"cloud_type_id": 30,
"delta_t": 1.0,
"dewpt": 4.2,
"gust_kmh": null,
"gust_kt": null,
"lat": -32.5,
"lon": 136.5,
"press_msl": null,
"press_qnh": null,
"press_tend": "-",
"rain_trace": "-",
"rel_hum": 85,
"sea_state": "-",
"swell_dir_worded": "-",
"swell_height": "-",
"swell_length": "-",
"vis_km": "40",
"weather": "Fine",
"wind_dir": "SW",
"wind_spd_kmh": 6,
"wind_spd_kt": 3
},
{
"sort_order": 6,
"wmo": 95655,
"name": "Nonning",
"history_product": "IDS60801",
"local_date_time": "09/03:00pm",
"local_date_time_full": "20100809150000",
"air_temp": 10.0,
"apparent_t": 7.8,
"cloud": "Cloudy",
"cloud_base_m": null,
"cloud_oktas": 8,
"cloud_type": "-",
"cloud_type_id": 30,
"delta_t": 2.1,
"dewpt": 5.4,
"gust_kmh": null,
"gust_kt": null,
"lat": -32.5,
"lon": 136.5,
"press_msl": null,
"press_qnh": null,
"press_tend": "-",
"rain_trace": "0.0",
"rel_hum": 73,
"sea_state": "-",
"swell_dir_worded": "-",
"swell_height": "-",
"swell_length": "-",
"vis_km": "30",
"weather": "Fine",
"wind_dir": "NE",
"wind_spd_kmh": 6,
"wind_spd_kt": 3
},
{
"sort_order": 7,
"wmo": 95655,
"name": "Nonning",
"history_product": "IDS60801",
"local_date_time": "09/09:00am",
"local_date_time_full": "20100809090000",
"air_temp": 9.5,
"apparent_t": 9.2,
"cloud": "Partly cloudy",
"cloud_base_m": null,
"cloud_oktas": 5,
"cloud_type": "-",
"cloud_type_id": 30,
"delta_t": 0.5,
"dewpt": 8.5,
"gust_kmh": null,
"gust_kt": null,
"lat": -32.5,
"lon": 136.5,
"press_msl": null,
"press_qnh": null,
"press_tend": "-",
"rain_trace": "3.0",
"rel_hum": 93,
"sea_state": "-",
"swell_dir_worded": "-",
"swell_height": "-",
"swell_length": "-",
"vis_km": "40",
"weather": "Fine",
"wind_dir": "CALM",
"wind_spd_kmh": 0,
"wind_spd_kt": 0
},
{
"sort_order": 8,
"wmo": 95655,
"name": "Nonning",
"history_product": "IDS60801",
"local_date_time": "09/06:00am",
"local_date_time_full": "20100809060000",
"air_temp": 3.5,
"apparent_t": 2.1,
"cloud": "Mostly cloudy",
"cloud_base_m": null,
"cloud_oktas": 6,
"cloud_type": "-",
"cloud_type_id": 30,
"delta_t": 0.0,
"dewpt": 3.5,
"gust_kmh": null,
"gust_kt": null,
"lat": -32.5,
"lon": 136.5,
"press_msl": null,
"press_qnh": null,
"press_tend": "-",
"rain_trace": "-",
"rel_hum": 100,
"sea_state": "-",
"swell_dir_worded": "-",
"swell_height": "-",
"swell_length": "-",
"vis_km": "50",
"weather": "Fine",
"wind_dir": "CALM",
"wind_spd_kmh": 0,
"wind_spd_kt": 0
}
]
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值