概念

序列化(Serialization):将对象的状态信息转换为可以存储或可以通过网络传输的过程,传输的格式可以是JSON、XML等。

反序列化:就是从存储区域(JSON,XML)读取反序列化对象的状态,重新创建该对象。

JSON(JavaScript Object Notation):一种轻量级数据交换格式,相对于XML而言更简单,也易于阅读和编写,机器也方便解析和生成,Json是JavaScript中的一个子集。

Python2.6开始加入了JSON模块,无需另外下载,Python的Json模块序列化与反序列化的过程分别是 encoding和 decoding

encoding:把一个Python对象编码转换成Json字符串
decoding:把Json格式字符串解码转换成Python对象
对于简单数据类型(string、unicode、int、float、list、tuple、dict),可以直接处理。

json.dumps方法对简单数据类型encoding:
  1. import json
  2. data = [{'a':"A",'b':(2,4),'c':3.0}] #list对象
  3. print "DATA:",repr(data)
  4. data_string = json.dumps(data)
  5. print "JSON:",data_string

输出:

  1. DATA: [{'a':'A','c':3.0,'b':(2,4)}] #python的dict类型的数据是没有顺序存储的
  2. JSON: [{"a":"A","c":3.0,"b":[2,4]}]

JSON的输出结果与DATA很相似,除了一些微妙的变化,如python的元组类型变成了Json的数组,Python到Json的编码转换规则是: 

json.loads方法处理简单数据类型的decoding(解码)转换
  1. import json
  2. data = [{'a':"A",'b':(2,4),'c':3.0}] #list对象
  3. data_string = json.dumps(data)
  4. print "ENCODED:",data_string
  5. decoded = json.loads(data_string)
  6. print "DECODED:",decoded
  7. print "ORIGINAL:",type(data[0]['b'])
  8. print "DECODED:",type(decoded[0]['b'])

输出:

  1. ENCODED: [{"a": "A", "c": 3.0, "b": [2, 4]}]
  2. DECODED: [{u'a': u'A', u'c': 3.0, u'b': [2, 4]}]
  3. ORIGINAL: <type 'tuple'>
  4. DECODED: <type 'list'>

解码过程中,json的数组最终转换成了python的list,而不是最初的tuple类型,Json到Python的解码规则是: 

json的人文关怀

编码后的json格式字符串紧凑的输出,而且也没有顺序,因此dumps方法提供了一些可选的参数,让输出的格式提高可读性,如sort_keys是告诉编码器按照字典排序(a到z)输出。

  1. import json
  2. data = [ { 'a':'A', 'b':(2, 4), 'c':3.0 } ]
  3. print 'DATA:', repr(data)
  4. unsorted = json.dumps(data)
  5. print 'JSON:', json.dumps(data)
  6. print 'SORT:', json.dumps(data, sort_keys=True)

