json

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。它源自JavaScript语言,易于人类阅读和编写,同时也方便机器进行解析和生成,目前被广泛应用于数据交换。

数据交换格式用于不同平台和语言之间的数据传递。例如,如果要在Python和Java之间进行通信,你会直接传递一个字典或列表给Java吗?Java可能会困惑不解。尽管Java也有字典和列表数据类型,但它们并不兼容,无法相互理解。这时就需要使用JSON这种数据交换格式,Python和Java都能理解JSON。那么其他语言为什么能理解JSON呢?因为这些语言内置或提供了处理JSON的模块,例如Python的json模块(需要注意,Python中的json模块名称全小写)。

JSON是一种跨语言、跨平台的格式,但只能对Python的基本数据类型进行操作,无法处理Python的类。JSON的格式和Python中的字典非常相似。然而,JSON要求字符串要用双引号括起来,并且不能有多余的逗号。这是因为在其他语言中,双引号表示字符串,单引号表示字符。此外,Python程序员经常在列表、元组或字典的最后一个元素后面加上逗号,但在JSON中是不允许的,需要特别注意。

在Python中,许多情况下都需要使用JSON。例如,在Socket通信中,你能直接将一个列表发送给对方吗?显然不行,因为Socket是基于字节(bytes)类型进行字节级发送的。这时可以使用JSON将列表转换为字符串,然后使用encode()方法将其转换为字节类型,然后发送出去。

关于JSON本身,我不打算在这里过多介绍和赘述,因为网络上有大量的相关介绍可供参考。如果你感兴趣,可以自行查阅。需要说明的是,JSON和XML之间的关系。XML是早期的数据交换格式,但现在逐渐被JSON取代,因为JSON的语法更简单,数据量更小。然而,由于某些机构(如银行、学校)早期使用的是XML格式的大量数据,迁移到JSON上需要花费大量时间和成本,因此XML在相当长的一段时间内仍然是常用的数据交换格式之一。

类型转换

将数据从Python转换到json格式,在数据类型上会有变化,如下表所示:

PythonJSON
dictobject
list, tuplearray
strstring
int, float, int- & float-derived Enumsnumber
Truetrue
Falsefalse
Nonenull

反过来,从json格式转化为Python内置类型,见下表:

JSONPython
objectdict
arraylist
stringstr
number (int)int
number (real)float
trueTrue
falseFalse
nullNone

使用方法

json模块的使用其实很简单,对于绝大多数场合下,我们只需要使用下面四个方法就可以了:

方法功能
json.dump(obj, fp)将python数据类型转换并保存到json格式的文件内。
json.dumps(obj)将python数据类型转换为json格式的字符串。
json.load(fp)从json格式的文件中读取数据并转换为python的类型。
json.loads(s)将json格式的字符串转换为python的类型。

下面是范例:

>>> import json
>>> json.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}])
'["foo", {"bar": ["baz", null, 1.0, 2]}]'
>>> print(json.dumps("\"foo\bar"))
"\"foo\bar"
>>> print(json.dumps('\u1234'))
"\u1234"
>>> print(json.dumps('\\'))
"\\"
>>> print(json.dumps({"c": 0, "b": 0, "a": 0}, sort_keys=True))
{"a": 0, "b": 0, "c": 0}
>>> from io import StringIO
>>> io = StringIO()
>>> json.dump(['streaming API'], io)
>>> io.getvalue()
'["streaming API"]'
>>> json.dumps([1, 2, 3, {'4': 5, '6': 7}], separators=(',', ':'))
'[1,2,3,{"4":5,"6":7}]'
>>> print(json.dumps({'4': 5, '6': 7}, sort_keys=True, indent=4))
{
    "4": 5,
    "6": 7
}
>>> json.loads('["foo", {"bar":["baz", null, 1.0, 2]}]')
['foo', {'bar': ['baz', None, 1.0, 2]}]
>>> json.loads('"\\"foo\\bar"')         ### 注意斜杠的转义
'"foo\x08ar'
>>> from io import StringIO
>>> io = StringIO('["streaming API"]')
>>> json.load(io)
['streaming API']

仔细观察四个方法的名称,很好记忆的,要转化成json就‘dump’,要从json转化成Python就‘load’;要根据字符串转化就加‘s’,要从文件进行转化就不加‘s’。

需要注意的是json模块不支持bytes类型,要先将bytes转换为str格式。

>>> import json
>>> s = "haha"
>>> j = json.dumps(s)
>>> j
'"haha"'
>>> b = b'xixi'
>>> k = json.dumps(b)
Traceback (most recent call last):
  File "<pyshell#5>", line 1, in <module>
    k = json.dumps(b)
  File "C:\Python36\lib\json\__init__.py", line 231, in dumps
    return _default_encoder.encode(obj)
  File "C:\Python36\lib\json\encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "C:\Python36\lib\json\encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "C:\Python36\lib\json\encoder.py", line 180, in default
    o.__class__.__name__)
TypeError: Object of type 'bytes' is not JSON serializable
>>> k = json.dumps(b.decode())
>>> k
'"xixi"'
>>> type(k)
<class 'str'>
>>> a = json.loads(k)
>>> a
'xixi'

对文件的读写:

>>>import json
>>> dic = {"k1":"v1","k2":123}
>>> f = json.dump(dic, open("d:\\3","w"))
>>> f       ## 没有返回值
>>> import os
>>> os.chdir("d:\\")
>>> os.listdir()        # 验证json文件3的存在
['$360Section', '$RECYCLE.BIN', '1.txt', '2.txt', '3', 'MobileFile', 'pymysql_test.py', 'System Volume Information', 'test', '用户目录']
>>> obj = json.load(open("d:\\3")) # 重新load回来
>>> obj
{'k1': 'v1', 'k2': 123}
>>> type(obj)
<class 'dict'>

可以在操作系统中,使用文本处理软件打开json文件,你会发现一切都是可读的。但是要当心,由于文本处理软件本身的问题,使用它们直接编辑json文件可能会在格式上出现问题。

还可以在命令行下,通过‘json.tool’使用json功能:

$ echo '{"json":"obj"}' | python -m json.tool
{
    "json": "obj"
}
$ echo '{1.2:3.4}' | python -m json.tool # 期望在花括号内使用双引号封装属性名称
Expecting property name enclosed in double quotes: line 1 column 2 (char 1)

在线工具

有时候,我们自己编写的,或者他人提供的json数据,格式、排版等等会非常混乱,比如下面的数据:

{
            "user" : "ZhangSan",           "type" : "work",            "team" : [{
                "city" : "BeiJing",
                "num" : 3           }, {                "city" : "GuangZhou",
                "num" : 3
            }, {                "city" : "ShangHai",
                "num" : 3
            }]
        }

这显然非常不利于阅读,无法区分层次关系,也不够优雅。

互联网上提供了很多JSON在线解析和校验工具,搜索关键字“json解析”,随便选一个,将你的数据粘贴进去,然后它就能帮你整理成下面的样子了。注意:切勿泄露敏感信息!

标签: python, python下载, Python教程, Python技术, Python学习, Python学习教程, Python语言, Python开发, Python入门教程, Python进阶教程, Python高级教程, Python面试题, Python笔试题, Python编程思想