json在python下的解析http://json.org/這個事json的官方網(wǎng)站,上面有很多json工具的介紹,和json的原理性介紹。
dos下面simplejson的安裝,先配置系統(tǒng)變量里面的path至C:/python27/,然后進(jìn)入simplejson的目錄,輸入python.exe setup.py install這個命令,執(zhí)行安裝程序即可。
一、JSON的格式:
1,對象:
{name:"Peggy",email:"peggy@gmail.com",homepage:"http://www.peggy.com"}
{ 屬性 : 值 , 屬性 : 值 , 屬性 : 值 },必須是大括號未外表,如果不是大括號,則把大括號外邊的內(nèi)容過濾掉。
2,數(shù)組是有順序的值的集合。一個數(shù)組開始于"[",結(jié)束于"]",值之間用","分隔。
[
{name:"Peggy",email:"peggy@gmail.com",homepage:"http://www.peggy.com"}, {name:"Peggy",email:"peggy@gmail.com",homepage:"http://www.peggy.com"},
{name:"Peggy",email:"peggy@gmail.com",homepage:"http://www.peggy.com"}
]
3, 值可以是字符串、數(shù)字、true、false、null,也可以是對象或數(shù)組。這些結(jié)構(gòu)都能嵌套。
4,json示例:
import json
# Converting Python to JSON
json_object = json.write( python_object )
# Converting JSON to Python
python_object = json.read( json_object )
5,simplejson 示例:
import simplejson
# Converting Python to JSON
json_object = simplejson.dumps( python_object )
# Converting JSON to Python
python_object = simplejson.loads( json_object )
二、python從web接口上查詢信息
1,先看個例子
>>> import urllib
>>> url='http://a.bkeep.com/page/api/saInterface/searchServerInfo.htm?serviceTag=729HH2X'
>>> page=urllib.urlopen(url)
>>> data=page.read()
>>> print data //這個就是json的數(shù)據(jù)結(jié)構(gòu),str類型
{"total":1,"data":[{"outGuaranteeTime":"","assetsNum":"B50070100007003","cabinet":"H05","deviceModel":"PowerEdge 1950","hostname":"hzshterm1.alibaba.com","logicSite":"中文站","memoryInfo":{"amount":4,"size":8192},"ip":"172.16.20.163","isOnline":true,"useState":"使用中","serviceTag":"729HH2X","cpuInfo":{"amount":2,"masterFrequency":1995,"model":"Intel(R) Xeon(R) CPU E5405 @ 2.00GHz","coreNum":8,"l2CacheSize":6144},"cabinetPositionNum":"","buyTime":"2009-06-29","manageIp":"172.31.58.223","idc":"杭州德勝機房","responsibilityPerson":"張之誠"}],"errorMsg":"","isSuccess":true}
>>> type(data)
<type 'str'>
2,有了json數(shù)據(jù)結(jié)構(gòu),我卻不知道怎么把它解析出來,幸虧有了李建輝的指導(dǎo)。大概思路是:
首先,json基本上是key/value的,python中就叫字典。既然是字典,那就應(yīng)該安照讀字典的方式去讀。
將上面的data轉(zhuǎn)為字典類型,這里用json模塊的read方法。
>>> import json
>>> ddata=json.read(data)
>>> ddata
{'isSuccess': True, 'errorMsg': '', 'total': 1, 'data': [{'isOnline': True, 'idc': '\xe6\x9d\xad\xe5\xb7\x9e\xe5\xbe\xb7\xe8\x83\x9c\xe6\x9c\xba\xe6\x88\xbf', 'assetsNum': 'B50070100007003', 'responsibilityPerson': '\xe5\xbc\xa0\xe4\xb9\x8b\xe8\xaf\x9a', 'deviceModel': 'PowerEdge 1950', 'serviceTag': '729HH2X', 'ip': '172.16.20.163', 'hostname': 'hzshterm1.alibaba.com', 'manageIp': '172.31.58.223', 'cabinet': 'H05', 'buyTime': '2009-06-29', 'useState': '\xe4\xbd\xbf\xe7\x94\xa8\xe4\xb8\xad', 'memoryInfo': {'amount': 4, 'size': 8192}, 'cpuInfo': {'coreNum': 8, 'l2CacheSize': 6144, 'amount': 2, 'model': 'Intel(R) Xeon(R) CPU E5405 @ 2.00GHz', 'masterFrequency': 1995}, 'cabinetPositionNum': '', 'outGuaranteeTime': '', 'logicSite': '\xe4\xb8\xad\xe6\x96\x87\xe7\xab\x99'}]}
>>>
看看ddata已經(jīng)是dict類型了
>>> type(ddata)
<type 'dict'>
其次,我們以讀字典中key 為”data”對應(yīng)的鍵值
>>> ddata['data'] //查看字典的方法!
[{'isOnline': True, 'idc': '\xe6\x9d\xad\xe5\xb7\x9e\xe5\xbe\xb7\xe8\x83\x9c\xe6\x9c\xba\xe6\x88\xbf', 'assetsNum': 'B50070100007003', 'responsibilityPerson': '\xe5\xbc\xa0\xe4\xb9\x8b\xe8\xaf\x9a', 'deviceModel': 'PowerEdge 1950', 'serviceTag': '729HH2X', 'ip': '172.16.20.163', 'hostname': 'hzshterm1.alibaba.com', 'manageIp': '172.31.58.223', 'cabinet': 'H05', 'buyTime': '2009-06-29', 'useState': '\xe4\xbd\xbf\xe7\x94\xa8\xe4\xb8\xad', 'memoryInfo': {'amount': 4, 'size': 8192}, 'cpuInfo': {'coreNum': 8, 'l2CacheSize': 6144, 'amount': 2, 'model': 'Intel(R) Xeon(R) CPU E5405 @ 2.00GHz', 'masterFrequency': 1995}, 'cabinetPositionNum': '', 'outGuaranteeTime': '', 'logicSite': '\xe4\xb8\xad\xe6\x96\x87\xe7\xab\x99'}]
>>>type(ddata[‘data’])
<type 'list'>
發(fā)現(xiàn)ddata[‘data’]是一個列表,列表就要用序號來查詢
>>> ddata['data'][0] //查看列表的方法!
{'isOnline': True, 'idc': '\xe6\x9d\xad\xe5\xb7\x9e\xe5\xbe\xb7\xe8\x83\x9c\xe6\x9c\xba\xe6\x88\xbf', 'assetsNum': 'B50070100007003', 'responsibilityPerson': '\xe5\xbc\xa0\xe4\xb9\x8b\xe8\xaf\x9a', 'deviceModel': 'PowerEdge 1950', 'serviceTag': '729HH2X', 'ip': '172.16.20.163', 'hostname': 'hzshterm1.alibaba.com', 'manageIp': '172.31.58.223', 'cabinet': 'H05', 'buyTime': '2009-06-29', 'useState': '\xe4\xbd\xbf\xe7\x94\xa8\xe4\xb8\xad', 'memoryInfo': {'amount': 4, 'size': 8192}, 'cpuInfo': {'coreNum': 8, 'l2CacheSize': 6144, 'amount': 2, 'model': 'Intel(R) Xeon(R) CPU E5405 @ 2.00GHz', 'masterFrequency': 1995}, 'cabinetPositionNum': '', 'outGuaranteeTime': '', 'logicSite': '\xe4\xb8\xad\xe6\x96\x87\xe7\xab\x99'}
>>>
呵呵,ddata[‘data’]列表的0號元素是個字典。。
好,那我們查查key為idc的鍵值是多少
>>> ddata['data'][0]['idc'] //查看字典的方法!
'\xe6\x9d\xad\xe5\xb7\x9e\xe5\xbe\xb7\xe8\x83\x9c\xe6\x9c\xba\xe6\x88\xbf'
>>> print ddata['data'][0]['idc'] //呵呵,為什么print搞出來的是漢字呢?
杭州德勝機房
看到這里終于明白怎么解析json數(shù)據(jù)結(jié)構(gòu)了。。。
那就是”一層一層往下剝”
json是很方便的web數(shù)據(jù)格式,特別是用在ajax的數(shù)據(jù)處理上。許多Python的框架都是使用 simplejson 包來進(jìn)行處理。不過最近發(fā)現(xiàn)我有這樣的一個需求,比如我想把一個Python的數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)為javascript數(shù)據(jù)結(jié)構(gòu),也就是將python的數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)為json格式,然后用在模板中使用。如,我有一個模板,其中有javascript代碼:
<html>
<head>
<title>Title</title>
<script type="text/javascript">
s = {{=data}}
</script>
</head>
<body></body>
</html>
上面的data我可以這樣處理:
def index():
data = {'name':'limodou'};
return dict(data=simplejson.dumps(data))
這樣,通過simplejson.dumps可以將一個python的數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)為json格式,結(jié)果為:
{"name": "limodou"}
那么,它可以正確處理基本的數(shù)據(jù)類型。使用它,要求你傳入的數(shù)據(jù)應(yīng)該是基本的。但是這里可能有問題:
如何處理非基本類型數(shù)據(jù)。比如從數(shù)據(jù)庫中讀出的日期,一般都是datetime類型,它不是基本類型,直接傳入simplejson會報錯
如果我不希望是"limodou",而是limodou能不能呢?為什么會有這個需求,因為在我生成的js代碼中,有些可能是函數(shù)名,或執(zhí)行語句,因此不是字符串,不希望自動加引號
對于第一個問題,simplejson的主頁和代碼中都有例子,方法就是從JSONEncoder中派生子類,然后覆蓋default方法,對于特殊的類型進(jìn)行處理就可以了。
對于第二個,simplejson好象沒有什么支持,于是我做了擴(kuò)展:
import simplejson as sj
class ComplexEncoder(sj.JSONEncoder):
def __init__(self, classes=[], **kwargs):
sj.JSONEncoder.__init__(self, **kwargs)
if not isinstance(classes, (tuple, list)):
self.classes = [classes]
else:
self.classes = list(classes)
def _iterencode_default(self, o, markers=None):
for _cls in self.classes:
if isinstance(o, _cls):
return o()
newobj = self.default(o)
return self._iterencode(newobj, markers)
class R:
def __init__(self, obj):
self.obj = obj
def __call__(self):
return self.obj
def dumps(obj, classes=R):
return sj.dumps(obj, cls=ComplexEncoder, classes=classes)
我定義了一個自已的Encoder類,然后覆蓋了__init__()方法和_iterencode_default()方法。這樣允許對特殊類調(diào)用類的轉(zhuǎn)換方法,這樣ComplexEncoder就不會對特殊類進(jìn)行特殊處理了,其結(jié)果為特殊類的輸出。舉例:
>>> print dumps({'a':'dddddd', 'b':R('sssssss')})
{"a": "dddddd", "b": sssssss}
可以看出sssssss前后就沒有雙引號了。
《轉(zhuǎn)載嘿~》