python模組介紹-json

來源:互聯網
上載者:User

#參考資料:《The Python Standard Library by Example》

12.9 json 模組

JSON就是JavaScript Object Notation,這個模組完成了python對象和JSON字串的互相轉換。適用於Python的版本2.6和更高版本。
json模組提供了一個類似pickle的API,轉換記憶體中的Python對象為JavaScript對象符號(JSON)序列。JSON具有有許多語言的實現(尤其是JavaScript)。在AJAX應用中,廣泛的使用在Web伺服器和用戶端之間,

12.9.1 編碼解碼單一資料型別

JSON編碼識別python的如下類型:(string, unicode, int,float, list, tuple, and dict),比如:

import json

data = [ { 'a':'A', 'b':(2, 4), 'c':3.0 } ]

print 'DATA:', repr(data)

data_string = json.dumps(data)

print 'JSON:', data_string

執行結果:

$ python json_simple_types.py

DATA: [{'a': 'A', 'c': 3.0, 'b': (2, 4)}]

JSON: [{"a": "A", "c": 3.0, "b": [2, 4]}]

可以json的表示和python的repr差不多。這裡還要注意一點,字典中,把可變對象往後靠,是不是有什麼規則?

下例進行編碼再解碼:

import json

data = [ { ’a’:’A’, ’b’:(2, 4), ’c’:3.0 } ]

print ’DATA :’, data

data_string = json.dumps(data)

print ’ENCODED:’, data_string

decoded = json.loads(data_string)

print ’DECODED:’, decoded

print ’ORIGINAL:’, type(data[0][’b’])

print ’DECODED :’, type(decoded[0][’b’])

執行結果:

$ python json_simple_types_decode.py

DATA : [{’a’: ’A’, ’c’: 3.0, ’b’: (2, 4)}]

ENCODED: [{"a": "A", "c": 3.0, "b": [2, 4]}]

DECODED: [{’a’: ’A’, ’c’: 3.0, ’b’: [2, 4]}]

ORIGINAL: <type ’tuple’>

DECODED : <type ’list’>

這裡元組:(2, 4), 編碼再解碼之後,成了列表

12.9.2 編碼解碼單一資料型別

JSON跟pickle比的另一個好處是結果的可讀性比較好。pickle函數接受多個參數,以使輸出甚至更好。下例實現了排序功能:

import json

data = [ { ’a’:’A’, ’b’:(2, 4), ’c’:3.0 } ]

print ’DATA:’, repr(data)

unsorted = json.dumps(data)

print ’JSON:’, json.dumps(data)

print ’SORT:’, json.dumps(data, sort_keys=True)

first = json.dumps(data, sort_keys=True)

second = json.dumps(data, sort_keys=True)

print ’UNSORTED MATCH:’, unsorted == first

print ’SORTED MATCH :’, first == second

執行結果:

$ python json_sort_keys.py

DATA: [{’a’: ’A’, ’c’: 3.0, ’b’: (2, 4)}]

JSON: [{"a": "A", "c": 3.0, "b": [2, 4]}]

SORT: [{"a": "A", "b": [2, 4], "c": 3.0}]

UNSORTED MATCH: False

SORTED MATCH : True

對於多層嵌套的資料結構,還可以使用縮排:

import json

data = [ { ’a’:’A’, ’b’:(2, 4), ’c’:3.0 } ]

print ’DATA:’, repr(data)

print ’NORMAL:’, json.dumps(data, sort_keys=True)

print ’INDENT:’, json.dumps(data, sort_keys=True, indent=2)

執行結果:

$ python json_indent.py

DATA: [{’a’: ’A’, ’c’: 3.0, ’b’: (2, 4)}]

NORMAL: [{"a": "A", "b": [2, 4], "c": 3.0}]

INDENT: [

{

"a": "A",

"b": [

2,

4

],

"c": 3.0

}

]

當縮排不是負數的時候,和pprint的效果差不多。

像這樣詳細的輸出,因此它不適合在產品環境中使用。可以調整分離編碼輸出資料使它甚至超過了預設的緊湊。

import json

data = [ { ’a’:’A’, ’b’:(2, 4), ’c’:3.0 } ]

print ’DATA:’, repr(data)

print ’repr(data) :’, len(repr(data))

plain_dump = json.dumps(data)

print ’dumps(data) :’, len(plain_dump)

small_indent = json.dumps(data, indent=2)

print ’dumps(data, indent=2) :’, len(small_indent)

with_separators = json.dumps(data, separators=(’,’,’:’))

