我有一个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))
,但这似乎不起作用。
我已经搜索了几个小时,但只是无法弄清楚。
答案 0 :(得分:0)
好吧,在这里了解Python解释器的工作将很有用。
在源代码中,您有以下一段文字:
'"Foo \u003cfoo@bar.net\u003e"'
当解析器找到第一个字符'
时,其结论是:“这是一个字符串文字!在找到下一个'
之前,我应该获取所有字符并将其放在列表中,用作字符串。”因此,可以说它在内存中创建以下列表:
[]
然后找到下一个字符"
。由于字符串文字未关闭(因为未找到'
),因此将其添加到列表中。作为计算机中的所有内容,字符都用数字表示。数字是其Unicode点,对于"
,代码点是34:
[ 34 ]
# "
它与下一个字符相同,将其代码点放在列表中:
[ 34 70 111 111 32 ]
# " F o o
\
和u
字符现在,解释器找到字符\
。但这根本不是普通字符!对解释者而言,这意味着下一个字符不代表自身,而应被解释。因此,解释器不会将\
添加到列表中,并让下一个解释器了解应执行的操作。 这就是为什么您的结果中没有\
的原因。
下一个字符是u
。由于其前缀为\
,因此解释程序不会将其插入列表。相反,the \u
pair is interpreted as a command可以获取接下来的四个字符,并将它们转换为十六进制数字。 这就是为什么您的结果中没有\u
的原因。
接下来的四个字符为0
,0
,3
和c
。它们形成0x3C十六进制数,即十进制形式的60。因此它被添加到列表中:
[ 34 70 111 111 32 60 ]
# " F o o <
好吧,Unicode中的60是<
。 这就是为什么您的结果中有<
的原因。这就是为什么六个字符(\
,u
,0
,{{1} },0
,3
)实际上在程序运行时仅代表一个(c
)。
当然,您可能希望结果字符串中包含字符>
,\
等。如果是这样,Python提供了一些选项,最简单的选择是raw string literal。为此,只需在字符串文字前加上u
即可,如下所示:
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"
现在,我不得不说,您可能不想在这里使用原始字符串。您可能只想用Unicode点表示字符串,但这也引出了为什么的问题。无论如何,现在由您决定要什么:)