Skip to content

Commit a1c7993

Browse files
feat(json): implement JsonHandler for robust JSON conversion and validation utilities
1 parent 85a5ee8 commit a1c7993

File tree

2 files changed

+839
-0
lines changed

2 files changed

+839
-0
lines changed

lib/utils/json_handler.dart

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
import 'dart:convert';
2+
3+
import 'package:flutter_policy_engine/utils/log_handler.dart';
4+
5+
/// A utility class for handling JSON conversions with generic type support.
6+
///
7+
/// This class provides methods to convert JSON strings to strongly-typed objects
8+
/// and vice versa, with proper error handling and type safety.
9+
class JsonHandler {
10+
/// Converts a JSON string to an object of type T.
11+
///
12+
/// [jsonString] - The JSON string to parse
13+
/// [fromJson] - A factory function that creates an instance of T from a Map
14+
///
15+
/// Returns an instance of T if successful, null otherwise.
16+
///
17+
/// Example:
18+
/// ```dart
19+
/// final policy = JsonHandler.fromJson<Policy>(
20+
/// jsonString,
21+
/// (json) => Policy.fromJson(json),
22+
/// );
23+
/// ```
24+
static T? fromJson<T>(
25+
String jsonString,
26+
T Function(Map<String, dynamic> json) fromJson,
27+
) {
28+
try {
29+
final Map<String, dynamic> jsonMap = jsonDecode(jsonString);
30+
return fromJson(jsonMap);
31+
} on FormatException catch (e) {
32+
LogHandler.error('JSON format error: $e');
33+
return null;
34+
} on TypeError catch (e) {
35+
LogHandler.error('Type conversion error: $e');
36+
return null;
37+
} catch (e) {
38+
LogHandler.error('Stack trace: ${e.toString()}');
39+
return null;
40+
}
41+
}
42+
43+
/// Converts a JSON string to a list of objects of type T.
44+
///
45+
/// [jsonString] - The JSON string to parse (should be a JSON array)
46+
/// [fromJson] - A factory function that creates an instance of T from a Map
47+
///
48+
/// Returns a List<T> if successful, empty list otherwise.
49+
///
50+
/// Example:
51+
/// ```dart
52+
/// final policies = JsonHandler.fromJsonList<Policy>(
53+
/// jsonString,
54+
/// (json) => Policy.fromJson(json),
55+
/// );
56+
/// ```
57+
static List<T> fromJsonList<T>(
58+
String jsonString,
59+
T Function(Map<String, dynamic> json) fromJson,
60+
) {
61+
try {
62+
final List<dynamic> jsonList = jsonDecode(jsonString);
63+
return jsonList
64+
.map((item) => fromJson(item as Map<String, dynamic>))
65+
.toList();
66+
} on FormatException catch (e) {
67+
LogHandler.error('JSON format error: $e');
68+
return [];
69+
} on TypeError catch (e) {
70+
LogHandler.error('Type conversion error: $e');
71+
return [];
72+
} catch (e) {
73+
LogHandler.error('Stack trace: ${e.toString()}');
74+
return [];
75+
}
76+
}
77+
78+
/// Converts an object to a JSON string.
79+
///
80+
/// [object] - The object to convert
81+
/// [toJson] - A function that converts the object to a Map
82+
///
83+
/// Returns a JSON string if successful, null otherwise.
84+
///
85+
/// Example:
86+
/// ```dart
87+
/// final jsonString = JsonHandler.toJson<Policy>(
88+
/// policy,
89+
/// (policy) => policy.toJson(),
90+
/// );
91+
/// ```
92+
static String? toJson<T>(
93+
T object,
94+
Map<String, dynamic> Function(T object) toJson,
95+
) {
96+
try {
97+
final Map<String, dynamic> jsonMap = toJson(object);
98+
return jsonEncode(jsonMap);
99+
} on TypeError catch (e) {
100+
LogHandler.error('Type conversion error: $e');
101+
return null;
102+
} catch (e) {
103+
LogHandler.error('Stack trace: ${e.toString()}');
104+
return null;
105+
}
106+
}
107+
108+
/// Converts a list of objects to a JSON string.
109+
///
110+
/// [objects] - The list of objects to convert
111+
/// [toJson] - A function that converts an object to a Map
112+
///
113+
/// Returns a JSON string if successful, null otherwise.
114+
///
115+
/// Example:
116+
/// ```dart
117+
/// final jsonString = JsonHandler.toJsonList<Policy>(
118+
/// policies,
119+
/// (policy) => policy.toJson(),
120+
/// );
121+
/// ```
122+
static String? toJsonList<T>(
123+
List<T> objects,
124+
Map<String, dynamic> Function(T object) toJson,
125+
) {
126+
try {
127+
final List<Map<String, dynamic>> jsonList =
128+
objects.map((object) => toJson(object)).toList();
129+
return jsonEncode(jsonList);
130+
} on TypeError catch (e) {
131+
LogHandler.error('Type conversion error: $e');
132+
return null;
133+
} catch (e) {
134+
LogHandler.error('Stack trace: ${e.toString()}');
135+
return null;
136+
}
137+
}
138+
139+
/// Safely parses a JSON string and returns the raw Map.
140+
///
141+
/// [jsonString] - The JSON string to parse
142+
///
143+
/// Returns a Map<String, dynamic> if successful, null otherwise.
144+
static Map<String, dynamic>? parseJson(String jsonString) {
145+
try {
146+
return jsonDecode(jsonString) as Map<String, dynamic>;
147+
} on FormatException catch (e) {
148+
LogHandler.error('JSON format error: $e');
149+
return null;
150+
} catch (e) {
151+
LogHandler.error('Stack trace: ${e.toString()}');
152+
return null;
153+
}
154+
}
155+
156+
/// Validates if a string is valid JSON.
157+
///
158+
/// [jsonString] - The string to validate
159+
///
160+
/// Returns true if the string is valid JSON, false otherwise.
161+
static bool isValidJson(String jsonString) {
162+
try {
163+
jsonDecode(jsonString);
164+
return true;
165+
} catch (e) {
166+
return false;
167+
}
168+
}
169+
}

0 commit comments

Comments
 (0)