将 JSON 转换为 Python 字典

Posted

技术标签:

【中文标题】将 JSON 转换为 Python 字典【英文标题】:Converting JSON into Python dict 【发布时间】:2011-01-29 23:01:15 【问题描述】:

我一直在寻找这个问题的答案,但我似乎无法找到它。可能到了晚上想不出答案已经太晚了,所以我转向这里的优秀读者。

我从 CouchDB 记录中提取了以下一些 JSON 数据:

"\"description\":\"fdsafsa\",\"order\":\"1\",\"place\":\"22 Plainsman Rd, Mississauga, ON, Canada\",\"lat\":43.5969175,\"lng\":-79.7248744,\"locationDate\":\"03/24/2010\",\"description\":\"sadfdsa\",\"order\":\"2\",\"place\":\"50 Dawnridge Trail, Brampton, ON, Canada\",\"lat\":43.7304774,\"lng\":-79.8055435,\"locationDate\":\"03/26/2010\","

此数据存储在名为“my_plan”的字典中的关键字“locations”下的 Python 字典中。我想将这些数据从 CouchDB 转换为 Python 字典,以便可以在 Django 模板中执行以下操作:

% for location in my_plan.locations %                                                           
<tr>
    <td> location.place </td>
    <td> location.locationDate </td>
</tr>

% endfor %

我找到了很多关于将 dicts 转换为 JSON 的信息,但没有找到其他方式。

【问题讨论】:

【参考方案1】:

第一件事第一

在这里,我将您提取的数据字符串存储到一个名为data_str的变量中,该变量有两个字典

>>> data_str = "\"description\":\"fdsafsa\",\"order\":\"1\",\"place\":\"22 Plainsman Rd, Mississauga, ON, Canada\",\"lat\":43.5969175,\"lng\":-79.7248744,\"locationDate\":\"03/24/2010\",\"description\":\"sadfdsa\",\"order\":\"2\",\"place\":\"50 Dawnridge Trail, Brampton, ON, Canada\",\"lat\":43.7304774,\"lng\":-79.8055435,\"locationDate\":\"03/26/2010\","

之后,我将其转换为另一个名为 data_str2 的字符串,该字符串采用 list 形式,并从末尾删除了多余的逗号(,)(如它给出了error而字符串数据到python对象的转换)。

>>> data_str2 = "[" + data_str[0: 1] + data_str[1: len(data_str)-1] + "]"

最后,我将这个 list string(一个包含 2 个字典的列表)转换为原始 python list 并将其存储在一个名为 data_list 的变量中.

>>> import json
>>> data_list = json.loads(data_str2) # Now data_list is a list having 2 dictionaries

现在让我们打印我们的数据。

>>> print data_list
[u'description': u'fdsafsa', u'order': u'1', u'place': u'22 Plainsman Rd, Mississauga, ON, Canada', u'lat': 43.5969175, u'lng': -79.7248744, u'locationDate': u'03/24/2010', u'description': u'sadfdsa', u'order': u'2', u'place': u'50 Dawnridge Trail, Brampton, ON, Canada', u'lat': 43.7304774, u'lng': -79.8055435, u'locationDate': u'03/26/2010']
>>> 
>>> print type(data_list)
<type 'list'>
>>> 
>>> print data_list[0]
u'description': u'fdsafsa', u'order': u'1', u'place': u'22 Plainsman Rd, Mississauga, ON, Canada', u'lat': 43.5969175, u'lng': -79.7248744, u'locationDate': u'03/24/2010'
>>> 
>>> print data_list[1]
u'description': u'sadfdsa', u'order': u'2', u'place': u'50 Dawnridge Trail, Brampton, ON, Canada', u'lat': 43.7304774, u'lng': -79.8055435, u'locationDate': u'03/26/2010'
>>> 

从视图中传递这个 data_list 列表并在您的 Django 模板 中访问它,如下所示,

% for data in locations %
      <tr>
           <td>  data.place  </td>
           <td>  data.locationDate  </td>
      </tr>
% endfor %

供您查看的示例代码段。

def locations(request):
    # YOU HAVE TO WRITE YOUR CODE LOGIC HERE TO GET THE LIST, 
    # I AM WRITING IT DIRECTLY
    data_list = [u'description': u'fdsafsa', u'order': u'1', u'place': u'22 Plainsman Rd, Mississauga, ON, Canada', u'lat': 43.5969175, u'lng': -79.7248744, u'locationDate': u'03/24/2010', u'description': u'sadfdsa', u'order': u'2', u'place': u'50 Dawnridge Trail, Brampton, ON, Canada', u'lat': 43.7304774, u'lng': -79.8055435, u'locationDate': u'03/26/2010']
    return render(request, "locations.html", "locations": data_list)

效果不错。

现在我想解释我是如何找到解决方案的,我认为这对初学者会有帮助。请参阅下面解释的逐步过程或see here。

