deserializeFromString method
Converts a string JSON message into a WAMP message object.
Implementation
AbstractMessage? deserializeFromString(String jsonMessage) {
final singleBinaryPayload = _deserializeSingleBinaryPayloadFromString(
jsonMessage,
);
if (singleBinaryPayload != null) {
return singleBinaryPayload;
}
final message = _decodeJsonMessage(jsonMessage);
if (message is List) {
if (message.isEmpty) {
throw const FormatException('WAMP message type must be an integer');
}
final Object? rawMessageId = message[0];
if (rawMessageId is! int) {
throw const FormatException('WAMP message type must be an integer');
}
final messageId = rawMessageId;
if (messageId == MessageTypes.codeUnsubscribed && message.length == 2) {
return Unsubscribed(message[1], null);
}
if (messageId != MessageTypes.codePublish || message.length < 4) {
validateWampMessageMinimumFieldCount(messageId, message.length);
}
if (messageId == MessageTypes.codeHello) {
validateWampMessageFieldCount(message.length);
return Hello(
message[1] as String?,
_decodeDetailsMap(
_normalizeJsonStringKeyMap(message[2] as Map<dynamic, dynamic>),
),
);
}
if (messageId == MessageTypes.codeChallenge) {
validateWampMessageFieldCount(message.length);
final extraMap = message[2] is Map
? _normalizeJsonStringKeyMap(message[2] as Map<dynamic, dynamic>)
: const <String, dynamic>{};
return Challenge(message[1], Extra.fromMap(extraMap));
}
if (messageId == MessageTypes.codeAuthenticate) {
validateWampMessageFieldCount(message.length);
final extra = message[2];
if (extra is! Map || extra.keys.any((key) => key is! String)) {
throw const FormatException(
'AUTHENTICATE.Extra must be a dictionary with string keys',
);
}
return Authenticate(
signature: message[1] as String?,
)..extra = Map<String, Object?>.from(_normalizeJsonStringKeyMap(extra));
}
if (messageId == MessageTypes.codeWelcome) {
validateWampMessageFieldCount(message.length);
return Welcome(
message[1],
_decodeDetailsMap(
_normalizeJsonStringKeyMap(message[2] as Map<dynamic, dynamic>),
),
);
}
if (messageId == MessageTypes.codeRegister) {
validateWampMessageFieldCount(message.length);
return Register(
message[1],
message[3],
options: _decodeRegisterOptions(
_decodeRequiredOptionsMap(message[2], 'REGISTER'),
),
);
}
if (messageId == MessageTypes.codeUnregister) {
validateWampMessageFieldCount(message.length);
return Unregister(message[1], message[2]);
}
if (messageId == MessageTypes.codeCall) {
return _addPayload(
Call(
message[1],
message[3],
options: _decodeCallOptions(
_decodeRequiredOptionsMap(message[2], 'CALL'),
),
),
message,
4,
);
}
if (messageId == MessageTypes.codeYield) {
return _addPayload(
Yield(
message[1],
options: _decodeYieldOptions(
_decodeRequiredOptionsMap(message[2], 'YIELD'),
),
),
message,
3,
);
}
if (messageId == MessageTypes.codePublish) {
return _addPayload(
Publish(
message[1],
message[3],
options: _decodePublishOptions(
_decodeRequiredOptionsMap(message[2], 'PUBLISH'),
),
),
message,
4,
);
}
if (messageId == MessageTypes.codeRegistered) {
validateWampMessageFieldCount(message.length);
return registered_msg.Registered(message[1], message[2]);
}
if (messageId == MessageTypes.codeUnregistered) {
validateWampMessageFieldCount(message.length);
return unregistered_msg.Unregistered(message[1]);
}
if (messageId == MessageTypes.codeInvocation) {
final detailsMap = message[3] as Map<dynamic, dynamic>;
return _addPayload(
Invocation(
message[1],
message[2],
_decodeInvocationDetails(detailsMap),
),
message,
4,
);
}
if (messageId == MessageTypes.codeInterrupt) {
validateWampMessageFieldCount(message.length);
final optionsMap = _validateRequiredOptionsMap(
message[2],
'INTERRUPT',
);
return interrupt_msg.Interrupt(
message[1],
options: (() {
final options = interrupt_msg.InterruptOptions();
options.mode = optionsMap['mode'] as String?;
return options;
})(),
);
}
if (messageId == MessageTypes.codeCancel) {
validateWampMessageFieldCount(message.length);
final optionsMap = _validateRequiredOptionsMap(message[2], 'CANCEL');
return cancel_msg.Cancel(
message[1],
options: (() {
final options = cancel_msg.CancelOptions();
options.mode = optionsMap['mode'] as String?;
return options;
})(),
);
}
if (messageId == MessageTypes.codeResult) {
final detailsMap = message[2] as Map<dynamic, dynamic>;
final progress = detailsMap['progress'];
final pptScheme = detailsMap['ppt_scheme'];
final pptSerializer = detailsMap['ppt_serializer'];
final pptCipher = detailsMap['ppt_cipher'];
final pptKeyId = detailsMap['ppt_keyid'];
return _addPayload(
Result(
message[1],
ResultDetails(
progress: progress,
pptScheme: pptScheme,
pptSerializer: pptSerializer,
pptCipher: pptCipher,
pptKeyId: pptKeyId,
custom: _extractCustomDetails(detailsMap, _resultDetailKeys),
),
),
message,
3,
);
}
if (messageId == MessageTypes.codePublished) {
validateWampMessageFieldCount(message.length);
return Published(message[1], message[2]);
}
if (messageId == MessageTypes.codeSubscribe) {
validateWampMessageFieldCount(message.length);
return Subscribe(
message[1],
message[3],
options: _decodeSubscribeOptions(
_decodeRequiredOptionsMap(message[2], 'SUBSCRIBE'),
),
);
}
if (messageId == MessageTypes.codeSubscribed) {
validateWampMessageFieldCount(message.length);
return Subscribed(message[1], message[2]);
}
if (messageId == MessageTypes.codeUnsubscribe) {
validateWampMessageFieldCount(message.length);
return Unsubscribe(message[1], message[2]);
}
if (messageId == MessageTypes.codeUnsubscribed) {
validateWampMessageFieldCount(message.length);
return Unsubscribed(
message[1],
UnsubscribedDetails(
message[2]['subscription'],
message[2]['reason'],
),
);
}
if (messageId == MessageTypes.codeEvent) {
final detailsMap = message[3] as Map<dynamic, dynamic>;
return _addPayload(
Event(
message[1],
message[2],
_decodeEventDetails(detailsMap),
),
message,
4,
);
}
if (messageId == MessageTypes.codeError) {
return _addPayload(
Error(
message[1],
message[2],
_normalizeJsonStringKeyMap(message[3] as Map<dynamic, dynamic>),
message[4],
),
message,
5,
);
}
if (messageId == MessageTypes.codeAbort) {
validateWampMessageFieldCount(message.length);
final details = message.length > 1 && message[1] != null
? _normalizeJsonStringKeyMap(message[1] as Map<dynamic, dynamic>)
: <String, Object?>{};
final reason = message.length > 2 ? message[2] as String : '';
List<dynamic>? arguments;
Map<String, Object?>? argumentsKeywords;
if (message.length > 3 && message[3] != null) {
arguments = List<dynamic>.from(message[3] as List);
}
if (message.length > 4 && message[4] != null) {
argumentsKeywords = Map<String, Object?>.from(
message[4] as Map<String, dynamic>,
);
}
final messageText = details['message'] as String?;
return Abort(
reason,
details: details,
message: messageText,
arguments: arguments,
argumentsKeywords: argumentsKeywords,
);
}
if (messageId == MessageTypes.codeGoodbye) {
validateWampMessageFieldCount(message.length);
return Goodbye(
_decodeGoodbyeMessage(
message.length > 1 && message[1] is Map
? message[1] as Map<dynamic, dynamic>
: null,
),
message[2],
);
}
}
_logger.shout(
'Could not deserialize JSON WAMP message (${jsonMessage.length} chars)',
);
// TODO respond with an error
return null;
}