print ’dumps(data, separators):’, len(with_separators)

執行結果:

$ python json_compact_encoding.py

DATA: [{’a’: ’A’, ’c’: 3.0, ’b’: (2, 4)}]

repr(data) : 35

dumps(data) : 35

dumps(data, indent=2) : 76

dumps(data, separators): 29

12.9.3 編碼字典

JSON字典的索引值是字串。試圖編碼非字串作為索引值會產生一個例外,是TypeError 或者ValueError,取決於載入的模組是純Python版本載入還是C的加速版本,可以讓json忽略這些非字串的索引值。

import json

data = [ { ’a’:’A’, ’b’:(2, 4), ’c’:3.0, (’d’,):’D tuple’ } ]

print ’First attempt’

try:

print json.dumps(data)

except (TypeError, ValueError), err:

print ’ERROR:’, err

print

print ’Second attempt’

print json.dumps(data, skipkeys=True)

執行結果:

import json

data = [ { ’a’:’A’, ’b’:(2, 4), ’c’:3.0, (’d’,):’D tuple’ } ]

print ’First attempt’

try:

print json.dumps(data)

except (TypeError, ValueError), err:

print ’ERROR:’, err

print

print ’Second attempt’

print json.dumps(data, skipkeys=True)

12.9.4 自訂類型

到目前為止,所有的例子使用了Python的內建類型,因為這些都是由JSON本身支援的。如果需要編碼自訂類,有兩種方法。比如有如下對象:

class MyObj(object):

def __init__(self, s):

self.s = s

def __repr__(self):

return ’<MyObj(%s)>’ % self.s

編碼MyObj執行個體的最簡單的方法是定義一個函數來轉換未知類型為已知類型。它不需要做編碼,因此它應該只是轉換一個對象到另一個。

import json

import json_myobj

obj = json_myobj.MyObj(’instance value goes here’)

print ’First attempt’

try:

print json.dumps(obj)

except TypeError, err:

print ’ERROR:’, err

def convert_to_builtin_type(obj):

print ’default(’, repr(obj), ’)’

# Convert objects to a dictionary of their representation

d = { ’__class__’:obj.__class__.__name__,

’__module__’:obj.__module__,

}

d.update(obj.__dict__)

return d

print

print ’With default’

print json.dumps(obj, default=convert_to_builtin_type)

執行結果:

$ python json_dump_default.py

First attempt

ERROR: <MyObj(instance value goes here)> is not JSON serializable

With default

default( <MyObj(instance value goes here)> )

{"s": "instance value goes here", "__module__": "json_myobj",

"__class__": "MyObj"}

要解碼的結果並建立一個MyObj中()執行個體,使用object_hook參數到loads()綁上給解碼器,這樣的類可以從模組匯入並用來建立執行個體。

每個從輸入資料流中解碼的字典調用object_hook,把字典轉換為其他資料類型。Hook函數程式應該接收的對象而不是字典。

import json

def dict_to_object(d):

if '__class__' in d:

class_name = d.pop('__class__')

module_name = d.pop('__module__')

module = __import__(module_name)

print 'MODULE:', module.__name__

class_ = getattr(module, class_name)

print 'CLASS:', class_

args = dict( (key.encode('ascii'), value)

for key, value in d.items())

print 'INSTANCE ARGS:', args

inst = class_(**args)

else:

inst = d

return inst

encoded_object = '''

[{"s": "instance value goes here",

"__module__": "json_myobj", "__class__": "MyObj"}]

'''

myobj_instance = json.loads(encoded_object,

object_hook=dict_to_object)

print myobj_instance

運行結果:

$ python json_load_object_hook.py

MODULE: json_myobj

CLASS: <class ’json_myobj.MyObj’>

INSTANCE ARGS: {’s’: ’instance value goes here’}

[<MyObj(instance value goes here)>]

由於JSON字串值轉換為Unicode對象,他們需要重新編碼
為ASCII字串,才可以作為類構造的關鍵字參數。

12.9.5 編碼和解碼類

json模組提供了編碼和解碼類。使用這些類可訪問額外的API來定製自己的行為。

JSONEncoder使用了一個可迭代介面編碼資料的“chunks”,從而在不需要在記憶體表示整個資料,更加容易寫檔案或網路socket。

import json

encoder = json.JSONEncoder()

data = [ { ’a’:’A’, ’b’:(2, 4), ’c’:3.0 } ]

for part in encoder.iterencode(data):

print ’PART:’, part

