将unicode字符串中的JSON解析为字典

时间:2017-04-05 10:30:00

标签: python json dictionary unicode

我有一个JSON输入,它包含一个字典列表作为unicode字符: 例如:

input = u'[{
        attributes: {
            NAME: "Name_1ĂĂÎÎ",
            TYPE: "Tip1",
            LOC_JUD: "Bucharest",
            LAT_LON: "234343/432545",
            S70: "2342345",
            MAP: "Map_one",
            SCH: "1:5000,
            SURSA: "PPP"
        }
    }, {
        attributes: {
            NAME: "NAME_2șțț",
            TYPE: "Tip2",
            LOC_JUD: "cea",
            LAT_LON: "123/54645",
            S70: "4324",
            MAP: "Map_two",
            SCH: "1:578000",
            SURSA: "PPP"
        }
    }
]
'

如何将此字符串解析为字典列表?我试着这样做:

import json
json_d = json.dumps(input)
print type(json_d)  # string object / Not list of dicts
json_obj = json.loads(json_d)  # unicode object / Not list of dicts

我无法解析JSON的内容:

print json_obj[0]["attributes"]
TypeError: string indices must be integers

我正在使用Python 2.7.11。谢谢你的帮助!

2 个答案:

答案 0 :(得分:1)

尝试一个简化的例子:

s = '[{attributes: { a: "foo", b: "bar" } }]'

主要问题是你的字符串不是有效的JSON:

>>> json.loads(s)
[...]
JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 3 (char 2)

如果输入是由您生成的,则修复它。如果它来自其他地方,那么在使用json模块加载它之前,您需要对其进行编辑。

注意如何使用正确的JSON,.load()方法按预期工作:

>>> s = '[{"attributes": { "a": "foo", "b": "bar" } }]'
>>> json.loads(s)
[{'attributes': {'a': 'foo', 'b': 'bar'}}]
>>> type(json.loads(s))
list

答案 1 :(得分:1)

正如其他人所提到的,您的输入数据不是JSON。理想情况下,应该在上游修复,以便获得有效的JSON。

但是,如果您无法控制,则可以将该数据转换为JSON。

主要问题是所有那些不带引号的密钥。我们可以通过使用正则表达式在每行的第一个字段中搜索有效名称来解决这个问题。如果找到有效名称,我们用双引号括起来。

import time
def blastOff(n):
    """Returns "Blast Off" after a reverse countdown of n"""
    for i in reversed(range(1, n + 1)): # iterate over a reversed range
        print(i, i * "*") # multiply "*" by the ith number of the range.
        time.sleep(1) # sleep for a second before looping over the next number in the range.
    return "BLAST OFF"

blastOff(4)

4 ****
3 ***
2 **
1 *
Out: 'BLAST OFF'    

<强>输出

import json
import re

source = u'''[{
        attributes: {
            NAME: "Name_1ĂĂÎÎ",
            TYPE: "Tip1",
            LOC_JUD: "Bucharest",
            LAT_LON: "234343/432545",
            S70: "2342345",
            MAP: "Map_one",
            SCH: "1:5000",
            SURSA: "PPP"
        }
    }, {
        attributes: {
            NAME: "NAME_2șțț",
            TYPE: "Tip2",
            LOC_JUD: "cea",
            LAT_LON: "123/54645",
            S70: "4324",
            MAP: "Map_two",
            SCH: "1:578000",
            SURSA: "PPP"
        }
    }
]
'''

# Split source into lines, then split lines into colon-separated fields
a = [s.strip().split(': ') for s in source.splitlines()]

# Wrap names in first field in double quotes
valid_name = re.compile('(^\w+$)')
for row in a:
    row[0] = valid_name.sub(r'"\1"', row[0])

# Recombine the data and load it
data = json.loads(' '.join([': '.join(row) for row in a]))

# Test 

print data[0]["attributes"]
print '- ' * 30
print json.dumps(data, indent=4, ensure_ascii=False)

请注意,此代码有点脆弱。它适用于问题中显示的格式的数据,但如果一行上有多个键值对,将不会工作。

正如我之前所说,解决此问题的最佳方法是上游,即生成非JSON。