如何动态构建JSON对象?

356

我是Python的新手,正在处理JSON数据。我想通过向现有JSON对象添加一些键值对来动态构建一个JSON对象。

我尝试了以下代码,但是出现了TypeError:'str' object does not support item assignment错误:

import json

json_data = json.dumps({})
json_data["key"] = "value"

print 'JSON: ', json_data
8个回答

718

在将对象编码为 JSON 字符串之前,您需要先构建该对象:

import json

data = {}
data['key'] = 'value'
json_data = json.dumps(data)

JSON是一种序列化格式,它使用文本数据来表示结构。它本身并不是那个结构。


3
你的解决方案对我非常有效。虽然我不理解你最后一行的意思,你可以再详细解释一下吗?谢谢。 - akki
6
@akki:OP试图将JSON字符串(一系列编码对象的字符)视为对象本身。他们尝试使用json_data['key'] = 'value',但这不起作用,因为json_data不是Python字典。 - Martijn Pieters
@CharlieParker:这个问题太宽泛了。Python对象并不是那么容易反映到JSON中的,因为JSON只有几种数据类型,格式相当有限。在SO上已经有很多关于特定对象类型和JSON的问题,比如Django或SQLAlchemy模型等。 - Martijn Pieters
1
@AlexJohnson:pip list 可以给你相同的信息,并且可以输出 JSON 格式:pip list --format=json - Martijn Pieters
太棒了。谢谢你。 - joshlsullivan
显示剩余2条评论

42
你可以一行代码创建Python字典并将其序列化为JSON格式,而且这样做甚至不会显得丑陋。
my_json_string = json.dumps({'key1': val1, 'key2': val2})

25

已经提供了一种解决方案,允许构建字典(或更复杂数据的嵌套字典),但如果您希望构建对象,则可以尝试使用'ObjDict'。这可大大控制将要创建的JSON,例如保留顺序,并允许构建为首选表示概念的对象。

首先请安装ObjDict:pip install objdict。

from objdict import ObjDict

data = ObjDict()
data.key = 'value'
json_data = data.dumps()

2
这正是我一直在寻找的!鉴于字典是无序的,虽然在调用json.dumps时可以按字母顺序排序,即json.dumps(response, sort_keys=True, indent=4),但你将被困在字母顺序而不是你所期望的顺序、分组和表示上。 - Jonathan
JSON规范不允许有序属性存在于JSON对象中,任何需要特定属性顺序的终端设备都会失望。如果需要特定顺序,则需要将值放置在对象内的数组中。 - Rodney P. Barbati

20
  • json.loads接收一个字符串作为输入并返回一个字典作为输出。
  • json.dumps接收一个字典作为输入并返回一个字符串作为输出。

如果需要将JSON数据转换为Python对象,可以使用Python3中的SimpleNamespaceobject_hook在一行代码中完成,无需额外安装:

从字符串中获得:

import json
from types import SimpleNamespace

string = '{"foo":3, "bar":{"x":1, "y":2}}'

# Parse JSON into an object with attributes corresponding to dict keys.
x = json.loads(string, object_hook=lambda d: SimpleNamespace(**d))

print(x.foo)
print(x.bar.x)
print(x.bar.y)

输出:

3
1
2

文件来源:

JSON对象:data.json

{
    "foo": 3,
    "bar": {
        "x": 1,
        "y": 2
    }
}
import json
from types import SimpleNamespace

with open("data.json") as fh:
    string = fh.read()

# Parse JSON into an object with attributes corresponding to dict keys.
x = json.loads(string, object_hook=lambda d: SimpleNamespace(**d))

print(x.foo)
print(x.bar.x)
print(x.bar.y)

输出:

3
1
2

来自请求模块

import json
from types import SimpleNamespace
import requests

r = requests.get('https://api.github.com/users/MilovanTomasevic')

# Parse JSON into an object with attributes corresponding to dict keys.
x = json.loads(r.text, object_hook=lambda d: SimpleNamespace(**d))

print(x.name)
print(x.company)
print(x.blog)

输出:

Milovan Tomašević
NLB
milovantomasevic.com

为了更漂亮、更快地访问API的JSON响应,请查看此响应


14

您可以使用EasyDict(文档):

EasyDict允许像属性一样访问字典值(递归地工作)。它提供了类似JavaScript的属性点表示法,用于Python字典。

