在Python(2.7)中,有没有一种方法可以在不使用Pickle的情况下动态生成任意JSON字符串?
(很明显,这个查询专门讨论构建JSON有效载荷......在调用json.dumps()之前很久。)
为什么?
想象一下,您正在开展一个涉及与几个复杂API交互的项目(使用JSON)。
将构建并发布到API的每个JSON对象的每个实例都需要一个独特的层次结构(很多很多级别的对象......一个':',',','的暴风雪' []','{}'...你明白了。)
除了实例化Python对象并通过Pickle对其进行序列化之外,是否有更简单的方法来构造复杂的,任意的JSON字符串,而不依赖于对结构进行手工/硬编码;比如这个[可怜的]例子:
json_string = '{' + '"field_a": [ {' + '"id":' + id + '", "category":' + category . . . + '] }'
你的想法?建议?评论
答案 0 :(得分:1)
默认JSON编码器能够从某些基本类型(例如int,str,list,dict)创建JSON,但它无法处理自定义对象。
例如:
json.dumps([1, 2, 3]) # this works: '[1, 2, 3]'
class A(object):
def __init__(self):
self.value1 = 1
self.value2 = {'foo': ['bar', 'baz']}
json.dumps(A()) # this fails
幸运的是,json允许创建自定义JSON编码器。
自定义JSON编码器不必创建JSON。它只是将一个对象转换为可以转换为JSON的东西!
因此,创建字典就足够了。
最简单的解决方案是使用__dict__
- 这将适用于大多数自定义类,因为__dict__
包含所有成员变量的字典,并且字典可以通过内置编码为JSON编码器:
class DictJsonEncoder(json.JSONEncoder):
def default(self, obj):
return obj.__dict__
json.dumps(a, cls=DictJsonEncoder) # '{"value2": {"foo": ["bar", "baz"]}, "value1": 1}'
为了获得更大的灵活性,请不要总是使用__dict__
(但请将其作为默认设置)。
一种常见的模式是实现__json__
方法,该方法可以满足需要并在可用时使用该方法:
class MyJsonEncoder(json.JSONEncoder):
def default(self, obj):
if hasattr(obj, '__json__'):
return obj.__json__()
else:
return super(MyJsonEncoder, self).default(obj)
然后实现返回__json__
的默认__dict__
方法:
class JsonCapable(object):
def __json__(self):
return self.__dict__
class A(JsonCapable):
def __init__(self):
self.value1 = 1
self.value2 = {'foo': ['bar', 'baz']}
# For special needs, override __json__ here
json.dumps(a, cls=MyJsonEncoder) # '{"value2": {"foo": ["bar", "baz"]}, "value1": 1}'
或者,如果编码器找到它并__json__
作为备份,编码器可以使用__dict__
。那么就不需要JsonCapable
类。