深入解析Python编程中JSON模块的使用


Posted in Python onOctober 15, 2015

JSON编码支持的基本数据类型为 None , bool , int , float 和 str , 以及包含这些类型数据的lists,tuples和dictionaries。 对于dictionaries,keys需要是字符串类型(字典中任何非字符串类型的key在编码时会先转换为字符串)。 为了遵循JSON规范,你应该只编码Python的lists和dictionaries。 而且,在web应用程序中,顶层对象被编码为一个字典是一个标准做法。

JSON编码的格式对于Python语法而已几乎是完全一样的,除了一些小的差异之外。 比如,True会被映射为true,False被映射为false,而None会被映射为null。 下面是一个例子,演示了编码后的字符串效果:

>>> json.dumps(False)
'false'
>>> d = {'a': True,
...   'b': 'Hello',
...   'c': None}
>>> json.dumps(d)
'{"b": "Hello", "c": null, "a": true}'
>>>

如果你试着去检查JSON解码后的数据,你通常很难通过简单的打印来确定它的结构, 特别是当数据的嵌套结构层次很深或者包含大量的字段时。 为了解决这个问题,可以考虑使用pprint模块的 pprint() 函数来代替普通的 print() 函数。 它会按照key的字母顺序并以一种更加美观的方式输出。 下面是一个演示如何漂亮的打印输出Twitter上搜索结果的例子:

>>> from urllib.request import urlopen
>>> import json
>>> u = urlopen('http://search.twitter.com/search.json?q=python&rpp=5')
>>> resp = json.loads(u.read().decode('utf-8'))
>>> from pprint import pprint
>>> pprint(resp)
{'completed_in': 0.074,
'max_id': 264043230692245504,
'max_id_str': '264043230692245504',
'next_page': '?page=2&max_id=264043230692245504&q=python&rpp=5',
'page': 1,
'query': 'python',
'refresh_url': '?since_id=264043230692245504&q=python',
'results': [{'created_at': 'Thu, 01 Nov 2012 16:36:26 +0000',
      'from_user': ...
      },
      {'created_at': 'Thu, 01 Nov 2012 16:36:14 +0000',
      'from_user': ...
      },
      {'created_at': 'Thu, 01 Nov 2012 16:36:13 +0000',
      'from_user': ...
      },
      {'created_at': 'Thu, 01 Nov 2012 16:36:07 +0000',
      'from_user': ...
      }
      {'created_at': 'Thu, 01 Nov 2012 16:36:04 +0000',
      'from_user': ...
      }],
'results_per_page': 5,
'since_id': 0,
'since_id_str': '0'}
>>>

一般来讲,JSON解码会根据提供的数据创建dicts或lists。 如果你想要创建其他类型的对象,可以给 json.loads() 传递object_pairs_hook或object_hook参数。 例如,下面是演示如何解码JSON数据并在一个OrderedDict中保留其顺序的例子:

>>> s = '{"name": "ACME", "shares": 50, "price": 490.1}'
>>> from collections import OrderedDict
>>> data = json.loads(s, object_pairs_hook=OrderedDict)
>>> data
OrderedDict([('name', 'ACME'), ('shares', 50), ('price', 490.1)])
>>>

下面是如何将一个JSON字典转换为一个Python对象例子:

>>> class JSONObject:
...   def __init__(self, d):
...     self.__dict__ = d
...
>>>
>>> data = json.loads(s, object_hook=JSONObject)
>>> data.name
'ACME'
>>> data.shares
50
>>> data.price
490.1
>>>

最后一个例子中,JSON解码后的字典作为一个单个参数传递给 __init__() 。 然后,你就可以随心所欲的使用它了,比如作为一个实例字典来直接使用它。

在编码JSON的时候,还有一些选项很有用。 如果你想获得漂亮的格式化字符串后输出,可以使用 json.dumps() 的indent参数。 它会使得输出和pprint()函数效果类似。比如:

>>> print(json.dumps(data))
{"price": 542.23, "name": "ACME", "shares": 100}
>>> print(json.dumps(data, indent=4))
{
  "price": 542.23,
  "name": "ACME",
  "shares": 100
}
>>>

对象实例通常并不是JSON可序列化的。例如:

>>> class Point:
...   def __init__(self, x, y):
...     self.x = x
...     self.y = y
...
>>> p = Point(2, 3)
>>> json.dumps(p)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.3/json/__init__.py", line 226, in dumps
    return _default_encoder.encode(obj)
  File "/usr/local/lib/python3.3/json/encoder.py", line 187, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/local/lib/python3.3/json/encoder.py", line 245, in iterencode
    return _iterencode(o, 0)
  File "/usr/local/lib/python3.3/json/encoder.py", line 169, in default
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: <__main__.Point object at 0x1006f2650> is not JSON serializable
>>>

如果你想序列化对象实例,你可以提供一个函数,它的输入是一个实例,返回一个可序列化的字典。例如:

def serialize_instance(obj):
  d = { '__classname__' : type(obj).__name__ }
  d.update(vars(obj))
  return d

