将看起来像列表[dictionary]的字符串转换为python list [dictionary]类型数据

时间:2018-12-05 16:39:23

标签: python json string python-3.x

我正在尝试将此看起来很像包含字典的列表的字符串数据转换为所述数据类型的实际数据或我可以检索信息的任何其他形式。为了将其分成多行以获得更好的视图,字符串看起来像这样。

[
    {"type": "account", "data": "{\bid\:8,\acc_num\:135}"},
    {"type": "card", "data": "{\card_num\:142}"}
]

我已经尝试了常见的json.loads(a, strict=False)json.loads(a),但存在以下错误。我希望将"{\bid\:8,\acc_num\:135}"部分集中到一个字符串中(作为键data的值),但是也许没有发生……以为可能是\导致此问题的字符串,但a=a.replace('\','') 也无效(SyntaxError: EOL while scanning string literal错误)。

Traceback (most recent call last):
File "a.py", line 55, in <module>
    a=json.loads(a)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/__init__.py", line 348, in loads
    return _default_decoder.decode(s)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/json/decoder.py", line 353, in raw_decode
    obj, end = self.scan_once(s, idx)
json.decoder.JSONDecodeError: Invalid control character at: line 1 column 32 (char 31)

2 个答案:

答案 0 :(得分:2)

您可以使用ast.literal_eval()

>>> s = """[
...     {"type": "account", "data": "{\bid\:8,\acc_num\:135}"},
...     {"type": "card", "data": "{\card_num\:142}"}
... ]"""
>>> import ast
>>> x = ast.literal_eval(s)
>>> x
[{'type': 'account', 'data': '{\x08id\\:8,\x07cc_num\\:135}'}, {'type': 'card', 'data': '{\\card_num\\:142}'}]
>>> x[0]
{'type': 'account', 'data': '{\x08id\\:8,\x07cc_num\\:135}'}

答案 1 :(得分:2)

就像其他人提到的那样,您可以使用ast.literal_eval()来执行此操作-但您需要使用它两次 ,如下所示,它使用字典来“转义”遇到任何标准的字符串反斜杠转义字符(同时不让其他字符出现)。

中心思想是一个两步过程:

  1. 首先将必须转义的字符转换回其原始的未转义格式(包含if(TOPLEVEL PROJECT) cmake_minimum_required(VERSION 2.8.7) else() cmake_minimum_required(VERSION ${INHERITED_VERSION}) endif() 字符)。
  2. 然后将其中的\字符替换为引号字符。

例如,字符\(退格)首先被更改为'x\08',然后被更改为'\b'

'"b'

输出:

from ast import literal_eval

translate = {
    '\\': r'"',   # Backslash (\)
    '\'': r"'",   # Single quote (')
    '\"': r'"',   # Double quote (")
    '\a': r'"a',  # ASCII Bell (BEL)
    '\b': r'"b',  # ASCII Backspace (BS)
    '\f': r'"f',  # ASCII Formfeed (FF)
    '\n': r'"n',  # ASCII Linefeed (LF)
    '\r': r'"r',  # ASCII Carriage Return (CR)
    '\t': r'"t',  # ASCII Horizontal Tab (TAB)
    '\v': r'"v',  # ASCII Vertical Tab (VT)
}.get  # Function to translate escaped characters back to their original form.

def parse(data):
    def unescaped(s): return ''.join(translate(ch, ch) for ch in s)

    result = []
    for d in literal_eval(data):  # First call.
        for key, value in d.items():
            try:
                d[key] = literal_eval(unescaped(value))  # Second call.
            except ValueError:
                pass
        result.append(d)

    return result


if __name__ == '__main__':
    from textwrap import dedent
    from pprint import pprint

    data = dedent("""\
        [
            {"type": "account", "data": "{\bid\:8,\acc_num\:135}"},
            {"type": "card", "data": "{\card_num\:142}"}
        ]
    """)

    pprint(parse(data))