最近一個項目要對藝龍,攜程等酒店預訂網站進行價格信息採集.因爲這兩個網站都不是省油的燈啊,多次提交ajax表單,參數編碼,獲取特定的城市和酒店代碼等等手段,可謂過五關斬六將,總算是把數據採集回來,但是又面臨一個難題:採集回來的信息是json格式的,那就涉及到json數據轉換成java對象了
首先要了解json數據的格式
[{
"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是個好東西,不過HTTPAnalysis直接就集成了jsonViewer,不過還是前者比較輕巧:
json和java之間的互換可以使用json-lib,
基本的使用可以看文檔就行.網上也有一些集成的類,我建議直接看它的源代碼,瞭解他是如何通過反射和使用臨時對象解析json數據,並封裝成java對象.
這個json數據時list的嵌套,如果要對整個json文件解析,需要使用如下方法,需要構造跟json數據對應的Tab.
class
和City.
class
,而且字段名稱必須一致(駱駝首字母小寫),提供默認構造方法,這樣就可以將json數據作爲一個完整的對象,想怎麼幹都行了.
HashMap<String,Class>
map =
new
HashMap<String,Class>();
map.put(
"tabList"
,
Tab.
class
);
map.put(
"cityList"
,
City.
class
);
/**
*
從一個JSON數組得到一個java對象集合,其中對象中包含有集合屬性
*
@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數據中獲取特定的信息對象,如上面的cityList,像tabList等對象我沒必要去構造和獲取,而且在實際使用過程中我發現
JSON數據中變量如果不是首字母小寫,是無法轉換成JAVA對象的.這個確實很坑爹!!!!!
於是乎,我就寫了個直接讀取和解析一個片段json數據的類,有了這個類,加上對象映射,基本上沒什麼解析不了
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 數據括號自動補全
*
**/
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
!=
'['
){
returnStr+=
'}'
;
}
else
{
stack.pollFirst();
}
}
else
if
(charArray[i]==
'}'
){
char
last = stack.peekFirst();
if
(last
!=
'{'
){
returnStr+=
']'
;
}
else
{
stack.pollFirst();
}
}
returnStr+=charArray[i];
}
for
(
char
c:stack){
System.out.println(
"left
in stack:"
+c);
}
return
returnStr;
}
/***
*
用於處理json數據中出現變量名非首字母小寫的情況,利用正則匹配變量,然後把首字母變成小寫
*
*/
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
])){
words[
0
]
= Character.toLowerCase(words[
0
]);
newValueName
=
new
String(words);
+
newValueName);
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編碼轉換成漢字
*
*/
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;
}
/***
*
用戶將漢字轉換成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文件,轉換爲字符串
*
*/
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 中尋找特定屬性的第一個值
*
*/
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)){
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數組
*
*/
public
static
List<JSONArray> findTargetJSonArray(JSONArray array,
String
targetName){
List<JSONArray>
arrays =
new
ArrayList<JSONArray>();
for
(Iterator
iter = array.iterator(); iter.hasNext();){
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){
if
(name.equals(targetName)){
arrays.add((JSONArray)
value);
}
arrays.addAll(findTargetJSonArray((JSONArray)
value,
targetName));
}
}
}
return
arrays;
}
}