本文實例分析了python對json的相關操作。分享給大家參考,具體如下:
什麼是json:
JSON(JavaScript Object Notation) 是一種輕量級的資料交換格式。易於人閱讀和編寫。同時也易於機器解析和生成。它是基於JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999的子集。 JSON採用完全獨立於語言的文字格式,但也使用了類似C語言家族的習慣(包括C, C++, C#, Java, JavaScript, Perl, Python等)。這些特性使JSON成為理想的資料交換語言。
JSON建構於兩種結構:
「名稱/值」對的集合(A collection of name/value pairs)。在不同的語言中,它被理解為物件(object),紀錄(record),結構(struct),字典(dictionary),哈希表(hash table),有鍵列表(keyed list),或關聯數組(associative array)。
值的有序列表(An ordered list of values)。在大部分語言中,它被理解為數組(array)。
這些都是常見的資料結構。事實上大部分現代電腦語言都以某種形式支援它們。這使得一種資料格式在同樣基於這些結構的程式語言之間交換成為可能。
json官方說明請參閱:http://json.org/
Python操作json的標準api函式庫參考:http://docs.python.org/library/json.html
對簡單資料類型的encoding 和decoding:
使用簡單的json.dumps方法對簡單資料類型進行編碼,例如:
import json obj = [[1,2,3],123,123.123,'abc',{'key1':(1,2,3),'key2':(4,5,6)}] encodedjson = json.dumps(obj) print repr(obj) print encodedjson
輸出:
[[1, 2, 3], 123, 123.123, 'abc', {'key2': (4, 5, 6), 'key1': (1, 2, 3)}] [[1, 2, 3], 123, 123.123, "abc", {"key2": [4, 5, 6], "key1": [1, 2, 3]}]
透過輸出的結果可以看出,簡單類型透過encode之後跟其原始的repr()輸出結果非常相似,但是有些資料類型進行了改變,例如上例中的元組則轉換為了列表。在json的編碼過程中,會存在從python原始類型轉化為json類型的過程,具體的轉換對照如下:
json.dumps()方法傳回了一個str對象encodedjson,我們接下來在對encodedjson進行decode,得到原始數據,需要使用的json.loads()函數:
decodejson = json.loads(encodedjson) print type(decodejson) print decodejson[4]['key1'] print decodejson
輸出:
<type 'list'> [1, 2, 3] [[1, 2, 3], 123, 123.123, u'abc', {u'key2': [4, 5, 6], u'key1': [1, 2, 3]}]
。例如,上例中‘abc'轉換為了unicode類型。從json到python的類型轉換對照如下:
json.dumps方法提供了很多好用的參數可供選擇,比較常用的有sort_keys(對dict物件進行排序,我們知道預設dict是無序存放的),separators,indent等參數。
排序功能讓儲存的資料更有利於觀察,也讓json輸出的物件比較,例如:
data1 = {'b':789,'c':456,'a':123} data2 = {'a':123,'b':789,'c':456} d1 = json.dumps(data1,sort_keys=True) d2 = json.dumps(data2) d3 = json.dumps(data2,sort_keys=True) print d1 print d2 print d3 print d1==d2 print d1==d3
輸出:
{"a": 123, "b": 789, "c": 456} {"a": 123, "c": 456, "b": 789} {"a": 123, "b": 789, "c": 456} False True
應該是一樣的,但是由於dict儲存的無序特性,造成兩者無法比較。因此兩者可以透過排序後的結果進行存儲就避免了數據比較不一致的情況發生,但是排序後再進行存儲,系統必定要多做一些事情,也一定會因此造成一定的性能消耗,所以適當排序是很重要的。
indent參數是縮排的意思,它可以讓資料儲存的格式變得更加優雅。
data1 = {'b':789,'c':456,'a':123} d1 = json.dumps(data1,sort_keys=True,indent=4) print d1
輸出:
{ "a": 123, "b": 789, "c": 456 }
輸出的資料被格式化之後,變得可讀性更強,但是卻是透過增加一些冗餘的空格。 json主要是作為一種資料通訊的格式存在的,而網路通訊是很在乎資料的大小的,無用的空格會佔據很多通訊頻寬,所以適當時候也要對資料進行壓縮。 separator參數可以起到這樣的作用,該參數傳遞是一個元組,包含分割物件的字串。
print 'DATA:', repr(data) print 'repr(data) :', len(repr(data)) print 'dumps(data) :', len(json.dumps(data)) print 'dumps(data, indent=2) :', len(json.dumps(data, indent=4)) print 'dumps(data, separators):', len(json.dumps(data, separators=(',',':')))
輸出:
DATA: {'a': 123, 'c': 456, 'b': 789} repr(data) : 30 dumps(data) : 30 dumps(data, indent=2) : 46 dumps(data, separators): 25
透過移除多餘的空格符,達到了壓縮資料的目的,而且效果還是明顯的。
另一個比較有用的dumps參數是skipkeys,預設為False。 dumps方法儲存dict物件時,key必須是str類型,如果出現了其他類型的話,那麼會產生TypeError異常,如果開啟該參數,設為True的話,則會比較優雅的過度。
data = {'b':789,'c':456,(1,2):123} print json.dumps(data,skipkeys=True)
輸出:
{"c": 456, "b": 789}
輸出:
class Person(object): def __init__(self,name,age): self.name = name self.age = age def __repr__(self): return 'Person Object name : %s , age : %d' % (self.name,self.age) if __name__ == '__main__': p = Person('Peter',22) print p
處理自己的資料類型
json
處理自己的資料類型jsonlson對像是很常用的。 🎜🎜首先,我們定義一個類別Person。 🎜''' Created on 2011-12-14 @author: Peter ''' import Person import json p = Person.Person('Peter',22) def object2dict(obj): #convert object to a dict d = {} d['__class__'] = obj.__class__.__name__ d['__module__'] = obj.__module__ d.update(obj.__dict__) return d def dict2object(d): #convert dict to object if'__class__' in d: class_name = d.pop('__class__') module_name = d.pop('__module__') module = __import__(module_name) class_ = getattr(module,class_name) args = dict((key.encode('ascii'), value) for key, value in d.items()) #get args inst = class_(**args) #create new instance else: inst = d return inst d = object2dict(p) print d #{'age': 22, '__module__': 'Person', '__class__': 'Person', 'name': 'Peter'} o = dict2object(d) print type(o),o #<class 'Person.Person'> Person Object name : Peter , age : 22 dump = json.dumps(p,default=object2dict) print dump #{"age": 22, "__module__": "Person", "__class__": "Person", "name": "Peter"} load = json.loads(dump,object_hook = dict2object) print load #Person Object name : Peter , age : 22
如果直接通过json.dumps方法对Person的实例进行处理的话,会报错,因为json无法支持这样的自动转化。通过上面所提到的json和python的类型转化对照表,可以发现,object类型是和dict相关联的,所以我们需要把我们自定义的类型转化为dict,然后再进行处理。这里,有两种方法可以使用。
方法一:自己写转化函数
''' Created on 2011-12-14 @author: Peter ''' import Person import json p = Person.Person('Peter',22) def object2dict(obj): #convert object to a dict d = {} d['__class__'] = obj.__class__.__name__ d['__module__'] = obj.__module__ d.update(obj.__dict__) return d def dict2object(d): #convert dict to object if'__class__' in d: class_name = d.pop('__class__') module_name = d.pop('__module__') module = __import__(module_name) class_ = getattr(module,class_name) args = dict((key.encode('ascii'), value) for key, value in d.items()) #get args inst = class_(**args) #create new instance else: inst = d return inst d = object2dict(p) print d #{'age': 22, '__module__': 'Person', '__class__': 'Person', 'name': 'Peter'} o = dict2object(d) print type(o),o #<class 'Person.Person'> Person Object name : Peter , age : 22 dump = json.dumps(p,default=object2dict) print dump #{"age": 22, "__module__": "Person", "__class__": "Person", "name": "Peter"} load = json.loads(dump,object_hook = dict2object) print load #Person Object name : Peter , age : 22
上面代码已经写的很清楚了,实质就是自定义object类型和dict类型进行转化。object2dict函数将对象模块名、类名以及__dict__存储在dict对象里,并返回。dict2object函数则是反解出模块名、类名、参数,创建新的对象并返回。在json.dumps 方法中增加default参数,该参数表示在转化过程中调用指定的函数,同样在decode过程中json.loads方法增加object_hook,指定转化函数。
方法二:继承JSONEncoder和JSONDecoder类,覆写相关方法
JSONEncoder类负责编码,主要是通过其default函数进行转化,我们可以override该方法。同理对于JSONDecoder。
''' Created on 2011-12-14 @author: Peter ''' import Person import json p = Person.Person('Peter',22) class MyEncoder(json.JSONEncoder): def default(self,obj): #convert object to a dict d = {} d['__class__'] = obj.__class__.__name__ d['__module__'] = obj.__module__ d.update(obj.__dict__) return d class MyDecoder(json.JSONDecoder): def __init__(self): json.JSONDecoder.__init__(self,object_hook=self.dict2object) def dict2object(self,d): #convert dict to object if'__class__' in d: class_name = d.pop('__class__') module_name = d.pop('__module__') module = __import__(module_name) class_ = getattr(module,class_name) args = dict((key.encode('ascii'), value) for key, value in d.items()) #get args inst = class_(**args) #create new instance else: inst = d return inst d = MyEncoder().encode(p) o = MyDecoder().decode(d) print d print type(o), o
对于JSONDecoder类方法,稍微有点不同,但是改写起来也不是很麻烦。看代码应该就比较清楚了。
希望本文所述对大家Python程序设计有所帮助。
更多python對json的相關操作實例詳解相关文章请关注PHP中文网!