執行結果:

$ python json_encoder_iterable.py

PART: [

PART: {

PART: "a"

PART: :

PART: "A"

PART: ,

PART: "c"

PART: :

PART: 3.0

PART: ,

PART: "b"

PART: :

PART: [2

PART: , 4

PART: ]

PART: }

PART: ]

encode()方法基本上等同於’ ’.join(encoder.iterencode()),不過事先多了一些錯誤檢查。要編碼的任意對象,使用前面類似convert_to_builtin_type的方法重載default()。

import json

import json_myobj

class MyEncoder(json.JSONEncoder):

def default(self, obj):

print 'default(', repr(obj), ')'

# Convert objects to a dictionary of their representation

d = { '__class__':obj.__class__.__name__,

'__module__':obj.__module__,

}

d.update(obj.__dict__)

return d

obj = json_myobj.MyObj('internal data')

print obj

print MyEncoder().encode(obj)

執行結果:

$ python json_encoder_default.py

<MyObj(internal data)>

default( <MyObj(internal data)> )

{"s": "internal data", "__module__": "json_myobj", "__class__":

"MyObj"}

解碼文本,然後轉換對象到字典,比之前的實現要稍微多一點步驟

import json

class MyDecoder(json.JSONDecoder):

def __init__(self):

json.JSONDecoder.__init__(self,

object_hook=self.dict_to_object)

def dict_to_object(self, d):

if ’__class__’ in d:

class_name = d.pop(’__class__’)

module_name = d.pop(’__module__’)

module = __import__(module_name)

print ’MODULE:’, module.__name__

class_ = getattr(module, class_name)

print ’CLASS:’, class_

args = dict( (key.encode(’ascii’), value)

for key, value in d.items())

print ’INSTANCE ARGS:’, args

inst = class_(**args)

else:

inst = d

return inst

encoded_object = ’’’

[{"s": "instance value goes here",

"__module__": "json_myobj", "__class__": "MyObj"}]

’’’

myobj_instance = MyDecoder().decode(encoded_object)

print myobj_instance。

執行結果:

$ python json_decoder_object_hook.py

MODULE: json_myobj

CLASS: <class ’json_myobj.MyObj’>

INSTANCE ARGS: {’s’: ’instance value goes here’}

[<MyObj(instance value goes here)>]

12.9.6 流和檔案

函數load() 和dump()用於讀寫檔案類似的對象。

import json

from StringIO import StringIO

data = [ { ’a’:’A’, ’b’:(2, 4), ’c’:3.0 } ]

f = StringIO()

json.dump(data, f)

print f.getvalue()

執行結果:

$ python json_dump_file.py

[{"a": "A", "c": 3.0, "b": [2, 4]}]

雖然不最佳化為一次唯讀取的部分資料,load()提供了從流輸入產生對象邏輯。

import json

from StringIO import StringIO

f = StringIO(’[{"a": "A", "c": 3.0, "b": [2, 4]}]’)

print json.load(f)

執行結果:

$ python json_load_file.py

[{’a’: ’A’, ’c’: 3.0, ’b’: [2, 4]}]

12.9.7 混合資料流

JSONDecoder包括raw_decode(),這個方法可以解碼包含更多資料的資料結構
,比如帶後續文本的JSON資料。傳回值是解碼後的輸入資料和索引。

(obj, end, remaining)

encoded_object = ’[{"a": "A", "c": 3.0, "b": [2, 4]}]’

extra_text = ’This text is not JSON.’

print ’JSON first:’

data = ’ ’.join([encoded_object, extra_text])

obj, end, remaining = get_decoded_and_remainder(data)

print ’Object :’, obj

print ’End of parsed input :’, end

print ’Remaining text :’, repr(remaining)

print

print ’JSON embedded:’

try:

data = ’ ’.join([extra_text, encoded_object, extra_text])

obj, end, remaining = get_decoded_and_remainder(data)

except ValueError, err:

print ’ERROR:’, err

執行結果:

$ python json_mixed_data.py

JSON first:

Object : [{’a’: ’A’, ’c’: 3.0, ’b’: [2, 4]}]

End of parsed input : 35

Remaining text : ’ This text is not JSON.’

JSON embedded:

ERROR: No JSON object could be decoded

注意,對象必須在輸入的開始

其他參考資料:

json (http://docs.python.org/library/json.html)

JavaScript Object Notation (http://json.org/)

simplejson (http://code.google.com/p/simplejson/)

simplejson (http://code.google.com/p/simplejson/)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.