简体   繁体   English

如何在没有转义序列的情况下取回与 fileInfo 一起存储的正确 json?

[英]How get back a proper json that was stored with fileInfo without the escape sequences?

I cannot retrieve the exact JSON string dump ( json.dumps ) that I store in Maya's 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)

The problem is the when Maya stores a value it ensures that it's properly escaped.问题是当 Maya 存储一个值时,它确保它被正确转义。 But when this string is retrieved its malformed for json.loads .但是当这个字符串被检索到它的json.loads格式json.loads How can I fix this?我怎样才能解决这个问题?

What I'm basically looking for is something that unescapes the escape sequence that MEL introduces while saving the value?我基本上要寻找的是在保存值的同时对 MEL 引入的转义序列进行转义的东西? So far I've failed to find anything that does this.到目前为止,我还没有找到任何可以做到这一点的东西。

MEL has a lot of similarity with C so the escape sequence is mostly identical to that of C as demonstrated above. MEL 与 C 有很多相似之处,因此转义序列与 C 的转义序列大部分相同,如上所示。

The best way to make sure you get stuff in and out of fileInfo intact is to base64 encode it on the way in and decode it on the way out.确保文件完整地进出文件的最佳方法是在进出时对其进行 base64 编码并在出路时对其进行解码。 Maya won't do that for you and the escaping it provides is, as you've seen, odd. Maya 不会为您执行此操作,而且正如您所见,它提供的转义很奇怪。

Here's an what I use;这是我使用的; it uses yaml but you should be able to swap in json no problem.它使用 yaml,但您应该可以毫无问题地交换 json。 I've used it for persisting yaml data the way you want to do.我已经用它来按照你想要的方式持久化 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))

The answer by @theodox is probably correct. @theodox 的答案可能是正确的。 But if you know that the json string will be escaped.但是如果你知道 json 字符串将被转义。 You can simply get back the original unescaped version of the string with.您可以简单地取回字符串的原始未转义版本。

mystring.decode('unicode_escape')

so in the above case, the proper way to deserialize the stored info would be:所以在上述情况下,反序列化存储信息的正确方法是:

json.loads(pc.fileInfo['foo'].decode('unicode_escape'))

It looks little ugly though, so you can have it inside a function.不过它看起来有点难看,所以你可以把它放在一个函数中。

def safe_json_loads(str):
    return json.loads(str.decode('unicode_escape'))


data = safe_json_loads(pc.fileInfo['foo'])

cheers,干杯,

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM