在 python 中输出 JSON 内容很奇怪
Weird thing about JSON content output in python
如果已经有人问过,请原谅我。我从一个简单的 python 代码片段中看到了一些奇怪的结果:
import json
''' copy contents of one json file into another '''
with open('./new_file.json', 'w') as f1:
with open('./old_file.json') as f2:
data = json.load(f2)
json.dump(data, f1)
上面的代码片段将一个 json 文件的内容复制到另一个文件中。原始文件没有漂亮的格式(即内容全部在一行上)
在 运行 代码之后,我执行以下操作:
$ diff -q new_file.json old_file.json
Files new_file.json and old_file.json differ
文件内容明显不同,很奇怪。
然后我尝试做:
$ cat new_file.json | python -m json.tool > foo
$ cat old_file.json | python -m json.tool > bar
然后当我比较文件 bar 和 foo 时,我得到:
:~/$ diff -q foo bar
:~/$
说明格式化后的内容是一样的。有什么解释吗?
提前致谢。
您已经指出:文件格式。一个文件只有一行,另一个文件可能有更多行。空格可以来来去去...所有这些格式化的东西使文件不同,但内容基本相同。
这是您所看到的行为的最小重新表达。仔细阅读它,看看您是否仍然对为什么 new==old
是 False
而 foo==bar
是 True
感到困惑。这几乎是不言自明的。
import json
def tool(jsons):
return json.dumps(json.loads(jsons))
old = '[{"key": "value" }]'
new = tool(old)
print(f'{old} == {new}', new == old)
# [{"key": "value" }] == [{"key": "value"}] False
foo = tool(new)
bar = tool(old)
print(f'{foo} == {foo}', foo == bar)
# [{"key": "value"}] == [{"key": "value"}] True
对其进行扩展。您看到的是 运行 该工具修复了所有不需要的格式。所以最初这两个文件是不同的。然而,由于 re运行 工具在已经格式化的东西上只是 returns 相同的结果,运行 在旧文件和新文件上的工具只会重现相同的输出两次,这是格式化输出。
json 对象是 defined as "an unordered set of name/value pairs",Python 字典也是(至少到 python 3.7),所以 json.load()
创建的字典可以他们的钥匙顺序不同。然后当你 json.dump()
那些字典时,它是用于生成 json 的当前字典键顺序。
示例:
$ cat old.json
{"a": 42, "c": {"baaz": "quux", "foo": "bar"}, "b": [1, 2, 3]}
$ cat new.json
{"a": 42, "b": [1, 2, 3], "c": {"foo": "bar", "baaz": "quux"}}
$ diff -q old.json new.json
Les fichiers old.json et new.json sont différents
d$ python
(...)
>>> import json
>>> with open("old.json") as f:
... old = json.load(f)
>>> with open("new.json") as f:
... new = json.load(f)
...
>>> old == new
True
>>>
关键在于,由于 json 中的键顺序并不重要,diff
不是检查两个 json 字符串是否真的不同的正确工具 - 而且它们是确实有很多工具可以做到 proper json diff.
正如 Poshi 和 Vincent 提到的,这两个 json 字符串等同于 json 数据,但与文本不同:
{"a": 42, "c": {"baaz": "quux", "foo": "bar"}, "b": [1, 2, 3]}
{"a":42, "c" : {"baaz":"quux" , "foo": "bar" } , "b" : [ 1, 2, 3] }
如果已经有人问过,请原谅我。我从一个简单的 python 代码片段中看到了一些奇怪的结果:
import json
''' copy contents of one json file into another '''
with open('./new_file.json', 'w') as f1:
with open('./old_file.json') as f2:
data = json.load(f2)
json.dump(data, f1)
上面的代码片段将一个 json 文件的内容复制到另一个文件中。原始文件没有漂亮的格式(即内容全部在一行上)
在 运行 代码之后,我执行以下操作:
$ diff -q new_file.json old_file.json
Files new_file.json and old_file.json differ
文件内容明显不同,很奇怪。 然后我尝试做:
$ cat new_file.json | python -m json.tool > foo
$ cat old_file.json | python -m json.tool > bar
然后当我比较文件 bar 和 foo 时,我得到:
:~/$ diff -q foo bar
:~/$
说明格式化后的内容是一样的。有什么解释吗?
提前致谢。
您已经指出:文件格式。一个文件只有一行,另一个文件可能有更多行。空格可以来来去去...所有这些格式化的东西使文件不同,但内容基本相同。
这是您所看到的行为的最小重新表达。仔细阅读它,看看您是否仍然对为什么 new==old
是 False
而 foo==bar
是 True
感到困惑。这几乎是不言自明的。
import json
def tool(jsons):
return json.dumps(json.loads(jsons))
old = '[{"key": "value" }]'
new = tool(old)
print(f'{old} == {new}', new == old)
# [{"key": "value" }] == [{"key": "value"}] False
foo = tool(new)
bar = tool(old)
print(f'{foo} == {foo}', foo == bar)
# [{"key": "value"}] == [{"key": "value"}] True
对其进行扩展。您看到的是 运行 该工具修复了所有不需要的格式。所以最初这两个文件是不同的。然而,由于 re运行 工具在已经格式化的东西上只是 returns 相同的结果,运行 在旧文件和新文件上的工具只会重现相同的输出两次,这是格式化输出。
json 对象是 defined as "an unordered set of name/value pairs",Python 字典也是(至少到 python 3.7),所以 json.load()
创建的字典可以他们的钥匙顺序不同。然后当你 json.dump()
那些字典时,它是用于生成 json 的当前字典键顺序。
示例:
$ cat old.json
{"a": 42, "c": {"baaz": "quux", "foo": "bar"}, "b": [1, 2, 3]}
$ cat new.json
{"a": 42, "b": [1, 2, 3], "c": {"foo": "bar", "baaz": "quux"}}
$ diff -q old.json new.json
Les fichiers old.json et new.json sont différents
d$ python
(...)
>>> import json
>>> with open("old.json") as f:
... old = json.load(f)
>>> with open("new.json") as f:
... new = json.load(f)
...
>>> old == new
True
>>>
关键在于,由于 json 中的键顺序并不重要,diff
不是检查两个 json 字符串是否真的不同的正确工具 - 而且它们是确实有很多工具可以做到 proper json diff.
正如 Poshi 和 Vincent 提到的,这两个 json 字符串等同于 json 数据,但与文本不同:
{"a": 42, "c": {"baaz": "quux", "foo": "bar"}, "b": [1, 2, 3]}
{"a":42, "c" : {"baaz":"quux" , "foo": "bar" } , "b" : [ 1, 2, 3] }