Python:如何从json解码枚举类型 [英] Python: How to decode enum type from json

查看:120
本文介绍了Python:如何从json解码枚举类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

class MSG_TYPE(IntEnum):
    REQUEST = 0
    GRANT = 1
    RELEASE = 2
    FAIL = 3
    INQUIRE = 4
    YIELD = 5

    def __json__(self):
        return str(self)

class MessageEncoder(JSONEncoder):
    def default(self, obj):
        return obj.__json__()

class Message(object):
    def __init__(self, msg_type, src, dest, data):
        self.msg_type = msg_type
        self.src = src
        self.dest = dest
        self.data = data

    def __json__(self):
        return dict (\
            msg_type=self.msg_type, \
            src=self.src, \
            dest=self.dest, \
            data=self.data,\
            )

    def ToJSON(self):
        return json.dumps(self, cls=MessageEncoder)

msg = Message(msg_type=MSG_TYPE.FAIL, src=0, dest=1, data="hello world")
encoded_msg = msg.ToJSON()
decoded_msg = yaml.load(encoded_msg)
print type(decoded_msg['msg_type'])

当调用 print type(decoded_msg ['msg_type'])时,我得到的结果是< type'str'> 而不是原始的 MSG_TYPTE类型.我觉得我也应该写一个自定义的json解码器,但是有点困惑.有任何想法吗?谢谢.

When calling print type(decoded_msg['msg_type']), I get the result <type 'str'> instead of the original MSG_TYPTE type. I feel like I should also write a custom json decoder but kind of confused how to do that. Any ideas? Thanks.

推荐答案

当调用打印类型(decoded_msg ['msg_type'])时,我得到的是结果而不是原始的MSG_TYPTE类型.

When calling print type(decoded_msg['msg_type']), I get the result instead of the original MSG_TYPTE type.

是的,那是因为您告诉 MSG_TYPE 这样编码自己:

Well, yeah, that's because you told MSG_TYPE to encode itself like this:

def __json__(self):
    return str(self)

因此,这显然将解码回字符串.如果您不想这样做,可以想出一些独特的方法来对值进行编码,而不仅仅是对它们的字符串表示形式进行编码.

So, that's obviously going to decode back to a string. If you don't want that, come up with some unique way to encode the values, instead of just encoding their string representations.

最常见的方法是使用某种特殊形式的 object 对所有自定义类型(包括枚举类型)进行编码-就像您对 Message .例如,您可以在 object 中放置一个 py-type 字段,该字段对您的对象的类型进行编码,然后其他字段的含义都取决于该类型.理想情况下,您将希望抽象出通用性,而不是将同一事物进行硬编码100次.

The most common way to do this is to encode all of your custom types (including your enum types) using some specialized form of object—just like you've done for Message. For example, you might put a py-type field in the object which encodes the type of your object, and then the meanings of the other fields all depend on the type. Ideally you'll want to abstract out the commonalities instead of hardcoding the same thing 100 times, of course.

我觉得我也应该写一个自定义的json解码器,但是如何做到这一点却很困惑.

I feel like I should also write a custom json decoder but kind of confused how to do that.

好吧,您阅读过文档吗?你到底在哪里困惑?通过跟踪StackOverflow问题,您将不会获得完整的教程.

Well, have you read the documentation? Where exactly are you confused? You're not going to get a complete tutorial by tacking on a followup to a StackOverflow question…

假设所有类型都有特殊的 object 结构,则可以使用 object_hook 将值解码回原始值.例如,作为一个快速的技巧:

Assuming you've got a special object structure for all your types, you can use an object_hook to decode the values back to the originals. For example, as a quick hack:

class MessageEncoder(JSONEncoder):
    def default(self, obj):
        return {'py-type': type(obj).__name__, 'value': obj.__json__()}

class MessageDecoder(JSONDecoder):
    def __init__(self, hook=None, *args, **kwargs):
        if hook is None: hook = self.hook
        return super().__init__(hook, *args, **kwargs)
    def hook(self, obj):
        if isinstance(obj, dict):
            pytype = obj.get('py-type')
            if pytype:
                t = globals()[pytype]
                return t.__unjson__(**obj['value'])
        return obj

现在,在您的 Message 类中:

@classmethod
def __unjson__(cls, msg_type, src, dest, data):
    return cls(msg_type, src, dest, data)

您需要一个 MSG_TYPE .__ json __ 返回一个dict,也许只是 {'name':str(self)} ,然后是一个 __ unjson __ 的功能类似于 getattr(cls,name).

And you need a MSG_TYPE.__json__ that returns a dict, maybe just {'name': str(self)}, then an __unjson__ that does something like getattr(cls, name).

一个现实的解决方案可能应该是让类注册自己而不是按名称查找它们,或者应该处理按限定名称查找它们,而不是仅仅转到 globals().而且,您可能希望让事物编码为 object 以外的其他事物,或者,如果不是,则只是将 py-type 塞入对象,而不是将其包装在另一个对象中.可能还有其他方法可以使JSON更加紧凑和/或更具可读性.还有一点错误处理会很好.依此类推.

A real-life solution should probably either have the classes register themselves instead of looking them up by name, or should handle looking them up by qualified name instead of just going to globals(). And you may want to let things encode to something other than object—or, if not, to just cram py-type into the object instead of wrapping it in another one. And there may be other ways to make the JSON more compact and/or readable. And a little bit of error handling would be nice. And so on.

您可能想看看 jsonpickle 的实现-不是因为您想要做和它完全一样的事情,但是要看它如何把所有的东西都钩在一起.

You may want to look at the implementation of jsonpickle—not because you want to do the exact same thing it does, but to see how it hooks up all the pieces.

这篇关于Python:如何从json解码枚举类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