【问题标题】:Parse Json without quotes in Python在 Python 中解析不带引号的 Json
【发布时间】:2021-10-11 09:14:34
【问题描述】:

我正在尝试将 JSON 输入解析为 Python 中的字符串,但由于 JSON 输入的格式不正确,因此无法解析为列表或字典(由于中间件的限制,此处无法做太多事情。)

{
  "Records": "{Output=[{_fields=[{Entity=ABC  , No=12345, LineNo=       1, EffDate=20200630}, {Entity=ABC  , No=567, LineNo=       1, EffDate=20200630}]}"
}

我尝试了json.loadsast.literal(无效语法错误)。

如何加载这个?

【问题讨论】:

  • 如果您在谈论 Records 的值中的内容,那根本就不是 JSON。这不仅仅是缺少引号的问题(尽管这是一个问题),它还使用= 而不是:。这只是一种完全不同的数据格式。
  • 您拥有的是有效的 JSON,但 Records 键的值不是(也不是正确的 Python dict 显示),甚至不是特别接近。您需要找到其他解析器,或说服生产者使其成为有效的 JSON。
  • 您能否详细说明您的问题?粘贴代码示例?您在问题中输入的字符串似乎格式正确,其中一个 JSON 项目带有“记录”键,值是键后双引号中包含的字符串。我最好的选择是,也许你在字符串中加入了某种转义字符。请粘贴返回语法错误的代码。
  • @czyngis 我怀疑 OP 正在尝试做类似json.loads(result["Records"]) 的事情,这注定要失败。
  • @T.J.Crowder 是的,这是另一个问题,但我正在考虑将 = 替换为 : 因为它是一个字符串,但引号是主要问题

标签: python json python-3.x python-2.7 jsonparser


【解决方案1】:

可悲的答案是:"Records" 字段的内容根本不是 JSON。再多的临时补丁(=:,添加引号)都不会改变这一点。您必须找出生产系统发出的语言/格式规范,并为该特定格式编写/找到合适的解析器

作为一个离合器,并且仅在上述示例已经捕获了您可能在生产数据中看到的所有可变性的情况下,基于正则表达式的更简单的方法(参见包 re 或 edd 的实用答案)可能就足够了.

【讨论】:

  • 为什么,补丁会变成json
  • 只有当我们完全知道这种数据格式将如何处理更高级的场景时,比如其中一个字段中的字符串/文本数据。如果Entity 可以发出多字串,那么现在提出的简单解决方案都将落空。或者如果它包含逗号、括号、大括号,则可能是一个带引号的字符串......我们根本无法从单个示例中猜测工作代码。
【解决方案2】:

据我了解,您正在尝试将字典中 Records 项的值解析为 JSON,很遗憾您不能。

那个值中的字符串不是JSON,你必须写一个解析器,它会先按照你自己写的字符串的格式,把这个字符串解析成一个JSON字符串。 (不幸的是,我们不知道您在说什么“中间件”)。

tldr:将其解析为 JSON 字符串,然后将 JSON 解析为 python 字典。阅读 this 以了解有关 JSON(Javascript 对象表示法)规则的更多信息。

【讨论】:

  • 为什么将其解析为“JSON 字符串”,即绕道而行,而不是直接解析为 Python 数据结构?
  • @ojdo OP 在问题的标题中说他想解析 JSON。他想解析 JSON,所以我已经回答了如何将其解析为 JSON。另外,我认为编写一个只操作字符串然后使用 json 模块加载它的解析器更容易。
【解决方案3】:

如果数据的生产者是一致的,您可以从以下内容开始,旨在弥合 JSON 差距。

import re
import json


source = {
  "Records": "{Output=[{_fields=[{Entity=ABC  , No=12345, LineNo=       1, EffDate=20200630}, {Entity=ABC  , No=567, LineNo=       1, EffDate=20200630}]}"
}

s = source["Records"]

# We'll start by removing any extraneous white spaces
s2 = re.sub('\s', '', s)

# Surrounding any word with "
s3 = re.sub('(\w+)', '"\g<1>"', s2)

# Replacing = with :
s4 = re.sub('=', ':', s3)

# Lastly, fixing missing closing ], }
## Note that }} is an escaped } for f-string.
s5 = f"{s4}]}}"

>>> json.loads(s5)
{'Output': [{'_fields': [{'Entity': 'ABC', 'No': '12345', 'LineNo': '1', 'EffDate': '20200630'}, {'Entity': 'ABC', 'No': '567', 'LineNo': '1', 'EffDate': '20200630'}]}]}

继续进行一些稳健的测试,并使用您最喜欢的工具进行完善的 ETL。

【讨论】:

  • 非常感谢您的回答,这正是我一直在寻找的,因为输入数据将始终保持一致我可以继续使用这种方法,并且只有在经过稳健测试后才能继续。
【解决方案4】:

给你。此代码将使其成为有效的 json:

notjson = """{
  "Records": "{Output=[{_fields=[{Entity=ABC  , No=12345, LineNo=       1, EffDate=20200630}, {Entity=ABC  , No=567, LineNo=       1, EffDate=20200630}]}"
}"""
notjson = notjson.replace("=","':") #adds a singlequote and makes it more valid
notjson = notjson.replace("{","{'")
notjson = notjson.replace(", ",", '")
notjson = notjson.replace("}, '{","}, {")
json = "{" + notjson[2:]
print(json)
print(notjson)

【讨论】:

  • 非常感谢代码,它帮助我解析了输入。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多