【问题标题】:How to use "incorrect" JSON in python3如何在 python3 中使用“不正确”的 JSON
【发布时间】:2018-03-27 12:17:28
【问题描述】:

我有一个以下格式的 JSON 文件 -

注意 1 和 2 之后的字符(等)表示不带双引号的字符串

{
    "Apparel": {
        "XX": {
            "1": YY,
            "2": ZZ
                },
        "TT": {
            "1":TTT,
            "2":TTT,
            "3": TTT,
            "4": TTT
                    },
        "XXX": {
            "1":XXX,
            "2":XXX
                    },
        "RRR": {
            "1":RRR,
            "2":RRR
                    },

        "AAA": {
            "1":AAA,
            "2":AAA,
            "3":AAA
                    },
                }
....

等等。

现在我知道文件格式不正确(由于设计或某些 idk 原因,文件以这种方式保存)并且将其与 Python3 中的标准 json 模块一起使用会产生解码错误,但我被告知要按原样使用文件。这意味着任何问题,我将不得不对我的代码进行排序。我需要从每个标题中选择1 之后的值,然后从每个标题中选择2 中的值等等。

目前我正在使用此代码来读取文件 -

import json

with open("brand_config.json") as json_file:
    json_data = json.load(json_file)
    test = (json_data["apparel"]["biba"])

print (test)

这段代码给出了这个错误-

Traceback (most recent call last):
  File "reader.py", line 4, in <module>
    json_data = json.load(json_file)
  File "/usr/lib/python3.5/json/__init__.py", line 268, in load
    parse_constant=parse_constant, object_pairs_hook=object_pairs_hook, **kw)
  File "/usr/lib/python3.5/json/__init__.py", line 319, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python3.5/json/decoder.py", line 339, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python3.5/json/decoder.py", line 357, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 4 column 9 (char 36)

如何在不更改 JSON 文件中的任何内容的情况下读取所需的值。

【问题讨论】:

  • 你能发布你的原始 JSON。看起来 JSON 无效。
  • 你的问题有点缺乏细节。您是否像这样显示 ZZ 和 YY 是因为您的文件中有未引用的字符串,这就是 JSON 无效的原因?
  • 正是我的意思... JSON 无效。我发布的文件与原始 JSON 格式完全相同,只是我更改了值
  • 解决方案:使用有效的 JSON。 (或者不要假装它是 JSON 并编写自己的解析器)
  • @DanielRoseman 问题已编辑。请立即查看

标签: python json io python-3.5


【解决方案1】:

我从问题中了解到,您的 JSON 的值没有被引号括起来

我编写了以下脚本来解析问题中的特定文件

#!/usr/bin/env python3

from json import dumps


# Reads THAT SPECIFIC MALFORMATTED JSON, SHOULD NOT BE USED
def parse_json(filename):
    j = {}
    with open(filename, 'r') as json_file:
    lines = [line.strip() for line in json_file.readlines()]

    level = 0
    keys = []
    for line in lines:
        # increase a level
        if '{' in line:
            level += 1
            # append proper key
            if ':' in line:
                keys.append(line.split(':')[0].replace('"', '').strip())
                if level == 2:
                    j[keys[0]] = {}
                elif level == 3:
                    j[keys[0]][keys[1]] = {}
        # decrease a level, remove key
        elif '}' in line:
            keys = keys[:-1]
            level -= 1
        # add value
        else:
            if level == 3 and line:
                k, v = line.split(':')
                k = k.replace('"', '').strip()
                v = v.strip()[:-1]
                j[keys[0]][keys[1]][k] = v
    return j


brand_config = parse_json('brand_config.json')
print(dumps(brand_config, indent=4, sort_keys=True))

这会创建一个 python dictionary:

{
    "Apparel": {
        "AAA": {
            "1": "AAA",
            "2": "AAA",
            "3": "AA"
        },
        "RRR": {
            "1": "RRR",
            "2": "RR"
        },
        "TT": {
            "1": "TTT",
            "2": "TTT",
            "3": "TTT",
            "4": "TT"
        },
        "XX": {
            "1": "YY",
            "2": "Z"
        },
        "XXX": {
            "1": "XXX",
            "2": "XX"
        }
    }
}

鉴于您在问题中提供的内容。

编辑:在 cmets 中要求解释

keys 是一个列表,用于存储当前在 json 中使用的密钥。例如,{ "Apparel": {}} 表示keys=["Apparel"]{ "Apparel": {"AAA": XXX }} 表示keys=["Apparel", "AAA"]

函数一次处理一行文本文件

  • 创建一个空字典 (j)。

  • 1234563创建与该键关联的新字典。
  • 如果不存在{,但存在:,则拆分行并使用左值作为key,右值作为value

  • 如果存在},则将级别降低1并删除最后一个键。

最后一行只是把它漂亮地打印出来。

【讨论】:

  • 那么这里发生的事情是这个脚本正在将字符串前后的空格转换为引号?
  • 另外,假设我有超过 1 个格式相同的 JSON,如何从中提取相应的值并将它们连接起来形成一个字符串?
  • 对于连接问题,我需要更多详细信息,但它的工作方式与使用标准 python 字典(它是)的方式相同。
  • 我的意思是,我总共有 3 个这样的 JSON。我想从每个文件中选择"1": 的每个值并将它们连接成一个字符串。然后"2":的每个值等等。我该怎么做?
  • 我还注意到一个奇怪的错误,当迭代一个包含很多条目(有些条目多达 30 个)的键时,最终输出的顺序混乱了。 Like 1 后面会跟着 28,依此类推,以明显的随机顺序
【解决方案2】:

你的json文件一定有问题。我不知道你是从哪里得到这个文件的,或者是你自己生成的。

你的命令是正确的,我做了同样的情况,它工作......

>>> import json
>>> obj = {5:'jul'}
>>> d = json.dump(obj,open(os.getcwd()+'/JS.sjon','w+'))
>>> ld = json.load(open(os.getcwd()+'/JS.sjon','r'))
{'5': 'jul'}
>>> ld.get('5')
'jul'

所以,请检查您的数据来源

【讨论】:

  • 我的 JSON 没有双引号中的值。
【解决方案3】:

YAML 是 JSON 的超集,当涉及到值的引号时,它不那么严格(请参阅包 pyaml)。

例如

import yaml

with open("brand_config.json") as json_file:
    json_data = yaml.safe_load(json_file)
    test = (json_data["apparel"]["biba"])

print (test)

我用你问题中的“坏”JSON sn-p 尝试了这种方法,这就是我得到的:

{'Apparel': {'AAA': {'1': 'AAA', '2': 'AAA', '3': 'AAA'},
  'RRR': {'1': 'RRR', '2': 'RRR'},
  'TT': {'1': 'TTT', '2': 'TTT', '3': 'TTT', '4': 'TTT'},
  'XX': {'1': 'YY', '2': 'ZZ'},
  'XXX': {'1': 'XXX', '2': 'XXX'}}}

【讨论】:

  • 我在运行你的脚本时遇到了这个错误 - yaml.scanner.ScannerError: while scanning for the next token found character '\t' that cannot start any token in "brand_config.json", line 2, column 1
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-29
  • 1970-01-01
  • 2022-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多