>>> import json   
>>>
>>> # A simple attempt
>>> s = "\"description\":\"fdsafsa\""
>>> python_dict = json.loads(s)
>>> python_dict
u'description': u'fdsafsa'
>>> # Accessing value using key
>>> python_dict["description"]
u'fdsafsa'
>>> 
>>> # It worked, lets test our given string containing 2 dictionaries(in string form) one by one
>>> # Converting 1st JSON string to Dict
>>> s2 = "\"description\":\"fdsafsa\",\"order\":\"1\",\"place\":\"22 Plainsman Rd, Mississauga, ON, Canada\",\"lat\":43.5969175,\"lng\":-79.7248744,\"locationDate\":\"03/24/2010\""
>>> python_dict2 = json.loads(s2)                                                                                      >>> python_dict2
u'description': u'fdsafsa', u'order': u'1', u'place': u'22 Plainsman Rd, Mississauga, ON, Canada', u'lat': 43.5969175, u'lng': -79.7248744, u'locationDate': u'03/24/2010'
>>> 
>>> # Converting 2nd JSON string to Dict
>>> # remove comma(,) from end otherwise you will get the following error
>>> s3 = "\"description\":\"sadfdsa\",\"order\":\"2\",\"place\":\"50 Dawnridge Trail, Brampton, ON, Canada\",\"lat\":43.7304774,\"lng\":-79.8055435,\"locationDate\":\"03/26/2010\","
>>> python_dict3 = json.loads(s3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", line 339, in loads
    return _default_decoder.decode(s)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/decoder.py", line 367, in decode
    raise ValueError(errmsg("Extra data", s, end, len(s)))
ValueError: Extra data: line 1 column 152 - line 1 column 153 (char 151 - 152)
>>> 
>>> # Now I removed comma(,) from end and retried, it worked
>>> s3 = "\"description\":\"sadfdsa\",\"order\":\"2\",\"place\":\"50 Dawnridge Trail, Brampton, ON, Canada\",\"lat\":43.7304774,\"lng\":-79.8055435,\"locationDate\":\"03/26/2010\""
>>> python_dict3 = json.loads(s3) 
>>> 
>>> # So now we knew that we have not to include any extra comma at end in the string form of JSON
>>> # For example (Correct form)
>>> details_str = "\"name\":\"Rishikesh Agrawani\", \"age\": 25" 
>>> details_dict = json.loads(details_str)
>>> details_dict["name"]
u'Rishikesh Agrawani'
>>> details_dict["age"]
25
>>> # Now (Incorrect form), here comma(,) is at end, just after  
>>> details_str = "\"name\":\"Rishikesh Agrawani\", \"age\": 25,"
>>> details_dict = json.loads(details_str)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", line 339, in loads
    return _default_decoder.decode(s)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/decoder.py", line 367, in decode
    raise ValueError(errmsg("Extra data", s, end, len(s)))
ValueError: Extra data: line 1 column 41 - line 1 column 42 (char 40 - 41)
>>> 
>>> # The problem is the string does not denote any single python object 
>>> # So we will convert the string into a list form by appending [ at beginning and ] at end
>>> # Now our string will denote a single Python object that is list of 2 dictioanaries
>>> # Lets do this, here I am storing the given string into variable s4
>>> data_str = "\"description\":\"fdsafsa\",\"order\":\"1\",\"place\":\"22 Plainsman Rd, Mississauga, ON, Canada\",\"lat\":43.5969175,\"lng\":-79.7248744,\"locationDate\":\"03/24/2010\",\"description\":\"sadfdsa\",\"order\":\"2\",\"place\":\"50 Dawnridge Trail, Brampton, ON, Canada\",\"lat\":43.7304774,\"lng\":-79.8055435,\"locationDate\":\"03/26/2010\","
>>> s5 = "[" + s4[0:1] + s4[1: len(s4)-1] + "]"
>>> s5
'["description":"fdsafsa","order":"1","place":"22 Plainsman Rd, Mississauga, ON, Canada","lat":43.5969175,"lng":-79.7248744,"locationDate":"03/24/2010","description":"sadfdsa","order":"2","place":"50 Dawnridge Trail, Brampton, ON, Canada","lat":43.7304774,"lng":-79.8055435,"locationDate":"03/26/2010"]'
>>> # l is a list of 2 dictionaries
>>> l = json.loads(s5)
>>> l[0]
u'description': u'fdsafsa', u'order': u'1', u'place': u'22 Plainsman Rd, Mississauga, ON, Canada', u'lat': 43.5969175, u'lng': -79.7248744, u'locationDate': u'03/24/2010'
>>> 
>>> l[1]
u'description': u'sadfdsa', u'order': u'2', u'place': u'50 Dawnridge Trail, Brampton, ON, Canada', u'lat': 43.7304774, u'lng': -79.8055435, u'locationDate': u'03/26/2010'
>>>                                                           

谢谢

【讨论】:

【参考方案2】:

只是其他答案的组合:

import json
yourString = "\"description\":\"fdsafsa\",\"order\":\"1\",\"place\":\"22 Plainsman Rd, Mississauga, ON, Canada\",\"lat\":43.5969175,\"lng\":-79.7248744,\"locationDate\":\"03/24/2010\",\"description\":\"sadfdsa\",\"order\":\"2\",\"place\":\"50 Dawnridge Trail, Brampton, ON, Canada\",\"lat\":43.7304774,\"lng\":-79.8055435,\"locationDate\":\"03/26/2010\","
target = json.loads("[" + yourString[:-1] + "]")

输出

[u'description': u'fdsafsa', u'order': u'1', u'place': u'22 Plainsman Rd, Mississauga, ON, Canada', u'lat': 43.5969175, u'lng': -79.7248744, u'locationDate': u'03/24/2010', u'description': u'sadfdsa', u'order': u'2', u'place': u'50 Dawnridge Trail, Brampton, ON, Canada', u'lat': 43.7304774, u'lng': -79.8055435, u'locationDate': u'03/26/2010']

如前所述

这个字符串包含两个json对象,所以把它放在一个数组中([]) 它有一个尾随,,通过[:-1] 切片语法删除

【讨论】:

【参考方案3】:
Hello here my example
import json
class SimpleObject(object):
    def __init__(self, _dict):
        self.__dict__.update(_dict)

data=json.loads("\"name\":\"Rishikesh Agrawani\", \"age\": 25" )  
so=SimpleObject(data)
print (so.name)
print (so.age)

if you transform your data to objects is better and more fast work.

【讨论】:

【参考方案4】:

您显示的字符串不是 JSON 编码的对象(eqv 到 Python dict)——更像是一个数组(eqv 到列表),没有括号,末尾有一个额外的逗号。所以(使用simplejson 实现版本可移植性——2.6 中标准库的json 当然也可以!-):

>>> import simplejson
>>> js = "\"description\":\"fdsafsa\",\"order\":\"1\",\"place\":\"22 Plainsman Rd, Mississauga, ON, Canada\",\"lat\":43.5969175,\"lng\":-79.7248744,\"locationDate\":\"03/24/2010\",\"description\":\"sadfdsa\",\"order\":\"2\",\"place\":\"50 Dawnridge Trail, Brampton, ON, Canada\",\"lat\":43.7304774,\"lng\":-79.8055435,\"locationDate\":\"03/26/2010\","
>>> simplejson.loads('[%s]' % js[:-1])
['description': 'fdsafsa', 'order': '1', 'place': '22 Plainsman Rd, Mississauga, ON, Canada', 'lat': 43.596917500000004, 'lng': -79.724874400000004, 'locationDate': '03/24/2010', 'description': 'sadfdsa', 'order': '2', 'place': '50 Dawnridge Trail, Brampton, ON, Canada', 'lat': 43.730477399999998, 'lng': -79.805543499999999, 'locationDate': '03/26/2010']

如果你真的想要一个 dict,你必须指定如何处理这两个未命名的项目,即,你想给它们敲什么任意键......?

【讨论】:

您的解决方案完美运行。谢谢!我将在数据进入 CouchDB 之前修复生成该数据的例程,以便不附加额外的逗号。有点深夜编码马虎 @Grumpy,当然——如果我是你,我也会在数据库中的字符串周围加上方括号,以确保它是有效的 JSON,而不是接收方的“有点不完整的 JSON”代码必须完成。 我以前这样做过,但不记得为什么我停止这样做了……我认为从现在开始深夜编码需要笔记 为什么不使用 json 模块? simplejson 是遗留的,很久以前就应该弃用了。检查下面的答案为什么:)【参考方案5】:

