在Python中使用预计算文本JSON的自定义JSON编码器

2024-05-13 19:12:49 发布

您现在位置:Python中文网/ 问答频道 /正文

假设我有一个特殊的对象,它可能包含一个文本json字符串,我打算将它用作更大json对象中的字段,作为文本值本身(而不是包含json的字符串)。在

我想写一个自定义编码器,可以完成这一点,即:

> encoder.encode({
>     'a': LiteralJson('{}')
> })
{"a": {}}

我不相信子类化JSONEncoder和重写default会起作用,因为最多只能返回字符串,这将导致结果{"a": "{}"}。在

当LiteralJson嵌套在另一个字典中的某个地方时,重写encode似乎也不起作用。在

如果您感兴趣的话,其背景是我将JSON编码的值存储在一个缓存中,在我看来,一直反序列化然后重新序列化是一种浪费。它是这样工作的,但是其中一些值相当长,看起来像是一个巨大的浪费。在

下面的编码器可以完成我想要的(但似乎不必要的慢):

^{pr2}$

Tags: 对象字符串文本jsondefaultencoder字典序列化
2条回答

我刚意识到我最近得了一种病。答案建议使用替换令牌。在

使用自定义的JSONEncoder在内部使用随机UUID生成这些标记,可以或多或少地透明地集成这个逻辑。(我所说的“RawJavaScriptText”相当于你的“LiteralJson”。)

然后可以直接使用json.dumps(testvar, cls=RawJsJSONEncoder)。在

import json
import uuid

class RawJavaScriptText:
    def __init__(self, jstext):
        self._jstext = jstext
    def get_jstext(self):
        return self._jstext

class RawJsJSONEncoder(json.JSONEncoder):
    def __init__(self, *args, **kwargs):
        json.JSONEncoder.__init__(self, *args, **kwargs)
        self._replacement_map = {}

    def default(self, o):
        if isinstance(o, RawJavaScriptText):
            key = uuid.uuid4().hex
            self._replacement_map[key] = o.get_jstext()
            return key
        else:
            return json.JSONEncoder.default(self, o)

    def encode(self, o):
        result = json.JSONEncoder.encode(self, o)
        for k, v in self._replacement_map.iteritems():
             result = result.replace('"%s"' % (k,), v)
        return result

testvar = {
   'a': 1,
   'b': 'abc',
   'c': RawJavaScriptText('{ "x": [ 1, 2, 3 ] }')
}

print json.dumps(testvar, cls=RawJsJSONEncoder)

结果(使用Python 2.6和2.7):

^{pr2}$

it seems to me to be a waste to deserialize then reserialize all the time.

这是浪费,但只是万一有人在寻找一个快速的解决办法,这种方法运作良好。在

抄袭布鲁诺的例子:

testvar = {
   'a': 1,
   'b': 'abc',
   'c': json.loads('{ "x": [ 1, 2, 3 ] }')
}

print json.dumps(testvar)

结果:

^{pr2}$

相关问题 更多 >