在Python 2.7自定义JSON编码器插入普通的JavaScript代码(Custom JSON

2019-07-03 12:31发布

我想Python的2.6代码的一部分升级到Python 2.7。 此代码使用json模块以产生一些JavaScript(未JSON标准),然后将其插入到脚本的其余部分。

总的想法是能够插入代码或指的是在别处定义的变量:它不打算用作JSON数据,但JavaScript代码。

下面是在Python 2.6工作自定义编码器:

import json

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

class RawJsJSONEncoder(json.JSONEncoder):
    def _iterencode_default(self, o, markers=None):
        if isinstance(o, RawJavaScriptText):
            yield self.default(o)
        else:
            json.JSONEncoder._iterencode_default(self, o, markers)

    def default(self, o):
        if isinstance(o, RawJavaScriptText):
            return o.get_jstext()
        else:
            return json.JSONEncoder.default(self, o)

testvar = {
   'a': 1,
   'b': 'abc',
   # RawJavaScriptText will be inserted as such, no serialisation.
   'c': RawJavaScriptText('function() { return "Hello World"; }'),
   'd': RawJavaScriptText('some_variable_name')
}

print json.dumps(testvar, cls=RawJsJSONEncoder)

使用Python 2.6,我们得到所需的结果:

{ "a": 1, "c": function() { return "Hello World"; },
  "b": "abc", "d": some_variable_name }

使用Python 2.7,一切都变成了一个字符串,从而失去的JavaScript代码的有效性:

{ "a": 1, "c": "function() { return \"Hello World\"; }",
  "b": "abc", "d": "some_variable_name" }

(作为附带说明,这仅仅是每与预先定义的一组原始JavaScript值的使用,以防止潜在的注射或误用)。

当然,这样做的原因是, _iterencode_default的方法JSONEncoder不会在Python 2.7版本的存在json模块。 诚然,这并不意味着在第一时间被重写。

有另一种方式实现在Python 2.7这个目标呢? 使用JSON库的基础,能够生成JavaScript代码这种方式是相当方便的。

编辑:这是完全可行的解决方案,使用替代詹姆斯亨斯特莱吉的建议。 我使用随机的UUID用于更换标记,应避免任何冲突。 这样一来,这是一个直接替换使用Python 2.6和2.7两种工作。

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('function() { return "Hello World"; }'),
   'd': [ RawJavaScriptText('some_variable_name') ],
   'e': {
       'x': RawJavaScriptText('some_variable_name'),
       'y': 'y'
   }
}

print json.dumps(testvar, cls=RawJsJSONEncoder)

结果(2.6和2.7):

{"a": 1, "c": function() { return "Hello World"; },
 "b": "abc",
 "e": {"y": "y", "x": some_variable_name},
 "d": [some_variable_name]}

Answer 1:

您正在使用出现无证专用接口已经消失在被窝里用C延伸扩大到覆盖更多的编码过程。

一个替代办法是插入占位符字符串为您RawJavaScriptText价值观和后处理的输出dumps到那些地方持有人转换成您所需要的形式。

例如:

>>> data = {'foo': '@@x@@'}
>>> print json.dumps(data)
{"foo": "@@x@@"}
>>> print json.dumps(data).replace('"@@x@@"', 'some_variable_name')
{"foo": some_variable_name}

你要小心这种技术,如果你的JSON包括不可信数据:你不希望在一个位置,外人可以对输出意外增加这样的占位符。



文章来源: Custom JSON encoder in Python 2.7 to insert plain JavaScript code