如果你想反过来获取这个实例,可以这样做:

# Dictionary mapping names to known classes
classes = {
  'Point' : Point
}

def unserialize_object(d):
  clsname = d.pop('__classname__', None)
  if clsname:
    cls = classes[clsname]
    obj = cls.__new__(cls) # Make instance without calling __init__
    for key, value in d.items():
      setattr(obj, key, value)
      return obj
  else:
    return d

下面是如何使用这些函数的例子:

>>> p = Point(2,3)
>>> s = json.dumps(p, default=serialize_instance)
>>> s
'{"__classname__": "Point", "y": 3, "x": 2}'
>>> a = json.loads(s, object_hook=unserialize_object)
>>> a
<__main__.Point object at 0x1017577d0>
>>> a.x
2
>>> a.y
3
>>>

json 模块还有很多其他选项来控制更低级别的数字、特殊值如NaN等的解析。 可以参考官方文档获取更多细节。

Python 相关文章推荐
python文件读写并使用mysql批量插入示例分享(python操作mysql)
Feb 17 Python
Python 包含汉字的文件读写之每行末尾加上特定字符
Dec 12 Python
Django中redis的使用方法(包括安装、配置、启动)
Feb 21 Python
python3爬取各类天气信息
Feb 24 Python
pandas 实现将重复表格去重,并重新转换为表格的方法
Apr 18 Python
python numpy 部分排序 寻找最大的前几个数的方法
Jun 27 Python
使用python的pandas库读取csv文件保存至mysql数据库
Aug 20 Python
Python提取频域特征知识点浅析
Mar 04 Python
Python字符串匹配之6种方法的使用详解
Apr 08 Python
如何安装2019Pycharm最新版本(详细教程)
Sep 26 Python
使用pycharm和pylint检查python代码规范操作
Jun 09 Python
浅谈Python numpy创建空数组的问题
May 25 Python
使用Python解析JSON数据的基本方法
Oct 15 #Python
深入讲解Python编程中的字符串
Oct 14 #Python
Python编程中字符串和列表的基本知识讲解
Oct 14 #Python
Python循环语句之break与continue的用法
Oct 14 #Python
Python编程中的for循环语句学习教程
Oct 14 #Python
在Python的while循环中使用else以及循环嵌套的用法
Oct 14 #Python
解析Python中while true的使用
Oct 13 #Python
You might like
php设计模式 Builder(建造者模式)
2011/06/26 PHP
PHP在获取指定目录下的目录,在获取的目录下面再创建文件,多平台
2011/08/03 PHP
php遍历目录方法小结
2015/03/10 PHP
支付宝服务窗API接口开发php版本
2016/07/20 PHP
PHP ElasticSearch做搜索实例讲解
2020/02/05 PHP
PHP 对象接口简单实现方法示例
2020/04/13 PHP
js获取窗口相对于屏幕左边和上边的位置坐标
2014/05/15 Javascript
javascript中CheckBox全选终极方案
2015/05/20 Javascript
漂亮! js实现颜色渐变效果
2016/08/12 Javascript
D3.js实现折线图的方法详解
2016/09/21 Javascript
利用jquery正则表达式在页面验证url网址输入是否正确
2017/04/04 jQuery
JavaWeb表单及时验证功能在输入后立即验证(含用户类型,性别,爱好...的验证)
2017/06/09 Javascript
浅谈webpack下的AOP式无侵入注入
2017/11/12 Javascript
详解使用Next.js构建服务端渲染应用
2018/07/10 Javascript
vue动画打包后失效问题的解决方法
2018/09/18 Javascript
js中数组常用方法总结(推荐)
2019/04/09 Javascript
Vue.js中该如何自己维护路由跳转记录
2019/05/19 Javascript
js实现数字从零慢慢增加到指定数字示例
2019/11/07 Javascript
VUE子组件向父组件传值详解(含传多值及添加额外参数场景)
2020/09/01 Javascript
python正则表达式爬取猫眼电影top100
2018/02/24 Python
详解Django定时任务模块设计与实践
2019/07/24 Python
python3实现单目标粒子群算法
2019/11/14 Python
TensorFlow内存管理bfc算法实例
2020/02/03 Python
python pyecharts 实现一个文件绘制多张图
2020/05/13 Python
Keras之自定义损失(loss)函数用法说明
2020/06/10 Python
Python调用REST API接口的几种方式汇总
2020/10/19 Python
详解基于 Canvas 手撸一个六边形能力图
2019/09/02 HTML / CSS
岗位职责风险防控
2014/02/18 职场文书
幼儿园师德演讲稿
2014/05/06 职场文书
迎新晚会策划方案
2014/06/13 职场文书
房屋出租协议书范本(标准版)
2014/09/24 职场文书
党的群众路线教育实践活动心得体会(乡镇)
2014/11/03 职场文书
先进工作者事迹材料
2014/12/23 职场文书
小马王观后感
2015/06/11 职场文书
Django展示可视化图表的多种方式
2021/04/08 Python
利用Python读取微信朋友圈的多种方法总结
2021/08/23 Python