首页 > 解决方案 > 编写多个 try 子句以将 json 字符串对象转换为数据类的更好方法是什么?

问题描述

我有一个函数可以接收具有不同结构和/或字段名称的多个不同的 json 字符串对象,如下所示:

event = '{"userId": "TDQIQb2fQaORKvCyepDYoZgsoEE3", "profileIsCreated": true}'

或者

event = '{"userId": "TDQIQb2fQaORKvCyepDYoZgsoEE3", "signUpFinished": true}'

我有这样的数据类:

from dataclasses import dataclass, field


@dataclass_json(letter_case=LetterCase.CAMEL)
@dataclass(frozen=True)
class UserId:
    userId: str


@dataclass_json(letter_case=LetterCase.CAMEL)
@dataclass(frozen=True)
class SignUpFinished(UserId):
    signUpFinished: bool


@dataclass_json(letter_case=LetterCase.CAMEL)
@dataclass(frozen=True)
class UserProfileCreated(UserId):
    profileIsCreated: bool

目前,我编写函数的方式是这样的:

def cast_event(event):
    user_details = None

    try:
        user_details = SignUpFinished.from_json(event)
    except KeyError:
        pass

    try:
        user_details = UserProfileCreated.from_json(event)
    except KeyError:
        pass

    if user_details:
        return "OK"
    else:
        return "UNHANDLED"

问题是,随着我要处理的事件越来越多,我的函数会变得越来越长,然而,它只是做同样的事情。

有没有更好的方法来实现我想要实现的目标?


我已经检查了一些 SO 问题:

但它们似乎不是试图实现我想要的最佳方式。

标签: pythonjsonpython-3.xtry-exceptpython-dataclasses

解决方案


虽然循环方法可以按要求解决您的问题,但如果您首先不需要“蛮力”方法来反序列化数据,那会好得多。为此,您需要一个明确地帮助您确定您正在处理的数据结构类型的字段。例如:

event = {'event': 'profile',
         'data': {'userId': 'TDQIQb2fQaORKvCyepDYoZgsoEE3', 'profileIsCreated': True}}

在这里,事件'profile'后面总是会跟着一个带有键'userId'和的对象'profileIsCreated'。这是您的事件消息应该做出的保证,然后解析它们就很简单了:

event_map = {
    'profile': UserProfileCreated,
    ...
}

return event_map[event['event']](**event['data'])

请注意,我在这里跳过了 JSON 解析步骤。您需要先解析 JSON 以评估其event密钥,因此使用dataclass_json可能是多余的/没有用处。


推荐阅读