为啥我不能在 Python 中反序列化带有单引号的 JSON 字符串?

Posted

技术标签:

【中文标题】为啥我不能在 Python 中反序列化带有单引号的 JSON 字符串?【英文标题】:Why can I not deserialise a JSON string with single quotes in Python?为什么我不能在 Python 中反序列化带有单引号的 JSON 字符串? 【发布时间】:2021-11-24 16:22:44 【问题描述】:

我正在使用 json 反序列化从我的 mysql 数据库接收到的字符串,以便生成的对象是字典。 这是代码:

sql.cursorobj.execute("SELECT * FROM timetableevents")
for record in sql.cursorobj.fetchall():
    print(record)
    obj= record['btnobject']
    detailsdict[obj]=json.loads(record['details'])    #I am facing an error here

我得到的错误是:

'btnobject': 'btnobject1', 'details': "'sno':[], 'time':[], 'events':[]"
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\veeru\Python 3.9.2\lib\tkinter\__init__.py", line 1892, in __call__
  return self.func(*args)
File "c:\Users\veeru\OneDrive\Visual Studio\Timetable\TimeTable.py", line 186, in <lambda>
  addtaskbtn.configure(command=lambda x=(btnobj, tableframe): ae.addtaskbtnclick(x[0], x[1]))
File "c:\Users\veeru\OneDrive\Visual Studio\Timetable\addevent.py", line 33, in addtaskbtnclick
  updateglobalvalues(btnobj)
File "c:\Users\veeru\OneDrive\Visual Studio\Timetable\addevent.py", line 22, in updateglobalvalues
  detailsdict[obj]=json.loads(f"record['details']")
File "C:\Users\veeru\Python 3.9.2\lib\json\__init__.py", line 346, in loads
  return _default_decoder.decode(s)
File "C:\Users\veeru\Python 3.9.2\lib\json\decoder.py", line 337, in decode
  obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "C:\Users\veeru\Python 3.9.2\lib\json\decoder.py", line 353, in raw_decode
  obj, end = self.scan_once(s, idx)
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)

上述错误代码的最后一行是最重要的。 我试过用双引号明确地将record['details'] 括起来 我也使用过fstrings,例如:json.loads(f"record['details']") **注意:** 请记住,json.loads(record['details']) 以前工作过,但在我更改数据库后,它就停止工作了。

【问题讨论】:

error msg 很清楚你的 dict 中有单引号,这使得它作为 json 无效,尝试使用 " 【参考方案1】:

您的 JSON 字符串无效。

来自json.org:

字符串是零个或多个 Unicode 字符的序列,用双引号括起来,使用反斜杠转义。

它有单引号,而 JSON 字符串应该有双引号才有效。

您实际上无法从数据库中批量替换引号,因此请在加载 JSON 之前使用 json.dumps 来转换引号。

试试这个:

detailsdict[obj]=json.loads(json.dumps(record['details']))

或者使用ast.literal_eval:

import ast
`detailsdict[obj]=json.loads(ast.literal_eval(record['details']))`

【讨论】:

【参考方案2】:

我们的字符串中有单引号,因此会出现此错误。您可以做的是将' 替换为",然后执行json.loads,如下所示:

sql.cursorobj.execute("SELECT * FROM timetableevents")
for record in sql.cursorobj.fetchall():
    print(record)
    obj= record['btnobject']
    # Replace ' with "
    details = record['details'].replace("'", '"')
    detailsdict[obj]=json.loads(details)    #I am facing an error here

【讨论】:

对于某些边缘情况,这似乎可能会失败。如果record['details'] 已经包含双引号怎么办?如果只有一个单引号(例如:“这不是那个”)怎么办? 如果已经包含双引号,则什么都不做。该代码只是用双引号替换单引号.. 对,但是如果你有一个像"this can't be true" 这样的字符串,你最终会得到"this can"t be true",这是无效的json。 @BryanOakley 是正确的 - 除非您 500% 确定输入,否则这将在某些形式的数据中打破可怕的错误,即使这样也有更好的方法【参考方案3】:

如果你尝试加载

print(json.loads('"sno":[], "time":[], "events":[]'))

它不会给你任何错误,因为密钥在双引号中, 你会得到结果

'sno': [], 'time': [], 'events': []

但如果您无法更改输出,请先尝试json.dumps

print(json.dumps("'sno':[], 'time':[], 'events':[]"))

这会给你

'"\'sno\':[], \'time\':[], \'events\':[]"'

【讨论】:

以上是关于为啥我不能在 Python 中反序列化带有单引号的 JSON 字符串?的主要内容,如果未能解决你的问题,请参考以下文章

Linux Shell中反引号``, 单引号'', 双引号"", $混用总结

JavaScript 中反引号 (`) 的使用

Mysql中反引号和单引号的区别

python单引号和双引号的区别

当我尝试在 .NET Core 中反序列化 FormFile 对象时,为啥会出现奇怪的异常?

shell脚本中反引号与双引号的·区别与联系