在Python(没有Pickle)中,可以动态构造任意JSON字符串吗?

时间:2016-09-26 20:55:22

标签: python json python-2.7 pickle

在Python(2.7)中,有没有一种方法可以在不使用Pickle的情况下动态生成任意JSON字符串?

(很明显,这个查询专门讨论构建JSON有效载荷......在调用json.dumps()之前很久。)

为什么?

想象一下,您正在开展一个涉及与几个复杂API交互的项目(使用JSON)。

将构建并发布到API的每个JSON对象的每个实例都需要一个独特的层次结构(很多很多级别的对象......一个':',',','的暴风雪' []','{}'...你明白了。)

除了实例化Python对象并通过Pickle对其进行序列化之外,是否有更简单的方法来构造复杂的,任意的JSON字符串,而不依赖于对结构进行手工/硬编码;比如这个[可怜的]例子:

json_string = '{' + '"field_a": [ {' + '"id":' + id + '", "category":' + category . . . + '] }'

你的想法?建议?评论

1 个答案:

答案 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。它只是将一个对象转换为可以转换为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类。