|
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. |
| 1 | +/// Utility for type-safe JSON conversions with generic support. |
6 | 2 | ///
|
7 |
| -/// This class provides methods to convert JSON strings to strongly-typed objects |
8 |
| -/// and vice versa, with proper error handling and type safety. |
| 3 | +/// Provides strongly-typed parsing and serialization to prevent runtime errors |
| 4 | +/// when working with dynamic JSON data structures. |
9 | 5 | 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 |
| 6 | + /// Converts JSON map to strongly-typed map using provided constructor. |
82 | 7 | ///
|
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, |
| 8 | + /// Use this when you need to parse a collection of JSON objects into |
| 9 | + /// a specific type while maintaining type safety. |
| 10 | + static Map<String, T> parseMap<T>( |
| 11 | + Map<String, dynamic> jsonMap, |
| 12 | + T Function(Map<String, dynamic>) fromJson, |
95 | 13 | ) {
|
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 |
| - } |
| 14 | + return jsonMap.map( |
| 15 | + (key, value) => MapEntry(key, fromJson(value as Map<String, dynamic>)), |
| 16 | + ); |
106 | 17 | }
|
107 | 18 |
|
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 |
| 19 | + /// Converts typed map to JSON-serializable format using provided serializer. |
112 | 20 | ///
|
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, |
| 21 | + /// Use this when you need to serialize a collection of typed objects |
| 22 | + /// back to JSON format for storage or transmission. |
| 23 | + static Map<String, dynamic> mapToJson<T>( |
| 24 | + Map<String, T> items, |
| 25 | + Map<String, dynamic> Function(T) toJson, |
125 | 26 | ) {
|
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 |
| - } |
| 27 | + return items.map( |
| 28 | + (key, value) => MapEntry(key, toJson(value)), |
| 29 | + ); |
168 | 30 | }
|
169 | 31 | }
|
0 commit comments