用法

>>> from easydict import EasyDict as edict
>>> d = edict({'foo':3, 'bar':{'x':1, 'y':2}})
>>> d.foo
3
>>> d.bar.x
1

>>> d = edict(foo=3)
>>> d.foo
3
[安装]:
  • pip install easydict

3
Benyamin,请您修改您的示例以展示与JSON dumps和loads一起使用的用法。 - Thom Ives

12

所有之前的答案都是正确的,这里提供一种更简单的方法。例如,创建一个Dict数据结构来序列化和反序列化对象。

(注意:在Python中,None表示Null,我有意使用它来演示如何存储null并将其转换为JSON null)

import json
print('serialization')
myDictObj = { "name":"John", "age":30, "car":None }
##convert object to json
serialized= json.dumps(myDictObj, sort_keys=True, indent=3)
print(serialized)
## now we are gonna convert json to object
deserialization=json.loads(serialized)
print(deserialization)

输入图像描述


2
我创建了一个递归函数来遍历表示JSON结构的嵌套字典。
  myjson={}
  myjson["Country"]= {"KR": { "id": "220", "name": "South Korea"}}
  myjson["Creative"]= {
                    "1067405": {
                        "id": "1067405",
                        "url": "https://cdn.gowadogo.com/559d1ba1-8d50-4c7f-b3f5-d80f918006e0.jpg"
                    },
                    "1067406": {
                        "id": "1067406",
                        "url": "https://cdn.gowadogo.com/3799a70d-339c-4ecb-bc1f-a959dde675b8.jpg"
                    },
                    "1067407": {
                        "id": "1067407",
                        "url": "https://cdn.gowadogo.com/180af6a5-251d-4aa9-9cd9-51b2fc77d0c6.jpg"
                    }
                }
   myjson["Offer"]= {
                    "advanced_targeting_enabled": "f",
                    "category_name": "E-commerce/ Shopping",
                    "click_lifespan": "168",
                    "conversion_cap": "50",
                    "currency": "USD",
                    "default_payout": "1.5"
                }

   json_data = json.dumps(myjson)

   #reverse back into a json

   paths=[]
   def walk_the_tree(inputDict,suffix=None):
       for key, value in inputDict.items():
            if isinstance(value, dict):
                if suffix==None:
                    suffix=key
                else:
                    suffix+=":"+key

                walk_the_tree(value,suffix)
            else:
                paths.append(suffix+":"+key+":"+value)
 walk_the_tree(myjson)
 print(paths)  

 #split and build your nested dictionary
 json_specs = {}
 for path in paths:
     parts=path.split(':')
     value=(parts[-1])
     d=json_specs
     for p in parts[:-1]:
         if p==parts[-2]:
             d = d.setdefault(p,value)
         else:
             d = d.setdefault(p,{})
    
 print(json_specs)        

 Paths:
 ['Country:KR:id:220', 'Country:KR:name:South Korea', 'Country:Creative:1067405:id:1067405', 'Country:Creative:1067405:url:https://cdn.gowadogo.com/559d1ba1-8d50-4c7f-b3f5-d80f918006e0.jpg', 'Country:Creative:1067405:1067406:id:1067406', 'Country:Creative:1067405:1067406:url:https://cdn.gowadogo.com/3799a70d-339c-4ecb-bc1f-a959dde675b8.jpg', 'Country:Creative:1067405:1067406:1067407:id:1067407', 'Country:Creative:1067405:1067406:1067407:url:https://cdn.gowadogo.com/180af6a5-251d-4aa9-9cd9-51b2fc77d0c6.jpg', 'Country:Creative:Offer:advanced_targeting_enabled:f', 'Country:Creative:Offer:category_name:E-commerce/ Shopping', 'Country:Creative:Offer:click_lifespan:168', 'Country:Creative:Offer:conversion_cap:50', 'Country:Creative:Offer:currency:USD', 'Country:Creative:Offer:default_payout:1.5']

请参阅如何反转嵌套字典路径的相关内容(https://stackoverflow.com/questions/2738141/python-created-nested-dictionary-from-list-of-paths/2739972) - Golden Lion

0

你可以使用jsonCreater模块创建JSON文件

        `jsonCreator.createJson(dict,”fileName”,[“path”])`

你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心找到有关如何编写良好答案的更多信息。 - Community

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