如何获取没有转义符的正确JSON,之前使用fileInfo存储的?
我无法获取我存储在Maya的fileInfo
中的确切 JSON 字符串(json.dumps
)。
>>> import pymel.core as pc
>>> json.dumps({'foo': 123})
'{"foo": 123}'
>>> pc.fileInfo['foo'] = json.dumps({'foo': 123})
>>> pc.fileInfo['foo']
u'{\\"foo\\": 123}'
>>> json.loads(pc.fileInfo['foo']) # this produces an error because of the escape sequence
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "c:\Program Files\Autodesk\Maya2011\bin\python26.zip\json\__init__.py", line 307, in loads
File "c:\Program Files\Autodesk\Maya2011\bin\python26.zip\json\decoder.py", line 319, in decode
File "c:\Program Files\Autodesk\Maya2011\bin\python26.zip\json\decoder.py", line 336, in raw_decode
File "c:\Program Files\Autodesk\Maya2011\bin\python26.zip\json\scanner.py", line 55, in iterscan
File "c:\Program Files\Autodesk\Maya2011\bin\python26.zip\json\decoder.py", line 171, in JSONObject
ValueError: Expecting property name: line 1 column 1 (char 1)
问题在于,当Maya存储一个值时,它会确保这个值被正确地转义。但当我试图取出这个字符串时,它却变得不符合json.loads
的格式。我该如何解决这个问题呢?
我基本上想要的是一种方法,可以取消转义 MEL在保存值时引入的转义序列?到目前为止,我还没有找到任何可以做到这一点的东西。
MEL和C语言有很多相似之处,所以它的转义序列基本上和C语言的一样,如上所示。
3 个回答
0
我遇到了同样的问题。当你从fileInfo命令中获取字符串后,只需像这样替换掉转义的引号:
# Lets say you stored some json data in a fileInfo called 'tester'
import maya.cmds as cmds
import json
s = cmds.fileInfo( 'tester', q = True )[ 0 ]
s = s.replace( '\\"', '"' ) # Handle escaped quotes
j = json.loads( s )
print( json.dumps( j, indent = 4 ) )
1
确保你在文件信息中存取的数据保持完整,最好的办法就是在存入时进行base64编码,取出时再解码。Maya不会自动帮你处理这些,而且它提供的转义方式,如你所见,是有点奇怪的。
下面是我使用的一个方法;它使用了yaml格式,但你可以轻松换成json格式。我用这个方法来保存yaml数据,正好符合你的需求。
'''
mayaPersist - namespace for functions related to storing data in fileInfo objects inside the current Maya file
I've tested this (a little) with as many as 100,000 integers - it works but it's slooow at that size
< 1000 values seems imperceptible
'''
import yaml
import base64
from maya.cmds import fileInfo
import itertools
def save(key, value):
'''
save the specified value as a base64 encoded yaml dunp at key 'key'
'''
encoded =encode(value)
fileInfo(key, encoded)
def load(key):
'''
return the value stored at 'key', or None if the value can't be found
@note it is possible to store a 'None' in the value, so this doesn't prove that the key does not exist !
'''
answer = fileInfo(key, q=True)
if not answer:
return None
return decode(answer[0])
def exists(key):
'''
returns true if the specified key exists
'''
answer = fileInfo(key, q=True)
return len(answer) != 0
def ls():
'''
a generator that returns all of the key-value pairs in this file's fileInfo
@note: these are not decoded, because they contain a mix of native stirngs and b64 values
'''
all_values = fileInfo(q=True)
keys = itertools.islice(all_values, 0, None, 2)
values = itertools.islice(all_values, 1, None, 2)
return itertools.izip(keys, values)
def delete(key):
'''
remove the key and any data stored with it from this file
'''
fileInfo(rm=key)
def decode(value):
'''
convert a base64'ed yaml object back into a maya object
if the object is not encoded (eg, one of the default string values) return it untouched
'''
try:
val = base64.b64decode(value)
return yaml.load(val)
except TypeError:
return value
def encode (value):
'''
return the supplied value encoded into base64-packed YAML dump
'''
return base64.b64encode(yaml.dump(value))
1
@theodox 的回答可能是对的。不过,如果你知道这个 json 字符串会被转义的话,你可以很简单地把它还原成原来的未转义版本,方法是:
mystring.decode('unicode_escape')
所以在上面的情况下,正确的做法是把存储的信息反序列化为:
json.loads(pc.fileInfo['foo'].decode('unicode_escape'))
不过这样看起来有点丑,所以你可以把它放在一个函数里。
def safe_json_loads(str):
return json.loads(str.decode('unicode_escape'))
data = safe_json_loads(pc.fileInfo['foo'])
祝好,