9

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

我想编写一个可以完成此任务的自定义编码器,即:

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

我不相信子类化 JSONEncoder 和覆盖默认值会起作用,因为充其量我可以返回字符串,这将使结果{"a": "{}"}

当 LiteralJson 嵌套在另一个字典中的某个地方时,覆盖编码似乎也不起作用。

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

以下编码器将完成我喜欢的事情(但似乎不必要地慢):

class MagicEncoder(json.JSONEncoder):

    def default(self, obj):
        if isinstance(obj, LiteralJson):
            return json.loads(obj.content)
        else:
            return json.JSONEncoder.default(self, obj)
4

2 回答 2

4

我刚刚意识到我最近有一个类似的问题。答案建议使用替换令牌。

可以使用自定义或多或少透明地集成此逻辑,该自定义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):

{"a": 1, "c": { "x": [ 1, 2, 3 ] }, "b": "abc"}
于 2012-11-03T03:59:14.310 回答
-2

在我看来,反序列化然后一直重新序列化是一种浪费。

这很浪费,但以防万一有人在寻找快速解决方法,这种方法可以正常工作。

抄袭布鲁诺的例子:

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

print json.dumps(testvar)

结果:

{"a": 1, "c": {"x": [1, 2, 3]}, "b": "abc"}
于 2014-02-12T05:04:20.477 回答