解析JSON从unicode字符串作为字典
问题描述:
我有一个JSON输入一个包含字典为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。谢谢你的帮助!
答
尝试一个简单的例子:
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怎么样,方法按预期工作:
>>> s = '[{"attributes": { "a": "foo", "b": "bar" } }]'
>>> json.loads(s)
[{'attributes': {'a': 'foo', 'b': 'bar'}}]
>>> type(json.loads(s))
list
答
正如其他人所说,你的输入数据不是JSON。理想情况下,应该固定上游,以便做获得有效的JSON。
但是,如果超出了你的控制范围,可以将该数据转换为JSON。
主要问题是所有这些未加引号的键。我们可以通过使用正则表达式在每行的第一个字段中搜索有效的名称来解决这个问题。如果找到一个有效的名字,我们用双引号把它包起来。
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)
输出
{u'LOC_JUD': u'Bucharest', u'NAME': u'Name_1\u0102\u0102\xce\xce', u'MAP': u'Map_one', u'SURSA': u'PPP', u'S70': u'2342345', u'TYPE': u'Tip1', u'LAT_LON': u'234343/432545', u'SCH': u'1:5000'}
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[
{
"attributes": {
"LOC_JUD": "Bucharest",
"NAME": "Name_1ĂĂÎÎ",
"MAP": "Map_one",
"SURSA": "PPP",
"S70": "2342345",
"TYPE": "Tip1",
"LAT_LON": "234343/432545",
"SCH": "1:5000"
}
},
{
"attributes": {
"LOC_JUD": "cea",
"NAME": "NAME_2șțț",
"MAP": "Map_two",
"SURSA": "PPP",
"S70": "4324",
"TYPE": "Tip2",
"LAT_LON": "123/54645",
"SCH": "1:578000"
}
}
]
注意,这个代码是有点脆弱。它适用于问题中显示格式的数据,但如果一行上有多个键值对,将不会工作。
正如我前面所说,解决此问题的最佳方法是上游,其中非JSON正在生成。
+0
感谢您的建议。事实上,格式并不总是这样,所以我需要在上游解决问题。 – Litwos
只要做'json.loads(输入)'。转储是相反的过程,你不需要它。 – RemcoGerlich
但他会需要正确串化的json。当前输入没有包含在引号内的属性。我想这会是一个问题。 –
您需要使用'json.loads'而不是'json.dumps'。 'load'用于*反序列化*。 'dump'用于*序列化*。您正在将一个unicode字符串*序列化为一个JSON字符串*。 –