json在python下的解析 這個事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."} { 屬性 : 值 , 屬性 : 值 , 屬性 : 值 },必須是大括號未外表,如果不是大括號,則把大括號外邊的內(nèi)容過濾掉。
2,數(shù)組是有順序的值的集合。一個數(shù)組開始于"[",結(jié)束于"]",值之間用","分隔。 [ {name:"Peggy",email:"peggy@gmail.com",homepage:"http://www."}, {name:"Peggy",email:"peggy@gmail.com",homepage:"http://www."}, {name:"Peggy",email:"peggy@gmail.com",homepage:"http://www."} ] 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./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":"杭州德勝機(jī)房","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搞出來的是漢字呢? 杭州德勝機(jī)房
看到這里終于明白怎么解析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)載嘿~》 |
|