参考:

概念

序列化(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:
import json
data = [{'a':"A",'b':(2,4),'c':3.0}] #list对象
print "DATA:",repr(data) data_string = json.dumps(data)
print "JSON:",data_string

输出:

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

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

json.loads方法处理简单数据类型的decoding(解码)转换
import json
data = [{'a':"A",'b':(2,4),'c':3.0}] #list对象 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'])

输出:

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

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

json的人文关怀

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

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)

输出:

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}

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

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)

输出:

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
}
]

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

import json

data = [ { 'a':'A', 'b':(2, 4), 'c':3.0 } ]
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=2))
print 'dumps(data, separators):', len(json.dumps(data, separators=(',',':')))

输出:

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

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

import json

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

try:
print json.dumps(data)
except (TypeError, ValueError) as err:
print 'ERROR:', err
print
print json.dumps(data, skipkeys=True)

输出:

ERROR: keys must be a string

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

让json支持自定义数据类型

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

import json  

class MyObj(object):
def __init__(self, s):
self.s = s
def __repr__(self):
return '<MyObj(%s)>' % self.s obj = .MyObj('helloworld') try:
print json.dumps(obj)
except TypeError, err:
print 'ERROR:', err #转换函数
def convert_to_builtin_type(obj):
print 'default(', repr(obj), ')'
# 把MyObj对象转换成dict类型的对象
d = { '__class__':obj.__class__.__name__,
'__module__':obj.__module__,
}
d.update(obj.__dict__)
return d print json.dumps(obj, default=convert_to_builtin_type)

输出:

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

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

#jsontest.py

import json

class MyObj(object):

    def __init__(self,s):
self.s = s def __repr__(self): return "<MyObj(%s)>" % self.s 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 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":"helloworld","__module__":"jsontest","__class__":"MyObj"}]' myobj_instance = json.loads(encoded_object,object_hook=dict_to_object)
print myobj_instance

输出:

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

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

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

import json

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

输出:

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(),而且预先会做些错误检查(比如非字符串作为dict的key),对于自定义的对象,我们只需从些JSONEncoder的default()方法,其实现方式与上面提及的函数convet_to_builtin_type()是类似的。

import json
import json_myobj class MyObj(object): def __init__(self,s):
self.s = s def __repr__(self):
return "<MyObj(%s)>" % self.s 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('helloworld')
print obj
print MyEncoder().encode(obj)

输出:

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

从json对Python对象的转换:

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
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": "helloworld", "__module__": "jsontest", "__class__": "MyObj"}]' myobj_instance = MyDecoder().decode(encoded_object)
print myobj_instance

输出:

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

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

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

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

输出:

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

类似的:

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

输出:

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

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

Python处理JSON(转)的更多相关文章

  1. Json概述以及python对json的相关操作

    JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.易于人阅读和编写.同时也易于机器解析和生成.它基于JavaScript Programming Langu ...

  2. 使用Python解析JSON数据的基本方法

    这篇文章主要介绍了使用Python解析JSON数据的基本方法,是Python入门学习中的基础知识,需要的朋友可以参考下:     ----------------------------------- ...

  3. python 序列化 json pickle

    python的pickle模块实现了基本的数据序列和反序列化.通过pickle模块的序列化操作我们能够将程序中运行的对象信息保存到文件中去,永久存储:通过pickle模块的反序列化操作,我们能够从文件 ...

  4. Python处理json格式的数据文件(一些坑、一些疑惑)

    这里主要说最近遇到的一个问题,不过目前只是换了一种思路先解决了,脑子里仍然有疑惑,只能怪自己太菜. 最近要把以前爬的数据用一下了,先简单的过滤一下,以前用scrapy存数据的时候为了省事也为了用一下它 ...

  5. Python处理JSON

    从开源中国的博客搬来,合并博客 一.JSON是什么? JSON是一种轻量级的数据交换格式 二.Python处理JSON的思维 其实很容易理解,无非是将数据编成JSON格式数据和吧JSON格式的数据解析 ...

  6. Python处理JSON数据

    python解析json时为了方便,我们首先安装json模块,这里选择demjson,官方网址是:http://deron.meranda.us/python/demjson/ 访问之后点击页面的的D ...

  7. Json概述以及python对json的相关操作(转)

    什么是json: JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.易于人阅读和编写.同时也易于机器解析和生成.它基于JavaScript Programm ...

  8. python 格式化 json输出

    利用python格式化json 字符串输出. $ echo '{"json":"obj"}' | python -m json.tool 利用python -m ...

  9. python解析json

    JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式. 引用 import json 编码:把一个Python对象编码转换成Json字符串 json.dumps ...

  10. python 解析json loads dumps

    认识 引用模块 重要函数 案例 排序 缩进参数 压缩 参考 认识 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.它基于JavaScript(Standa ...

随机推荐

  1. EJB实体Bean怎样和数据库中表关联?

    <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE ejb-jar PUBLIC "- ...

  2. java.lang.UnsatisfiedLinkError:no dll in java.library.path终极解决之道

     Java调用Dll时,会出现no dll in java.library.path异常,在Java Project中不常见,因为只要将Dll拷贝到system32目录下即可:         但若是 ...

  3. EasyUI 常规用法

    (function () {     // 获取树的路径,如 组织分类 > YHBH > 湖南省卫生厅 > 湖南省长沙市     var getBreadcrumbs = funct ...

  4. PHP自己定义安装

    ① 自己定义安装(先要在管理里停止apache服务,再卸载apache.再安装时不须要重新启动电脑) apache+php+mysql+phpmyadmin自行安装 我们建议大家,安装的时候安装到同一 ...

  5. insert-delete-getrandom-o1

    // 参考了下面一些讨论的解法 // https://discuss.leetcode.com/topic/53235/java-with-hashtable-arraylist/2 class Ra ...

  6. LigerUI之Grid使用详解(三)——字典数据展示

    一.问题概述 在开发web信息管理系统时,使用Web前端框架可以帮助我们快速搭建一组风格统一的界面效果,而且能够解决大多数浏览器兼容问题,提升开发效率.在关于LigerGrid的前两篇的内容里,给大家 ...

  7. cocos2dx游戏存储举例及其注意事项

    今天白白跟大家分享一下cocos2dx中游戏的存储及需要注意的事项 cocos2dx中自带了存储类:CCUserDefault ,倘若需要存储的数据量教大的话,建议使用数据库来存储 现在先给大家看一下 ...

  8. 申请红帽企业版Linux开发者订阅

    导读 注册成为开发者计划的成员现在可以得到一套免费的 Red Hat Enterprise Linux 许可证,RHEL 开发套件将为程序员提供一个构建企业应用的稳定发展平台.红帽开发订阅成员还可以免 ...

  9. Oracle服务启动顺序导致ORA-12514

    在window 上装了oracle11g,按照常规步骤安装完成后一切OK,如下图所示 C:\Users\Administrator>sqlplus /nolog SQL*Plus: Releas ...

  10. Wndows 主进程(Rundll32)已停止工作

        打开电脑,出现"windows 主进程(Rundll32)已停止工作",百度了一下,是文件损坏了.     下载一个新的文件,替换即可,若遇到权限问题,使用魔方工具中的设置 ...