考虑我有一个特殊的对象可能包含一个文字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)
答案 0 :(得分:3)
我刚刚意识到我最近有similar question。答案建议使用替换令牌。
使用随机UUID在内部生成这些令牌的自定义JSONEncoder
可以或多或少地透明地集成此逻辑。 (我称之为“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"}
答案 1 :(得分:-1)
在我看来,废弃反序列化然后一直重新编译。
这很浪费,但万一有人在寻找快速解决方法,这种方法运行正常。
来自布鲁诺的例子:
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"}