将JSON转换为Python字典

26

我一直在四处搜索寻找这个问题的答案,但似乎无法找到。也许已经太晚了,难以找到答案,所以我转向这里优秀的读者们。

我正在从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'。我想将这些数据从CouchDB转换成Python字典,以便在Django模板中执行以下操作:

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

{% endfor %}

我在转换字典为JSON方面已经找到了很多信息,但是没有关于反向转换的。

6个回答

39
  • 使用json模块来加载JSON。(对于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对象组成,它们之间用逗号分隔并以逗号结尾,所以无法通过这种方式加载。您需要将它们分开或以其他方式处理。

    • 您从哪里获取了此字符串?

  • 那个字符串来自我正在开发的应用程序生成的数据,这是一种针对计划旅行、酒吧爬行等活动的位置和日期社交应用程序。 - GrumpyCanuck

    20
    你展示的字符串不是一个JSON编码的对象(相当于Python字典)——更像是一个缺少括号且末尾有一个多余逗号的数组(相当于列表)。所以(为了版本可移植性,可以使用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'}]
    

    如果你真的想要一个字典,你需要指定如何处理这两个未命名的项,也就是你想要添加什么任意键?


    1
    你的解决方案完美地运行了。谢谢!在将数据放入CouchDB之前,我会修复生成数据的程序,以便不再添加额外的逗号。这是一些深夜编码的疏忽。 - GrumpyCanuck
    1
    @Grumpy,当然-如果我是你,我也会在数据库中的字符串周围加上括号,以确保它是有效的JSON,而不是接收代码必须完成的“有些不完整的JSON”。 - Alex Martelli
    1
    我以前做过那件事,但不记得为什么停止了...我想从现在开始,深夜编程需要笔记。 - GrumpyCanuck
    为什么不使用json模块呢?simplejson已经过时了,应该在很久以前就被弃用了。请查看下面的答案 :) - holms

    2
    django.utils.simplejson.loads(someJson)
    

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

    0
    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.
    

    0

    以下是其他答案的结合:

    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]切片语法移除

    0

    首先,要做的是第一件事

    在这里,我已经将您提取的数据字符串存储到一个名为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的字符串,它是以列表形式存在的,并从最后移除了额外的逗号(,)(因为在将字符串数据转换为Python对象时会出现错误)。

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

    最后,我将这个包含两个字典的列表字符串转换成原始的Python列表,并将其存储在一个名为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})
    

    它运行得很好。

    现在我想要解释一下我是如何达到这个解决方案的,我认为这对初学者会有所帮助。请看下面逐步解释的过程或在这里查看

    >>> 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'}
    >>>                                                           
    

    谢谢


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接