binance-connector-python icon indicating copy to clipboard operation
binance-connector-python copied to clipboard

Fix issue #405

Open rocky-d opened this issue 4 months ago • 0 comments

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}

rocky-d avatar Sep 05 '25 13:09 rocky-d