Skip to content

Conversation

@rocky-d
Copy link

@rocky-d rocky-d commented Sep 5, 2025

Fix issue #405

# the issue:
s = '{"e": "ORDER_TRADE_UPDATE", "E": 1568879465651, "T": 1568879465650, "o": {"s": "BTCUSDT", "c": "TEST", "S": "SELL", "o": "TRAILING_STOP_MARKET", "f": "GTC", "q": "0.001", "p": "0", "ap": "0", "sp": "7103.04", "x": "NEW", "X": "NEW", "i": 8886774, "l": "0", "z": "0", "L": "0", "N": "USDT", "n": "0", "T": 1568879465650, "t": 0, "b": "0", "a": "9.91", "m": false, "R": false, "wt": "CONTRACT_PRICE", "ot": "TRAILING_STOP_MARKET", "ps": "LONG", "cp": false, "AP": "7476.89", "cr": "5.0", "pP": false, "si": 0, "ss": 0, "rp": "0", "V": "EXPIRE_TAKER", "pm": "OPPONENT", "gtd": 0}}'
x = UserDataStreamEventsResponse.model_validate_json(s)
print(x)  # oneof_schema_1_validator=None oneof_schema_2_validator=None oneof_schema_3_validator=None oneof_schema_4_validator=None onee one_of_schemas={'TradeLite', 'OrderTradeUof_schema_5_validator=None oneof_schema_6_validator=None oneof_schema_7_validator=None oneof_schema_8_validator=None oneof_l', 'Listenkeyexpired'} discriminator_valueschema_9_validator=None actual_instance=None one_of_schemas={'TradeLite', 'OrderTradeUpdate', 'AccountConfigUpdate', 'StrategyUpdate', 'AccountUpdate', 'GridUpdate', 'ConditionalOrderTriggerReject', 'MarginCall', 'Listenkeyexpired'} discriminatorof_schema_5_validator=None oneof_schema_6_v_value_class_map={}

# should be:
s = '{"actual_instance": ' + s + '}'
x = UserDataStreamEventsResponse.model_validate_json(s)
print(x)  # oneof_schema_1_validator=None oneof_schema_2_validator=None oneof_schema_3_validator=None oneof_schema_4_validator=None one7103.04', x='NEW', X='NEW', i=8886774, l='0of_schema_5_validator=None oneof_schema_6_validator=None oneof_schema_7_validator=None oneof_schema_8_validator=None oneof_G_STOP_MARKET', ps='LONG', cp=False, AP='74schema_9_validator=None actual_instance=OrderTradeUpdate(E=1568879465651, T=1568879465650, o=OrderTradeUpdateO(s='BTCUSDT',al_properties={}) one_of_schemas={'TradeLit c='TEST', S='SELL', o='TRAILING_STOP_MARKET', f='GTC', q='0.001', p='0', ap='0', sp='7103.04', x='NEW', X='NEW', i=8886774ect', 'MarginCall', 'Listenkeyexpired'} dis, l='0', z='0', L='0', N='USDT', n='0', T=1568879465650, t=0, b='0', a='9.91', m=False, R=False, wt='CONTRACT_PRICE', ot='TRAILING_STOP_MARKET', ps='LONG', cp=False, AP='7476.89', cr='5.0', pP=False, si=0, ss=0, rp='0', V='EXPIRE_TAKER', pm='OPPONENT', gtd=0, additional_properties={}), additional_properties={}) one_of_schemas={'TradeLite', 'OrderTradeUpdate', 'AccountConfigUpdate', 'StrategyUpdate', 'AccountUpdate', 'GridUpdate', 'ConditionalOrderTriggerReject', 'MarginCall', 'Listenkeyexpired'} discriminator_value_class_map={}

The input data should be first wrapped with "actual_instance". So that the validator can identify it correctly.

I used @model_validator(mode="before") to fix this issue.

Advantages:

  1. Automatic data wrapping: Callers can directly pass raw JSON data without preprocessing.
  2. Encapsulation: Callers don't need to know about the internal details.
  3. Minimal implementation cost: It only adds a single @model_validator function (3 lines of code).
class UserDataStreamEventsResponse(BaseModel):

    # existing code

    @model_validator(mode="before")
    def wrap_actual_instance(cls, values):
        return {"actual_instance": values}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant