Python2.7中用于插入普通JavaScript代码的自定义JSON编码器

Python2.7中用于插入普通JavaScript代码的自定义JSON编码器,python,json,python-2.7,python-2.6,Python,Json,Python 2.7,Python 2.6,我正在尝试将Python2.6代码的一部分升级到Python2.7。此代码使用json模块生成一些JavaScript(不符合json),然后将其插入脚本的其余部分 一般的想法是能够插入代码或引用其他地方定义的变量:它不打算用作JSON数据,而是JavaScript代码 以下是在Python 2.6中工作的自定义编码器: 导入json 类RawJavaScriptText: 定义初始化(self,jstext): self.\u jstext=jstext def get_jstext(自我):

我正在尝试将Python2.6代码的一部分升级到Python2.7。此代码使用
json
模块生成一些JavaScript(不符合json),然后将其插入脚本的其余部分

一般的想法是能够插入代码或引用其他地方定义的变量:它不打算用作JSON数据,而是JavaScript代码

以下是在Python 2.6中工作的自定义编码器:

导入json
类RawJavaScriptText:
定义初始化(self,jstext):
self.\u jstext=jstext
def get_jstext(自我):
返回self.\jstext
类rawjsonencoder(json.JSONEncoder):
默认值(self、o、markers=None):
如果isinstance(o,RawJavaScriptText):
收益率自默认值(o)
其他:
json.JSONEncoder.\u iterencode\u默认值(self、o、markers)
def默认值(自身,o):
如果isinstance(o,RawJavaScriptText):
返回o.get_jstext()
其他:
返回json.JSONEncoder.default(self,o)
testvar={
"a":1,,
‘b’:‘abc’,
#RawJavaScriptText将按原样插入,无序列化。
'c':RawJavaScriptText('function(){return“Hello World”;}'),
'd':RawJavaScriptText('some_variable_name')
}
打印json.dumps(testvar,cls=rawjsonencoder)
使用Python 2.6,我们可以得到所需的结果:

{“a”:1,“c”:function(){返回“Hello World”;},
“b”:“abc”,“d”:一些变量名}
使用Python 2.7,所有内容都转换为字符串,从而失去JavaScript代码的有效性:

{“a”:1,“c”:“function(){return\'Hello World\';}”,
“b”:“abc”,“d”:“某个变量的名称”}
(作为旁注,这仅用于预定义的原始JavaScript值集,以防止潜在的注入或误用。)

当然,这是因为
jsonecoder
\u iterencode\u default
方法在
json
模块的Python 2.7版本中不存在。诚然,它本来就不应该被推翻

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

编辑:这里是完整的工作解决方案,使用James Henstridge建议的替换。我将随机UUID用于替换令牌,这将防止任何冲突。这样,就可以直接替换Python2.6和2.7

导入json
导入uuid
类RawJavaScriptText:
定义初始化(self,jstext):
self.\u jstext=jstext
def get_jstext(自我):
返回self.\jstext
类rawjsonencoder(json.JSONEncoder):
定义初始化(self,*args,**kwargs):
json.JSONEncoder.\uuuu init\uuuu(self,*args,**kwargs)
self.\u replacement\u map={}
def默认值(自身,o):
如果isinstance(o,RawJavaScriptText):
key=uuid.uuid4().hex
self._replacement_map[key]=o.get_jstext()
返回键
其他:
返回json.JSONEncoder.default(self,o)
def编码(自身,o):
result=json.JSONEncoder.encode(self,o)
对于k,v在self.\u replacement\u map.iteritems():
结果=结果。替换('%s'%(k,),v)
返回结果
testvar={
"a":1,,
‘b’:‘abc’,
'c':RawJavaScriptText('function(){return“Hello World”;}'),
“d”:[RawJavaScriptText('some_variable_name'),
“e”:{
'x':RawJavaScriptText('some_variable_name'),
“y”:“y”
}
}
打印json.dumps(testvar,cls=rawjsonencoder)
结果(2.6和2.7):


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

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

例如:

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

如果JSON包含不受信任的数据,您需要小心这种技术:您不希望局外人意外地将此类占位符添加到输出中。

顺便说一句——有没有任何原因,您不能使其与JSON兼容,而不是包含实际的代码,包括它作为代码的引用,然后让Javascript作为另一端的引用代码?@JonClements,它不仅包括实际代码,还包括变量(如
some_variable_name
示例)。JavaScript端需要能够区分
“某个变量名”
(实际字符串值)和
某个变量名
(然后它将引用该变量中的值)。啊哈-这很有意义现在干杯,我刚刚添加了一个解决方案,如您所建议的,使用
替换
。为了防止冲突,我在自定义编码器本身中使用随机UUID。
>>> data = {'foo': '@@x@@'}
>>> print json.dumps(data)
{"foo": "@@x@@"}
>>> print json.dumps(data).replace('"@@x@@"', 'some_variable_name')
{"foo": some_variable_name}