将一个Python字典转换为正确的Python基础模型(BaseModel)pydantic类

huangapple go评论116阅读模式
英文:

Convert a python dict to correct python BaseModel pydantic class

问题

我要创建一个SendNotificationChannel实例,其中正确设置conditional_config,以使condition_prop成为ConditionalExpressionProps或CycleDurationTrendProps,根据字典的结构而定。例如,如果字典如下:

{
    "id": "1",
    "customer_id": "abc",
    "conditional_config": {
        "cond_type": "EXPRESSION",
        "conditional_expression": ".s_num>10"
    }
}

那么执行类似SendNotificationChannel(**dict)的操作应该将conditional_config.condition_prop设置为ConditionalExpressionProps,对于CycleDurationTrendProps也是类似的。

然而,当我这样做时,它却采用了BaseConditionalProps。

>>> channel = {"conditional_config": {"cond_type": "EXPRESSION", "condition_prop":{"conditional_expression":"ALPHA"}}}
>>> channel_obj = SendNotificationChannel(**channel)
>>> channel_obj
SendNotificationChannel(conditional_config=ConditionalConfig(cond_type=<ConditionType.EXPRESSION: 'EXPRESSION'>, condition_prop=BaseConditionalProps()))
>>> channel_obj.conditional_config.condition_prop
BaseConditionalProps()
>>>

我想知道有人如何解决这个问题,或者我是否在处理这个问题的方式上有误。

英文:

My requirement is to convert python dictionary which can take multiple forms into appropriate pydantic BaseModel class instance. Following are details:

class ConditionType(str, Enum):
    EXPRESSION = &#39;EXPRESSION&#39;
    CYCLE_DUR_TREND = &#39;CYCLE_DUR_TREND&#39;

class ConditionalExpressionProps(BaseConditionalProps):
    conditional_expression: str

class CycleDurationTrendProps(BaseConditionalProps):
    direction_up : bool = True
    n : int = Field(1, ge=1, le=1000)

class ConditionalConfig(BaseModel):
    cond_type: ConditionType = ConditionType.EXPRESSION
    condition_prop: BaseConditionalProps

class SendNotificationChannel(BaseModel):
    id: str
    customer_id: str
    conditional_config: Optional[ConditionalConfig]

I want to create a SendNotificationChannel instance with correct conditional_config set such that condition_prop becomes ConditionalExpressionProps or CycleDurationTrendProps based on the structure of dict.

For example, if dict is:

{
    &quot;id&quot; : &quot;1&quot;, 
    &quot;customer_id&quot; : &quot;abc&quot;, 
    &quot;conditional_config&quot; : {
        &quot;cond_type&quot;: &quot;EXPRESSION&quot;,
        &quot;conditional_expression&quot; : &quot;.s_num&gt;10&quot;
    }
}

then on doing something like SendNotificationChannel(**dict) should make the conditional_config.condition_prop of type ConditionalExpressionProps, and similarly for CycleDurationTrendProps.

However when I'm doing this, its taking BaseConditionalProps.

