最近一個(gè)項(xiàng)目要對(duì)藝龍,攜程等酒店預(yù)訂網(wǎng)站進(jìn)行價(jià)格信息采集.因?yàn)檫@兩個(gè)網(wǎng)站都不是省油的燈啊,多次提交ajax表單,參數(shù)編碼,獲取特定的城市和酒店代碼等等手段,可謂過五關(guān)斬六將,總算是把數(shù)據(jù)采集回來,但是又面臨一個(gè)難題:采集回來的信息是json格式的,那就涉及到j(luò)son數(shù)據(jù)轉(zhuǎn)換成java對(duì)象了
首先要了解json數(shù)據(jù)的格式
[{"CityType":"hotel","TabList":[{"TabId":"1","Name":"\u70ED\u95E8","NameEn":"Hot","CityList":[{"ProvinceId":null,"CityId":"0101","CityCode":"0101","CityNameCn":"\u5317\u4EAC","CityNameEn":"Beijing","CityThreeSign":"","CityType":"hotel","OldEnglishName":"peking"},{"ProvinceId":null,"CityId":"0201","CityCode":"0201","CityNameCn":"\u4E0A\u6D77","CityNameEn":"Shanghai","CityThreeSign":"","CityType":"hotel","OldEnglishName":""},{"ProvinceId":null,"CityId":"2001","CityCode":"2001","CityNameCn":"\u5E7F\u5DDE","CityNameEn":"Guangzhou","CityThreeSign":"","CityType":"hotel","OldEnglishName":"canton"}]}]}];
jsonViewer是個(gè)好東西,不過HTTPAnalysis直接就集成了jsonViewer,不過還是前者比較輕巧:
json和java之間的互換可以使用json-lib, 基本的使用可以看文檔就行.網(wǎng)上也有一些集成的類,我建議直接看它的源代碼,了解他是如何通過反射和使用臨時(shí)對(duì)象解析json數(shù)據(jù),并封裝成java對(duì)象.
這個(gè)json數(shù)據(jù)時(shí)list的嵌套,如果要對(duì)整個(gè)json文件解析,需要使用如下方法,需要構(gòu)造跟json數(shù)據(jù)對(duì)應(yīng)的Tab.class 和City.class,而且字段名稱必須一致(駱駝首字母小寫),提供默認(rèn)構(gòu)造方法,這樣就可以將json數(shù)據(jù)作為一個(gè)完整的對(duì)象,想怎么干都行了.
HashMap<String,Class> map = new HashMap<String,Class>();map.put("tabList", Tab.class);map.put("cityList", City.class); /** * 從一個(gè)JSON數(shù)組得到一個(gè)java對(duì)象集合,其中對(duì)象中包含有集合屬性 * @param object * @param clazz * @param map 集合屬性的類型 (key : 集合屬性名, value : 集合屬性類型class) eg: ("beansList" : Bean.class) * @return */ public static List getDTOList(String jsonString, Class clazz, Map map){ setDataFormat2JAVA(); JSONArray array = JSONArray.fromObject(jsonString); List list = new ArrayList(); for(Iterator iter = array.iterator(); iter.hasNext();){ JSONObject jsonObject = (JSONObject)iter.next(); list.add(JSONObject.toBean(jsonObject, clazz, map)); } return list; }
由于我的需求只是需要重json數(shù)據(jù)中獲取特定的信息對(duì)象,如上面的cityList,像tabList等對(duì)象我沒必要去構(gòu)造和獲取,而且在實(shí)際使用過程中我發(fā)現(xiàn)
json數(shù)據(jù)中變量如果不是首字母小寫,是無法轉(zhuǎn)換成java對(duì)象的.這個(gè)確實(shí)很坑爹!!!!!
于是乎,我就寫了個(gè)直接讀取和解析一個(gè)片段json數(shù)據(jù)的類,有了這個(gè)類,加上對(duì)象映射,基本上沒什么解析不了
package com.engine.logic.component.loader.impl.json.utils;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.util.ArrayList;import java.util.Iterator;import java.util.LinkedList;import java.util.List;import java.util.regex.Matcher;import java.util.regex.Pattern;import net.sf.json.JSONArray;import net.sf.json.JSONObject;public class JSonStrUtils { /** * json 數(shù)據(jù)括號(hào)自動(dòng)補(bǔ)全 * **/ public static String autoComplete(String targetJson){ LinkedList<Character> stack = new LinkedList<Character>(); String returnStr =""; char[] charArray = targetJson.toCharArray(); for(int i = 0;i<charArray.length;i++){ if(charArray[i]=='['||charArray[i]=='{'){//入棧 stack.addFirst(charArray[i]); }else if(charArray[i]==']'){ //判斷是否閉合 char last = stack.peekFirst(); if(last !='['){//不閉合,補(bǔ) } returnStr+='}'; }else//閉合 { stack.pollFirst(); } }else if(charArray[i]=='}'){ //判斷是否閉合 char last = stack.peekFirst(); if(last !='{'){//不閉合,補(bǔ) } returnStr+=']'; }else//閉合 { stack.pollFirst(); } } returnStr+=charArray[i]; } for(char c:stack){ System.out.println("left in stack:"+c); } return returnStr; } /*** * 用于處理json數(shù)據(jù)中出現(xiàn)變量名非首字母小寫的情況,利用正則匹配變量,然后把首字母變成小寫 * */ public static String dealWithFirstChar(String jsonInput){ String originalInput = jsonInput; StringBuilder inputStr = new StringBuilder(jsonInput); String regex = "\"(\\w+)\":"; Pattern p = Pattern.compile(regex,Pattern.CASE_INSENSITIVE); Matcher m = p.matcher(inputStr); List<String> result=new ArrayList<String>(); while(m.find()){ String valueName = m.group(1); String newValueName = null; char[] words =valueName.toCharArray(); if(Character.isUpperCase(words[0])){//首字母大寫,不符合變量命名規(guī)范 words[0] = Character.toLowerCase(words[0]); newValueName = new String(words);// System.out.println("orignal value:"+valueName+" new value :"+ newValueName);// String regexWord = "\""+valueName+"\":"; String regx1 = "\""+valueName+"\":"; String replace = "\""+newValueName+"\":"; originalInput=originalInput.replaceAll(regx1, replace); } result.add(valueName); inputStr.delete(0, m.end(0)); m=p.matcher(inputStr); } return originalInput; } /*** * 用戶將unicode編碼轉(zhuǎn)換成漢字 * */ public static String UnicodeToString(String str) { Pattern pattern = Pattern.compile("(\\\\u(\\p{XDigit}{4}))"); Matcher matcher = pattern.matcher(str); char ch; while (matcher.find()) { ch = (char) Integer.parseInt(matcher.group(2), 16); str = str.replace(matcher.group(1), ch + ""); } return str; } /*** * 用戶將漢字轉(zhuǎn)換成unicode編碼 * */ public static String toUNICODE(String s) { StringBuilder sb=new StringBuilder(); for(int i=0;i<s.length();i++) { if(s.charAt(i)<=256) { sb.append("\\u00"); } else { sb.append("\\u"); } sb.append(Integer.toHexString(s.charAt(i)).toUpperCase()); } return sb.toString(); } /** * 讀取json文件,轉(zhuǎn)換為字符串 * */ public static String readJSonFile(String fileName){ InputStream in = null; String jsonStr = ""; try { in = JSonStrUtils.class.getResourceAsStream(fileName); BufferedReader reader = new BufferedReader(new InputStreamReader(in)); String temp = reader.readLine(); while(temp!=null){ jsonStr+=temp; temp = reader.readLine(); } in.close(); } catch (IOException e) { e.printStackTrace(); System.out.println("read json file failed :"+fileName); } return jsonStr; } /*** * 在指定的JSONObject 中尋找特定屬性的第一個(gè)值 * */ public static List<String> findTargetProperty(JSONObject object,String propertyName,boolean isRecursive){ List<String> values = new ArrayList<String>(); for( Iterator entries = object.names().iterator(); entries.hasNext(); ){ String name = (String) entries.next(); Object value = object.get(name); if(name.equals(propertyName)){//找到目標(biāo)屬性 values.add(value.toString()); }else if(isRecursive){ if(value instanceof JSONObject){ values.addAll(findTargetProperty((JSONObject)value,propertyName,isRecursive)); }else if(value instanceof JSONArray){ JSONArray array = (JSONArray)value; for(Iterator iter = array.iterator(); iter.hasNext();){ JSONObject jsonObject = (JSONObject)iter.next(); values.addAll(findTargetProperty(jsonObject,propertyName,isRecursive)); } } } } return values; } /*** * 從指定的JSonArray中尋找指定名稱的子json數(shù)組 * */ public static List<JSONArray> findTargetJSonArray(JSONArray array,String targetName){ List<JSONArray> arrays = new ArrayList<JSONArray>(); for(Iterator iter = array.iterator(); iter.hasNext();){//遍歷數(shù)組中的JSONObject JSONObject jsonObject = (JSONObject)iter.next(); if( jsonObject == null || jsonObject.isNullObject() ){ continue; } for( Iterator entries = jsonObject.names().iterator(); entries.hasNext(); ){ String name = (String) entries.next(); Object value = jsonObject.get(name); if(value instanceof JSONArray){//屬性為數(shù)組 //先判斷是否目標(biāo)數(shù)組 if(name.equals(targetName)){ arrays.add((JSONArray) value); } //遞歸查找 arrays.addAll(findTargetJSonArray((JSONArray) value,targetName)); } } } return arrays; }}