保留unicode字符json.loads文件()或在执行json.dumps文件()

2024-04-27 00:42:33 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个json文件,其中包含unicode字符\u003c\u003e。加载文件时json.load文件()这些字符被转换成<>。考虑以下实验:

d = json.loads('"Foo \u003cfoo@bar.net\u003e"')

然后像这样打印:

'Foo <foo@bar.net>'

假设我需要将这个文件转储回一个文件,并且需要将字符<>转换回\u003c\u003e。我目前正在使用f.write(json.dumps(d)),但这似乎不起作用。你知道吗

我已经找了好几个小时了,但就是想不出来。你知道吗


Tags: 文件jsonnetfoounicodebarload字符
1条回答
网友
1楼 · 发布于 2024-04-27 00:42:33

好吧,在这里理解Python解释器在做什么会很有用。你知道吗

当解释器找到字符串文字的开头时

在源代码中,有这样一段文字:

'"Foo \u003cfoo@bar.net\u003e"'

当解析器找到第一个字符'时,它得出结论:“这是一个字符串文本!在找到下一个'之前,我应该获取所有字符并将其放入一个列表中,作为字符串使用。“因此,假设它在内存中创建以下列表:

[]

然后找到下一个字符"。因为字符串文本没有关闭(因为没有找到'),所以它将它添加到列表中。就像电脑里的一切一样,字符都用数字来表示。数字是它的Unicode点,对于",代码点是34:

[ 34 ]
#  "

它对下一个字符执行相同的操作,将其代码点放在列表中:

[ 34   70  111  111   32 ]
#  "    F    o    o       

源代码中的\u字符

现在,解释器找到字符\。但这根本不是一个普通的字符!对于解释者来说,这意味着接下来的字符并不意味着他们自己,而是应该被解释。因此解释器不会\添加到列表中,并让下一个解释器理解应该做什么。这就是结果中没有\的原因。

下一个字符是u。因为它的前缀是\,所以解释器不会将它插入到列表中。相反,the ^{} pair is interpreted as a command要获得接下来的四个字符,请将它们转换为十六进制数。这就是为什么结果中没有\u

六个字怎么变成一个

接下来的四个字符是003c。它们形成0x3C十六进制数,即十进制形式的60。因此,它被添加到列表中:

[ 34   70  111  111   32   60 ]
#  "    F    o    o         <

嗯,60在Unicode中是<这就是结果中有<的原因。这就是为什么程序运行时,六个字符(\u003c)实际上只代表一个(>)。你知道吗

如何得到你想要的

当然,您可能希望在结果字符串中包含字符\u等。如果是这样,Python会提供一些选项,最简单的选项是raw string literal。要做到这一点,只需在字符串文本前面加上r,如下所示:

r'"Foo \u003cfoo@bar.net\u003e"'

当解释器将源代码中的r加上引号(如')时,它知道这是一个字符串文本,但这个字符串文本根本没有\的解释。它里面的所有东西都要像在源代码中键入的那样使用。这会产生一个类似于您想要的结果:

>>> print('"Foo \u003cfoo@bar.net\u003e"')
"Foo <foo@bar.net>"
>>> print(r'"Foo \u003cfoo@bar.net\u003e"')
"Foo \u003cfoo@bar.net\u003e"

Be Careful What You Wish For

但是请注意,这些字符串是完全不同的!甚至它们的大小也大不相同,因为第二个有更多的字符:

>>> len('"Foo \u003cfoo@bar.net\u003e"')
19
>>> len(r'"Foo \u003cfoo@bar.net\u003e"')
29

现在,我不得不说,你可能不希望这里有一个原始字符串。您可能只想用Unicode点来表示字符串,但这也引出了一个问题:为什么要这样做。不管怎样,现在由你来决定你想要什么:)

相关问题 更多 >