From ed6d588518197162d8d500e5d2d0cbb07789cfe3 Mon Sep 17 00:00:00 2001 From: cogwheel0 <172976095+cogwheel0@users.noreply.github.com> Date: Tue, 9 Dec 2025 22:35:07 +0530 Subject: [PATCH] feat(models): Add safe parsing for JSON deserialization --- lib/core/models/chat_message.dart | 55 +++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 6 deletions(-) diff --git a/lib/core/models/chat_message.dart b/lib/core/models/chat_message.dart index 8111302..424678e 100644 --- a/lib/core/models/chat_message.dart +++ b/lib/core/models/chat_message.dart @@ -114,8 +114,9 @@ abstract class ChatCodeExecution with _$ChatCodeExecution { @JsonKey(fromJson: _nullableString) String? name, @JsonKey(fromJson: _nullableString) String? language, @JsonKey(fromJson: _nullableString) String? code, + @JsonKey(fromJson: _safeCodeExecutionResult) ChatCodeExecutionResult? result, - Map? metadata, + @JsonKey(fromJson: _safeJsonMap) Map? metadata, }) = _ChatCodeExecution; factory ChatCodeExecution.fromJson(Map json) => @@ -125,12 +126,12 @@ abstract class ChatCodeExecution with _$ChatCodeExecution { @freezed abstract class ChatCodeExecutionResult with _$ChatCodeExecutionResult { const factory ChatCodeExecutionResult({ - String? output, - String? error, + @JsonKey(fromJson: _nullableString) String? output, + @JsonKey(fromJson: _nullableString) String? error, @JsonKey(fromJson: _executionFilesFromJson, toJson: _executionFilesToJson) @Default([]) List files, - Map? metadata, + @JsonKey(fromJson: _safeJsonMap) Map? metadata, }) = _ChatCodeExecutionResult; factory ChatCodeExecutionResult.fromJson(Map json) => @@ -142,7 +143,7 @@ abstract class ChatExecutionFile with _$ChatExecutionFile { const factory ChatExecutionFile({ @JsonKey(fromJson: _nullableString) String? name, @JsonKey(fromJson: _nullableString) String? url, - Map? metadata, + @JsonKey(fromJson: _safeJsonMap) Map? metadata, }) = _ChatExecutionFile; factory ChatExecutionFile.fromJson(Map json) => @@ -157,7 +158,7 @@ abstract class ChatSourceReference with _$ChatSourceReference { @JsonKey(fromJson: _nullableString) String? url, @JsonKey(fromJson: _nullableString) String? snippet, @JsonKey(fromJson: _nullableString) String? type, - Map? metadata, + @JsonKey(fromJson: _safeJsonMap) Map? metadata, }) = _ChatSourceReference; factory ChatSourceReference.fromJson(Map json) => @@ -324,3 +325,45 @@ String? _nullableString(dynamic value) { final str = value.toString(); return str.isEmpty ? null : str; } + +/// Safely parse a `Map` from various formats. +/// Returns null if the value cannot be converted to a valid map or is empty. +Map? _safeJsonMap(dynamic value) { + if (value == null) return null; + if (value is Map) { + return value.isEmpty ? null : value; + } + if (value is Map) { + final result = {}; + value.forEach((key, v) { + result[key.toString()] = v; + }); + return result.isEmpty ? null : result; + } + return null; +} + +/// Safely parse a ChatCodeExecutionResult from various formats. +/// Returns null if the value cannot be converted to a valid result. +ChatCodeExecutionResult? _safeCodeExecutionResult(dynamic value) { + if (value == null) return null; + if (value is Map) { + try { + return ChatCodeExecutionResult.fromJson(value); + } catch (_) { + return null; + } + } + if (value is Map) { + try { + final map = {}; + value.forEach((key, v) { + map[key.toString()] = v; + }); + return ChatCodeExecutionResult.fromJson(map); + } catch (_) { + return null; + } + } + return null; +}