输出:

  1. DATA: [{'a': 'A', 'c': 3.0, 'b': (2, 4)}]
  2. JSON: [{"a": "A", "c": 3.0, "b": [2, 4]}]
  3. SORT: [{"a": "A", "b": [2, 4], "c": 3.0}

indent参数根据数据格式缩进显示,读起来更加清晰:

  1. import json
  2. data = [ { 'a':'A', 'b':(2, 4), 'c':3.0 } ]
  3. print 'DATA:', repr(data)
  4. print 'NORMAL:', json.dumps(data, sort_keys=True)
  5. print 'INDENT:', json.dumps(data, sort_keys=True, indent=2)

输出:

  1. DATA: [{'a': 'A', 'c': 3.0, 'b': (2, 4)}]
  2. NORMAL: [{"a": "A", "b": [2, 4], "c": 3.0}]
  3. INDENT: [
  4. {
  5. "a": "A",
  6. "b": [
  7. 2,
  8. 4
  9. ],
  10. "c": 3.0
  11. }
  12. ]

separators参数的作用是去掉,,:后面的空格,从上面的输出结果都能看到", :"后面都有个空格,这都是为了美化输出结果的作用,但是在我们传输数据的过程中,越精简越好,冗余的东西全部去掉,因此就可以加上separators参数:

  1. import json
  2. data = [ { 'a':'A', 'b':(2, 4), 'c':3.0 } ]
  3. print 'DATA:', repr(data)
  4. print 'repr(data) :', len(repr(data))
  5. print 'dumps(data) :', len(json.dumps(data))
  6. print 'dumps(data, indent=2) :', len(json.dumps(data, indent=2))
  7. print 'dumps(data, separators):', len(json.dumps(data, separators=(',',':')))

输出:

  1. DATA: [{'a': 'A', 'c': 3.0, 'b': (2, 4)}]
  2. repr(data) : 35
  3. dumps(data) : 35
  4. dumps(data, indent=2) : 76
  5. dumps(data, separators): 29

skipkeys参数,在encoding过程中,dict对象的key只可以是string对象,如果是其他类型,那么在编码过程中就会抛出ValueError的异常。skipkeys可以跳过那些非string对象当作key的处理.

  1. import json
  2. data= [ { 'a':'A', 'b':(2, 4), 'c':3.0, ('d',):'D tuple' } ]
  3. try:
  4. print json.dumps(data)
  5. except (TypeError, ValueError) as err:
  6. print 'ERROR:', err
  7. print
  8. print json.dumps(data, skipkeys=True)

输出:

  1. ERROR: keys must be a string
  2. [{"a": "A", "c": 3.0, "b": [2, 4]}]

让json支持自定义数据类型

以上例子都是基于python的built-in类型的,对于自定义类型的数据结构,json模块默认是没法处理的,会抛出异常:TypeError xx is not JSON serializable,此时你需要自定义一个转换函数:

  1. import json
  2. class MyObj(object):
  3. def __init__(self, s):
  4. self.s = s
  5. def __repr__(self):
  6. return '<MyObj(%s)>' % self.s
  7. obj = .MyObj('helloworld')
  8. try:
  9. print json.dumps(obj)
  10. except TypeError, err:
  11. print 'ERROR:', err
  12. #转换函数
  13. def convert_to_builtin_type(obj):
  14. print 'default(', repr(obj), ')'
  15. # 把MyObj对象转换成dict类型的对象
  16. d = { '__class__':obj.__class__.__name__,
  17. '__module__':obj.__module__,
  18. }
  19. d.update(obj.__dict__)
  20. return d
  21. print json.dumps(obj, default=convert_to_builtin_type)

输出:

  1. ERROR: <MyObj(helloworld)> is not JSON serializable
  2. default( <MyObj(helloworld)> )
  3. {"s": "hellworld", "__module__": "MyObj", "__class__": "__main__"}
  4. #注意:这里的class和module根据你代码的所在文件位置不同而不同

相反,如果要把json decode 成python对象,同样也需要自定转换函数,传递给json.loads方法的object_hook参数:

  1. #jsontest.py
  2. import json
  3. class MyObj(object):
  4. def __init__(self,s):
  5. self.s = s
  6. def __repr__(self):
  7. return "<MyObj(%s)>" % self.s
  8. def dict_to_object(d):
  9. if '__class__' in d:
  10. class_name = d.pop('__class__')
  11. module_name = d.pop('__module__')
  12. module = __import__(module_name)
  13. print "MODULE:",module
  14. class_ = getattr(module,class_name)
  15. print "CLASS",class_
  16. args = dict((key.encode('ascii'),value) for key,value in d.items())
  17. print 'INSTANCE ARGS:',args
  18. inst = class_(**args)
  19. else:
  20. inst = d
  21. return inst
  22. encoded_object = '[{"s":"helloworld","__module__":"jsontest","__class__":"MyObj"}]'
  23. myobj_instance = json.loads(encoded_object,object_hook=dict_to_object)
  24. print myobj_instance

输出:

  1. MODULE: <module 'jsontest' from 'E:\Users\liuzhijun\workspace\python\jsontest.py'>
  2. CLASS <class 'jsontest.MyObj'>
  3. INSTANCE ARGS: {'s': u'helloworld'}
  4. [<MyObj(helloworld)>]
  5. MODULE: <module 'jsontest' from 'E:\Users\liuzhijun\workspace\python\jsontest.py'>
  6. CLASS <class 'jsontest.MyObj'>
  7. INSTANCE ARGS: {'s': u'helloworld'}
  8. [<MyObj(helloworld)>]

使用Encoder与Decoder类实现json编码的转换

JSONEncoder有一个迭代接口iterencode(data),返回一系列编码的数据,他的好处是可以方便的把逐个数据写到文件或网络流中,而不需要一次性就把数据读入内存.

  1. import json
  2. encoder = json.JSONEncoder()
  3. data = [ { 'a':'A', 'b':(2, 4), 'c':3.0 } ]
  4. for part in encoder.iterencode(data):
  5. print 'PART:', part

输出:

  1. PART: [
  2. PART: {
  3. PART: "a"
  4. PART: :
  5. PART: "A"
  6. PART: ,
  7. PART: "c"
  8. PART: :
  9. PART: 3.0
  10. PART: ,
  11. PART: "b"
  12. PART: :
  13. PART: [2
  14. PART: , 4
  15. PART: ]
  16. PART: }
  17. PART: ]

encode方法等价于''.join(encoder.iterencode(),而且预先会做些错误检查(比如非字符串作为dict的key),对于自定义的对象,我们只需从些JSONEncoder的default()方法,其实现方式与上面提及的函数convet_to_builtin_type()是类似的。

  1. import json
  2. import json_myobj
  3. class MyObj(object):
  4. def __init__(self,s):
  5. self.s = s
  6. def __repr__(self):
  7. return "<MyObj(%s)>" % self.s
  8. class MyEncoder(json.JSONEncoder):
  9. def default(self, obj):
  10. print 'default(', repr(obj), ')'
  11. # Convert objects to a dictionary of their representation
  12. d = { '__class__':obj.__class__.__name__,
  13. '__module__':obj.__module__,
  14. }
  15. d.update(obj.__dict__)
  16. return d
  17. obj = json_myobj.MyObj('helloworld')
  18. print obj
  19. print MyEncoder().encode(obj)

输出:

  1. <MyObj(internal data)>
  2. default( <MyObj(internal data)> )
  3. {"s": "helloworld", "__module__": "Myobj", "__class__": "MyObj"}

从json对Python对象的转换:

  1. class MyDecoder(json.JSONDecoder):
  2. def __init__(self):
  3. json.JSONDecoder.__init__(self, object_hook=self.dict_to_object)
  4. def dict_to_object(self, d):
  5. if '__class__' in d:
  6. class_name = d.pop('__class__')
  7. module_name = d.pop('__module__')
  8. module = __import__(module_name)
  9. print 'MODULE:', module
  10. class_ = getattr(module, class_name)
  11. print 'CLASS:', class_
  12. args = dict( (key.encode('ascii'), value) for key, value in d.items())
  13. print 'INSTANCE ARGS:', args
  14. inst = class_(**args)
  15. else:
  16. inst = d
  17. return inst
  18. encoded_object = '[{"s": "helloworld", "__module__": "jsontest", "__class__": "MyObj"}]'
  19. myobj_instance = MyDecoder().decode(encoded_object)
  20. print myobj_instance

输出:

  1. MODULE: <module 'jsontest' from 'E:\Users\liuzhijun\workspace\python\jsontest.py'>
  2. CLASS: <class 'jsontest.MyObj'>
  3. INSTANCE ARGS: {'s': u'helloworld'}
  4. [<MyObj(helloworld)>]

json格式字符串写入到文件流中

上面的例子都是在内存中操作的,如果对于大数据,把他编码到一个类文件(file-like)中更合适,load()dump()方法就可以实现这样的功能。

  1. import json
  2. import tempfile
  3. data = [ { 'a':'A', 'b':(2, 4), 'c':3.0 } ]
  4. f = tempfile.NamedTemporaryFile(mode='w+')
  5. json.dump(data, f)
  6. f.flush()
  7. print open(f.name, 'r').read()

输出:

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

类似的:

  1. import json
  2. import tempfile
  3. f = tempfile.NamedTemporaryFile(mode='w+')
  4. f.write('[{"a": "A", "c": 3.0, "b": [2, 4]}]')
  5. f.flush()
  6. f.seek(0)
  7. print json.load(f)

输出:


  1. [{u'a': u'A', u'c': 3.0, u'b': [2, 4]}]
  2. 参考:

http://docs.python.org/2/library/json.html
http://www.cnblogs.com/coser/archive/2011/12/14/2287739.html
http://pymotw.com/2/json/

  1.  

python JSON处理的更多相关文章

  1. python json基础学习01

    # -*- coding: utf-8 -*- # python:2.x __author__ = 'Administrator' import json #全称(javascript object  ...

  2. python json数据的转换

    1  Python数据转json字符串 import json json_str = json.dumps(py_data) 参数解析: json_str = json.dumps(py_data,s ...

  3. python大法好——python json

    Python JSON 本章节我们将为大家介绍如何使用 Python 语言来编码和解码 JSON 对象. JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式, ...

  4. Python json 读取 json 文件并转为 dict

    Python json 读取 json 文件并转为 dict 在 D 盘 新建 test.json: { "test": "测试\n换行", "dic ...

  5. Python Json & Pickle模块

    用于序列化的两个模块 Json,用于字符串 和 python数据类型间进行转换 Pickle,用于python特有的类型 和 python的数据类型间进行转换 Json模块提供了四个功能:dumps. ...

  6. Python: json模块实例详解

    ref:https://www.jianshu.com/p/e29611244810 https://www.cnblogs.com/qq78292959/p/3467937.html https:/ ...

  7. python学习笔记——python JSON

    JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,易于人阅读和编写. 1.JSON 函数 使用 JSON 函数需要导入 json 库:import json ...

  8. Python json使用

    转自:https://www.cnblogs.com/wangyayun/p/6699184.html?utm_source=tuicool&utm_medium=referral 使用Pyt ...

  9. Python -- Json 数据编码及解析

    Python  --  Json  数据编码及解析 Json 简单介绍 JSON: JavaScript Object Notation(JavaScript 对象表示法) JSON 是存储和交换文本 ...

  10. python json.dumps() 中文乱码问题

    python json.dumps() 中文乱码问题   python 输出一串中文字符,在控制台上(控制台使用UTF-8编码)通过print 可以正常显示,但是写入到文件中之后,中文字符都输出成as ...

随机推荐

  1. iOS之UIview动画

    一.UIView动画(首尾) 1.简单说明 UIKit直接将动画集成到UIView类中,当内部的一些属性发生改变时,UIView将为这些改变提供动画支持 执行动画所需要的工作由UIView类自动完成, ...

  2. C# ADO.NET参数查询

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  3. Canvas 笔记(持续更新中)

    1.从线条开始 HTML <canvas id="canvas"></canvas> Javascript var canvas=document.getE ...

  4. ios ReactiveViewModel

    项目中使用 ReactiveCocoa 一般都会嵌入ReactiveViewModel 或者 ReactiveCocoaLayout 联合处理UI.网络.动画.布局.窗口切换等,组合使用时威力惊人. ...

  5. O-C相关05:方法的封装.

    前言:在 OC 中进行封装, 就是实现设置实例变量和获取实例变量数据的方法, 常常称为 setter 方法和 getter 方法. 或称为 get set 读写器. 1,setter 方法 sette ...

  6. Fxcop 初体验

    代码质量对于软件项目的成败很重要,这点我想大家都明白.那么在一个软件团队中如何保证代码质量呢?对于这个问题不同的人可能会有不同的答案,对于我而言我觉得做好两点代码质量基本就可以保证了: 1.代码规范( ...

  7. java web-----DAO设计模式(数据库访问)

    一,DAO设计模式用于 j2ee 的数据层访问,包括五部分, 数据库连接类(包含数据库的连接与关闭操作的一个类), VO类(私有变量与数据库表格对应,接收数据库中表格各字段内容), DAO接口类(包含 ...

  8. java之表达式陷阱

    String str1 = "Hello Java的长度:10"; String str2 = "Hello Java的长度:10";  String str3 ...

  9. java数据同步陷阱

    并发,我的理解就是同时运行多个程序.同时,难以避免的就是数据的同步问题,如果数据同步问题处理不好就很容易造成程序出现bug,当然,对于其造成的危害,不加详述. 首先,来看一个简单的例子,当然,这个例子 ...

  10. ZOJ 3471 Most Powerful(DP + 状态压缩)

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4257 题目大意:有 n(2<=n<=10) 个原子,每两 ...