Python如何读取、写入JSON数据


Posted in Python onJuly 28, 2020

问题

你想读写JSON(JavaScript Object Notation)编码格式的数据。

解决方案

json 模块提供了一种很简单的方式来编码和解码JSON数据。其中两个主要的函数是 json.dumps() 和 json.loads() ,要比其他序列化函数库如pickle的接口少得多。下面演示如何将一个Python数据结构转换为JSON:

import json

data = {
 'name' : 'ACME',
 'shares' : 100,
 'price' : 542.23
}

json_str = json.dumps(data)

下面演示如何将一个JSON编码的字符串转换回一个Python数据结构:

data = json.loads(json_str)

如果你要处理的是文件而不是字符串,你可以使用json.dump()和json.load()来编码和解码JSON数据。例如:

# Writing JSON data
with open('data.json', 'w') as f:
 json.dump(data, f)

# Reading data back
with open('data.json', 'r') as f:
 data = json.load(f)

讨论

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如何读取、写入JSON数据的详细内容,更多关于Python读写json数据的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
从CentOS安装完成到生成词云python的实例
Dec 01 Python
python学生管理系统代码实现
Apr 05 Python
python使用tornado实现简单爬虫
Jul 28 Python
Python中利用aiohttp制作异步爬虫及简单应用
Nov 29 Python
Python实现的调用C语言函数功能简单实例
Mar 13 Python
django2笔记之路由path语法的实现
Jul 17 Python
python+pygame实现坦克大战
Sep 10 Python
在Python中画图(基于Jupyter notebook的魔法函数)
Oct 28 Python
详谈tensorflow gfile文件的用法
Feb 05 Python
django model object序列化实例
Mar 13 Python
python用Configobj模块读取配置文件
Sep 26 Python
python 使用OpenCV进行简单的人像分割与合成
Feb 02 Python
python3.6中anaconda安装sklearn踩坑实录
Jul 28 #Python
Python基于xlutils修改表格内容过程解析
Jul 28 #Python
Python如何读取、写入CSV数据
Jul 28 #Python
PyQt中使用QtSql连接MySql数据库的方法
Jul 28 #Python
pycharm全局搜索的具体步骤
Jul 28 #Python
Django model重写save方法及update踩坑详解
Jul 27 #Python
matplotlib 画双轴子图无法显示x轴的解决方法
Jul 27 #Python
You might like
用PHP将数据导入到Foxmail
2006/10/09 PHP
不用mod_rewrite直接用php实现伪静态化页面代码
2008/10/04 PHP
php curl_init函数用法
2014/01/31 PHP
php分页代码学习示例分享
2014/02/20 PHP
Yii实现简单分页的方法
2016/04/29 PHP
PHP mongodb操作类定义与用法示例【适合mongodb2.x和mongodb3.x】
2018/06/16 PHP
php和nginx交互实例讲解
2019/09/24 PHP
使用IE6看老赵的博客 jQuery初探
2010/01/17 Javascript
javascript hashtable 修正版 下载
2010/12/30 Javascript
让新消息在网页标题闪烁提示的jQuery代码
2013/11/04 Javascript
SeaJS入门教程系列之SeaJS介绍(一)
2014/03/03 Javascript
Jquery中使用show()与hide()方法动画显示和隐藏图片
2015/10/08 Javascript
JavaScript的String字符串对象常用操作总结
2016/05/26 Javascript
JavaScript和jQuery获取input框的绝对位置实现方法
2016/10/13 Javascript
关于BootStrap modal 在IOS9中不能弹出的解决方法(IOS 9 bootstrap modal ios 9 noticework)
2016/12/14 Javascript
jQuery实现花式轮播之圣诞节礼物传送效果
2016/12/25 Javascript
微信小程序 基础组件与导航组件详细介绍
2017/02/21 Javascript
vue2.0获取鼠标位置的方法
2018/09/13 Javascript
js获取form表单中name属性的值
2019/02/27 Javascript
微信小程序 获取手机号 JavaScript解密示例代码详解
2020/05/14 Javascript
antd design table更改某行数据的样式操作
2020/10/31 Javascript
[02:19]2018年度DOTA2最佳核心位选手-完美盛典
2018/12/17 DOTA
使用Python中的greenlet包实现并发编程的入门教程
2015/04/16 Python
Win7下搭建python开发环境图文教程(安装Python、pip、解释器)
2016/05/17 Python
Python将多个excel表格合并为一个表格
2021/02/22 Python
python使用pycharm环境调用opencv库
2018/02/11 Python
django初始化数据库的实例
2018/05/27 Python
[原创]Python入门教程3. 列表基本操作【定义、运算、常用函数】
2018/10/30 Python
详解python中的生成器、迭代器、闭包、装饰器
2019/08/22 Python
python编写猜数字小游戏
2019/10/06 Python
python 正则表达式贪婪模式与非贪婪模式原理、用法实例分析
2019/10/14 Python
python Plotly绘图工具的简单使用
2020/03/03 Python
python中turtle库的简单使用教程
2020/11/11 Python
Python 利用argparse模块实现脚本命令行参数解析
2020/12/28 Python
以太网Ethernet IEEE802.3
2013/08/05 面试题
HR必备:超全面的薪酬待遇管理方案!
2019/07/12 职场文书