&gt;&gt;&gt; channel = {&quot;conditional_config&quot; : {&quot;cond_type&quot;: &quot;EXPRESSION&quot;, &quot;condition_prop&quot;:{&quot;conditional_expression&quot;:&quot;ALPHA&quot;}}}
&gt;&gt;&gt; channel_obj = SendNotificationChannel(**channel)
&gt;&gt;&gt; channel_obj
SendNotificationChannel(conditional_config=ConditionalConfig(cond_type=&lt;ConditionType.EXPRESSION: &#39;EXPRESSION&#39;&gt;, condition_prop=BaseConditionalProps()))
&gt;&gt;&gt; channel_obj.conditional_config.condition_prop
BaseConditionalProps()
&gt;&gt;&gt; 

I'd want to know how would someone solve this problem, or if I'm tackling this the incorrect way.

答案1

得分: 1

如果我正确理解您的问题,您可以使用 .parse_obj 方法来解决问题。此外,您需要更新 condition_prop 字段的类型。以下是示例代码:

from enum import Enum
from typing import Optional, Union

from pydantic import BaseModel, Field


class ConditionType(str, Enum):
    EXPRESSION = 'EXPRESSION'
    CYCLE_DUR_TREND = 'CYCLE_DUR_TREND'

class BaseConditionalProps(BaseModel):
    pass

class ConditionalExpressionProps(BaseConditionalProps):
    conditional_expression: str

class CycleDurationTrendProps(BaseConditionalProps):
    direction_up : bool = True
    n : int = Field(1, ge=1, le=1000)

class ConditionalConfig(BaseModel):
    cond_type: ConditionType = ConditionType.EXPRESSION
    condition_prop: Union[ConditionalExpressionProps, CycleDurationTrendProps]

class SendNotificationChannel(BaseModel):
    id: str
    customer_id: str
    conditional_config: Optional[ConditionalConfig]

channel_1 = {
    "id" : "1", 
    "customer_id" : "abc", 
    "conditional_config" : {
        "cond_type": "EXPRESSION",
        "condition_prop": {
            "conditional_expression" : ".s_num>10"
        }
    }
}

channel_1_obj = SendNotificationChannel.parse_obj(channel_1)
print(channel_1_obj)
# id='1' customer_id='abc' conditional_config=ConditionalConfig(cond_type=<ConditionType.EXPRESSION: 'EXPRESSION'>, condition_prop=ConditionalExpressionProps(conditional_expression='.s_num>10'))

channel_2 = {
    "id" : "2", 
    "customer_id" : "def", 
    "conditional_config" : {
        "cond_type": "CYCLE_DUR_TREND",
        "condition_prop": {
            "n" : 10
        }
    }
}

channel_2_obj = SendNotificationChannel.parse_obj(channel_2)
print(channel_2_obj)
# id='2' customer_id='def' conditional_config=ConditionalConfig(cond_type=<ConditionType.CYCLE_DUR_TREND: 'CYCLE_DUR_TREND'>, condition_prop=CycleDurationTrendProps(direction_up=True, n=10))
英文:

If I understand your question correctly you can to use .parse_obj method for your problem. Also you need to update the condition_prop field type. The following code it is example:

from enum import Enum
from typing import Optional, Union

from pydantic import BaseModel, Field


class ConditionType(str, Enum):
    EXPRESSION = &#39;EXPRESSION&#39;
    CYCLE_DUR_TREND = &#39;CYCLE_DUR_TREND&#39;

class BaseConditionalProps(BaseModel):
    pass

class ConditionalExpressionProps(BaseConditionalProps):
    conditional_expression: str

class CycleDurationTrendProps(BaseConditionalProps):
    direction_up : bool = True
    n : int = Field(1, ge=1, le=1000)

class ConditionalConfig(BaseModel):
    cond_type: ConditionType = ConditionType.EXPRESSION
    condition_prop: Union[ConditionalExpressionProps, CycleDurationTrendProps]

class SendNotificationChannel(BaseModel):
    id: str
    customer_id: str
    conditional_config: Optional[ConditionalConfig]


channel_1 = {
    &quot;id&quot; : &quot;1&quot;, 
    &quot;customer_id&quot; : &quot;abc&quot;, 
    &quot;conditional_config&quot; : {
        &quot;cond_type&quot;: &quot;EXPRESSION&quot;,
        &quot;condition_prop&quot;: {
            &quot;conditional_expression&quot; : &quot;.s_num&gt;10&quot;
        }
    }
}

channel_1_obj = SendNotificationChannel.parse_obj(channel_1)
print(channel_1_obj)
# id=&#39;1&#39; customer_id=&#39;abc&#39; conditional_config=ConditionalConfig(cond_type=&lt;ConditionType.EXPRESSION: &#39;EXPRESSION&#39;&gt;, condition_prop=ConditionalExpressionProps(conditional_expression=&#39;.s_num&gt;10&#39;))

channel_2 = {
    &quot;id&quot; : &quot;2&quot;, 
    &quot;customer_id&quot; : &quot;def&quot;, 
    &quot;conditional_config&quot; : {
        &quot;cond_type&quot;: &quot;CYCLE_DUR_TREND&quot;,
        &quot;condition_prop&quot;: {
            &quot;n&quot; : 10
        }
    }
}

channel_2_obj = SendNotificationChannel.parse_obj(channel_2)
print(channel_2_obj)
# id=&#39;2&#39; customer_id=&#39;def&#39; conditional_config=ConditionalConfig(cond_type=&lt;ConditionType.CYCLE_DUR_TREND: &#39;CYCLE_DUR_TREND&#39;&gt;, condition_prop=CycleDurationTrendProps(direction_up=True, n=10))

huangapple
  • 本文由 发表于 2023年1月6日 14:53:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/75027840.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定