![](/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.