Python2.7中用于插入纯JavaScript cod的自定义JSON编码器

2024-06-16 10:02:24 发布

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

我正在尝试将python2.6的一部分代码升级到python2.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,我们可以得到所需的结果:

^{pr2}$

使用Python 2.7,所有内容都会变成字符串,从而失去JavaScript代码的有效性:

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

(另请注意,这只是每次使用预定义的原始JavaScript值集,以防止潜在的注入或误用。)

当然,原因是JSONEncoder_iterencode_default方法在json模块的python2.7版本中不存在。诚然,它本来就不是要被推翻的。在

在Python2.7中有没有其他方法可以实现这个目标?使用JSON库的基础以这种方式生成JavaScript代码相当方便。在

编辑:这里是完整的工作解决方案,使用James Henstridge建议的替换。我使用随机uuid来替换令牌,这应该可以防止任何冲突。这样,就可以直接替换python2.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]}

Tags: 代码nameselfjsondefaultreturninitdef
1条回答
网友
1楼 · 发布于 2024-06-16 10:02:24

当在封面下使用的C扩展扩展覆盖更多的编码过程时,您使用的未记录的私有接口似乎已经消失了。在

另一种方法是为RawJavaScriptText值插入占位符字符串,并对dumps的输出进行后处理,以将这些占位符转换为所需的形式。在

例如:

^{1}$

如果您的JSON包含不可信的数据,您将需要小心这种技术:您不希望处于局外人可以意外地向输出添加此类占位符的位置。在

相关问题 更多 >