![](/img/trans.png)
[英]python json.dumps and json.loads before DynamoDB insertion
[英]preserve unicode characters with json.loads() or convert them back to when doing a json.dumps()
我有一个 json 文件,其中包含 unicode 字符\<
和\>
\<
。 使用 json.load() 加载文件时,这些字符会转换为<
和>
。 考虑以下实验:
d = json.loads('"Foo \u003cfoo@bar.net\u003e"')
然后打印如下:
'Foo <foo@bar.net>'
假设我需要将其转储回文件,并且需要将字符<
和>
转换回\<
和\>
\<
。 我目前正在使用f.write(json.dumps(d))
但这似乎不起作用。
我已经搜索了几个小时,但无法弄清楚这一点。
好吧,在这里了解 Python 解释器在做什么会很有用。
在你的源代码中,你有这样一段文字:
'"Foo \u003cfoo@bar.net\u003e"'
当解析器找到第一个字符'
,它得出结论:“这是一个字符串文字!在找到下一个'
,我应该获取所有字符并将其放入一个列表中,以用作字符串。” 因此,假设它在内存中创建了以下列表:
[]
然后它找到下一个字符"
。由于字符串文字没有关闭(因为没有找到'
),它将它添加到列表中。作为计算机中的一切,字符都表示为数字。数字是它的 Unicode 点,对于"
代码点是 34:
[ 34 ]
# "
它对下一个字符执行相同的操作,将它们的代码点放在列表中:
[ 34 70 111 111 32 ]
# " F o o
\\
和u
字符现在,解释器找到了字符\\
。 但这根本不是一个常见的字符! 对于解释器来说,这意味着接下来的字符不代表他们自己,而是应该被解释。 所以解释器不会将\\
添加到列表中,并让下一个解释器了解应该做什么。 这就是结果中没有\\
的原因。
下一个字符是u
。 由于它以\\
为前缀,解释器不会将其插入到列表中。 相反,
\\u\u003c/code>对被解释为
获取接下来的四个字符的命令,并将它们转换为十六进制数。
这就是结果中没有
\\u\u003c/code>的原因。
六个字符如何变成只有一个
接下来的四个字符是
0
、 0
、 3
和c
。 它们形成 0x3C 十六进制数,即十进制形式的 60。 所以它被添加到列表中:
[ 34 70 111 111 32 60 ]
# " F o o <
好吧,60 在 Unicode 中是
<
。 这就是为什么你的结果中有一个<
。 这就是为什么六个字符( \\
、 u
、 0
、 0
、 3
、 c
)在程序运行时实际上只代表一个( >
)的原因。
如何得到你想要的
当然,您可能希望在结果字符串中包含字符
\\
、 u
等。 如果是这样,Python 会给你一些选择,最简单的一个是原始字符串文字。 为此,您只需要在字符串文字前加上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"
小心你的愿望
但是请注意,这些字符串完全不同! 甚至它们的大小也大不相同,因为第二个字符更多:
>>> len('"Foo \u003cfoo@bar.net\u003e"')
19
>>> len(r'"Foo \u003cfoo@bar.net\u003e"')
29
现在,我不得不说,您可能不想在这里使用原始字符串。 您可能只想用 Unicode 点表示字符串,但这也引出了为什么. 无论如何,现在由你决定你想要什么:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.