使用 json 模块加载 JSON。 (Pre-2.6 使用第三方simplejson 模块,API 完全相同。)

>>> import json
>>> s = '"foo": 6, "bar": [1, 2, 3]'
>>> d = json.loads(s)
>>> print d
u'foo': 6, u'bar': [1, 2, 3]

您的实际数据无法以这种方式加载,因为它实际上是两个 JSON 对象,由逗号分隔并以逗号结尾。您需要将它们分开或以其他方式处理。

你从哪里得到这个字符串?

【讨论】:

该字符串来自我正在开发的应用程序生成的数据,这是一种用于计划旅行、酒吧爬行等的位置和日期社交应用程序【参考方案6】:
django.utils.simplejson.loads(someJson)

【讨论】:

不转换为字典。我确实尝试过;) 它给出的实际错误是“额外数据:第 1 行第 151 列 - 第 1 行第 304 列(字符 151 - 304)” @GrumpyCanuck,仔细看。这不是一个对象。它是一个对象,然后是一个逗号,然后是一个对象,然后是一个逗号。 是的,当我看到@Alex Martelli 的回答时我就明白了

以上是关于将 JSON 转换为 Python 字典的主要内容,如果未能解决你的问题,请参考以下文章

Python Flask:如何将字典对象转换为 json? [复制]

如何将返回的python JSON字典转换为字典中的列表,并将数据转换为SQL插入

Python爬虫编程思想(78): JSON字符串与字典互相转换

Python爬虫编程思想(78): JSON字符串与字典互相转换

将多维json数组转换成python字典成dataframe

python-将字符串转换为字典