jsonUtils.dart 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. import 'dart:convert';
  2. class JsonUtils {
  3. static String encodeJson(Object? value, {
  4. Object? Function(dynamic object)? toEncodable,
  5. }) {
  6. return json.encode(value, toEncodable: toEncodable);
  7. }
  8. static dynamic decodeJson(String source, {
  9. Object? Function(Object? key, Object? value)? reviver,
  10. }) {
  11. return removeNullValues(json.decode(source, reviver: reviver));
  12. }
  13. /// 递归移除 JSON 对象中的 null 字段,保持数组顺序并保留数组中的 null。
  14. /// 顶层 null 会原样返回,由调用方决定其业务含义。
  15. static dynamic removeNullValues(dynamic value) {
  16. if (value is Map) {
  17. final Map result = value is Map<String, dynamic>
  18. ? <String, dynamic>{}
  19. : <dynamic, dynamic>{};
  20. value.forEach((key, nestedValue) {
  21. if (nestedValue != null) {
  22. result[key] = removeNullValues(nestedValue);
  23. }
  24. });
  25. return result;
  26. }
  27. if (value is List) {
  28. return value.map(removeNullValues).toList();
  29. }
  30. return value;
  31. }
  32. static String getString(Map? map, String key, {String defaultValue = ''}) {
  33. if (map == null || !map.containsKey(key)) return defaultValue;
  34. final value = map[key];
  35. if (value == null) return defaultValue;
  36. return value.toString();
  37. }
  38. static String? tryGetString(Map? map, String key) {
  39. if (map == null || !map.containsKey(key)) return null;
  40. final value = map[key];
  41. if (value == null) return null;
  42. return value.toString();
  43. }
  44. static int getInt(Map? map, String key, {int defaultValue = 0}) {
  45. if (map == null || !map.containsKey(key)) return defaultValue;
  46. final value = map[key];
  47. if (value == null) return defaultValue;
  48. if (value is int) return value;
  49. return int.tryParse(value.toString()) ?? defaultValue;
  50. }
  51. static int? tryGetInt(Map? map, String key) {
  52. if (map == null || !map.containsKey(key)) return null;
  53. final value = map[key];
  54. if (value == null) return null;
  55. if (value is int) return value;
  56. return int.tryParse(value.toString());
  57. }
  58. static DateTime getDateTime(Map? map, String key) {
  59. DateTime defaultValue = DateTime.now();
  60. if (map == null || !map.containsKey(key)) return defaultValue;
  61. final value = map[key];
  62. if (value == null) return defaultValue;
  63. if (value is int) return DateTime.fromMillisecondsSinceEpoch(value);
  64. if (value is String) {
  65. final timestamp = int.tryParse(value);
  66. if (timestamp != null) {
  67. return DateTime.fromMillisecondsSinceEpoch(timestamp);
  68. }
  69. }
  70. final dateTime = DateTime.tryParse(value.toString());
  71. return dateTime ?? defaultValue;
  72. }
  73. static DateTime? tryGetDateTime(Map? map, String key) {
  74. DateTime? defaultValue;
  75. if (map == null || !map.containsKey(key)) return defaultValue;
  76. final value = map[key];
  77. if (value == null) return defaultValue;
  78. if (value is int) return DateTime.fromMillisecondsSinceEpoch(value);
  79. if (value is String) {
  80. final timestamp = int.tryParse(value);
  81. if (timestamp != null) {
  82. return DateTime.fromMillisecondsSinceEpoch(timestamp);
  83. }
  84. }
  85. final dateTime = DateTime.tryParse(value.toString());
  86. return dateTime ?? defaultValue;
  87. }
  88. /// ==================== Enum 通用转换方法 ====================
  89. /// 将枚举值转换为字符串
  90. /// 示例:
  91. /// enum Status { active, inactive }
  92. /// String json = JsonUtils.enumToJson(Status.active); // "active"
  93. ///
  94. static String enumToJson<T extends Enum>(T value) {
  95. return value.name;
  96. }
  97. /// 将字符串转换为枚举值(带默认值)
  98. ///
  99. /// 参数:
  100. /// - [values]: 枚举的所有值,通过 EnumType.values 传入
  101. /// - [name]: 要转换的字符串
  102. /// - [defaultValue]: 解析失败时的默认值
  103. /// 示例:
  104. /// enum ApiVersion { v1, v2, v3 }
  105. /// var version = JsonUtils.jsonToEnum(
  106. /// ApiVersion.values,
  107. /// 'v2',
  108. /// defaultValue: ApiVersion.v1,
  109. /// );
  110. ///
  111. static T jsonToEnum<T extends Enum>(List<T> values, String? name, {
  112. required T defaultValue,
  113. }) {
  114. if (name == null || name.isEmpty) {
  115. return defaultValue;
  116. }
  117. return values.firstWhere(
  118. (e) => e.name.toLowerCase() == name.toLowerCase(),
  119. orElse: () => defaultValue,
  120. );
  121. }
  122. /// 将字符串转换为可空的枚举值(解析失败返回 null)
  123. /// 示例:
  124. /// enum Priority { low, medium, high } /// var priority = JsonUtils.tryJsonToEnum(Priority.values, 'medium'); ///
  125. static T? tryJsonToEnum<T extends Enum>(List<T> values, String? name) {
  126. if (name == null || name.isEmpty) {
  127. return null;
  128. }
  129. return values.firstWhere(
  130. (e) => e.name.toLowerCase() == name.toLowerCase(),
  131. orElse: () => throw StateError('No matching enum value'),
  132. );
  133. }
  134. /// 从 Map 中安全地获取枚举值(带默认值)
  135. /// 示例:
  136. /// var apiVersion = JsonUtils.getEnumFromMap(
  137. /// map,
  138. /// 'api_version',
  139. /// ApiVersion.values,
  140. /// defaultValue: ApiVersion.v1,
  141. /// );
  142. ///
  143. static T getEnumFromMap<T extends Enum>(
  144. Map? map,
  145. String key,
  146. List<T> values, {
  147. required T defaultValue,
  148. }) {
  149. if (map == null || !map.containsKey(key)) {
  150. return defaultValue;
  151. }
  152. final name = map[key]?.toString();
  153. return jsonToEnum(values, name, defaultValue: defaultValue);
  154. }
  155. /// 从 Map 中安全地获取可空的枚举值
  156. /// 示例:
  157. /// var priority = JsonUtils.tryGetEnumFromMap(
  158. /// map,
  159. /// 'priority',
  160. /// Priority.values,
  161. /// );
  162. ///
  163. static T? tryGetEnumFromMap<T extends Enum>(
  164. Map? map,
  165. String key,
  166. List<T> values,
  167. ) {
  168. if (map == null || !map.containsKey(key)) {
  169. return null;
  170. }
  171. final name = map[key]?.toString();
  172. return tryJsonToEnum(values, name);
  173. }
  174. /// 将枚举值按索引转换为整数
  175. /// 示例:
  176. /// int index = JsonUtils.enumToInt(Status.active); // 0
  177. ///
  178. static int enumToInt<T extends Enum>(T value) {
  179. return value.index;
  180. }
  181. /// 将整数转换为枚举值(带默认值)
  182. /// 示例:
  183. /// var status = JsonUtils.intToEnum(
  184. /// Status.values,
  185. /// 1,
  186. /// defaultValue: Status.inactive,
  187. /// );
  188. ///
  189. static T intToEnum<T extends Enum>(
  190. List<T> values,
  191. int? index, {
  192. required T defaultValue,
  193. }) {
  194. if (index == null || index < 0 || index >= values.length) {
  195. return defaultValue;
  196. }
  197. return values.elementAt(index);
  198. }
  199. /// 从 Map 中安全地获取枚举值(通过整数索引)
  200. /// 示例:
  201. /// var status = JsonUtils.getEnumFromMapByInt(
  202. /// map,
  203. /// 'status_index',
  204. /// Status.values,
  205. /// defaultValue: Status.inactive,
  206. /// );
  207. ///
  208. static T getEnumFromMapByInt<T extends Enum>(
  209. Map? map,
  210. String key,
  211. List<T> values, {
  212. required T defaultValue,
  213. }) {
  214. if (map == null || !map.containsKey(key)) {
  215. return defaultValue;
  216. }
  217. final index = getInt(map, key, defaultValue: -1);
  218. return intToEnum(values, index, defaultValue: defaultValue);
  219. }
  220. /// ==================== DateTime 转换 ====================
  221. /// int timestamp = JsonUtils.dateTimeToTimestamp(DateTime.now());
  222. /// // 例如: 1712134567890
  223. ///
  224. static int dateTimeToTimestamp(DateTime dateTime) {
  225. return dateTime.millisecondsSinceEpoch;
  226. }
  227. /// 将毫秒时间戳转换为 DateTime
  228. ///
  229. /// 参数:
  230. /// - [timestamp]: 毫秒时间戳
  231. ///
  232. /// 示例:
  233. /// DateTime date = JsonUtils.timestampToDateTime(1712134567890);
  234. ///
  235. static DateTime timestampToDateTime(int timestamp) {
  236. return DateTime.fromMillisecondsSinceEpoch(timestamp);
  237. }
  238. /// 将 DateTime 转换为秒时间戳(整数)
  239. ///
  240. /// 示例:
  241. ///
  242. /// int timestamp = JsonUtils.dateTimeToTimestampSeconds(DateTime.now());
  243. /// // 例如: 1712134567
  244. ///
  245. static int dateTimeToTimestampSeconds(DateTime dateTime) {
  246. return dateTime.millisecondsSinceEpoch ~/ 1000;
  247. }
  248. /// 将秒时间戳转换为 DateTime
  249. ///
  250. /// 参数:
  251. /// - [timestamp]: 秒时间戳
  252. ///
  253. /// 示例:
  254. ///
  255. /// DateTime date = JsonUtils.timestampSecondsToDateTime(1712134567);
  256. ///
  257. static DateTime timestampSecondsToDateTime(int timestamp) {
  258. return DateTime.fromMillisecondsSinceEpoch(timestamp * 1000);
  259. }
  260. /// 将 DateTime 转换为 ISO 8601 格式的字符串
  261. ///
  262. /// 示例:
  263. ///
  264. /// String iso = JsonUtils.dateTimeToIsoString(DateTime.now());
  265. /// // 例如: "2024-04-03T10:30:00.000Z"
  266. ///
  267. static String dateTimeToIsoString(DateTime dateTime) {
  268. return dateTime.toIso8601String();
  269. }
  270. /// 将 ISO 8601 格式的字符串转换为 DateTime
  271. ///
  272. /// 参数:
  273. /// - [isoString]: ISO 8601 格式的时间字符串
  274. /// - [defaultValue]: 解析失败时的默认值
  275. ///
  276. /// 示例:
  277. /// DateTime date = JsonUtils.isoStringToDateTime("2024-04-03T10:30:00.000Z");
  278. ///
  279. static DateTime isoStringToDateTime(
  280. String? isoString, {
  281. DateTime? defaultValue,
  282. }) {
  283. if (isoString == null || isoString.isEmpty) {
  284. return defaultValue ?? DateTime.now();
  285. }
  286. final dateTime = DateTime.tryParse(isoString);
  287. return dateTime ?? (defaultValue ?? DateTime.now());
  288. }
  289. /// 将可空的 ISO 8601 字符串转换为可空的 DateTime
  290. /// 示例:
  291. /// DateTime? date = JsonUtils.tryIsoStringToDateTime("2024-04-03T10:30:00.000Z");
  292. ///
  293. static DateTime? tryIsoStringToDateTime(String? isoString) {
  294. if (isoString == null || isoString.isEmpty) {
  295. return null;
  296. }
  297. return DateTime.tryParse(isoString);
  298. }
  299. /// 从 Map 中安全地获取时间戳并转换为 DateTime(带默认值)
  300. ///
  301. /// 参数:
  302. /// - [map]: 数据 Map
  303. /// - [key]: 时间戳字段的 key
  304. /// - [defaultValue]: 解析失败时的默认值
  305. /// - [isSeconds]: 是否为秒时间戳(默认为 false,即毫秒时间戳)
  306. ///
  307. /// 示例:
  308. /// DateTime createTime = JsonUtils.getDateTimeFromMap( /// map, /// 'create_time', /// defaultValue: DateTime.now(), /// ); ///
  309. static DateTime getDateTimeFromMap(
  310. Map? map,
  311. String key, {
  312. DateTime? defaultValue,
  313. bool isSeconds = false,
  314. }) {
  315. if (map == null || !map.containsKey(key)) {
  316. return defaultValue ?? DateTime.now();
  317. }
  318. final value = map[key];
  319. if (value == null) {
  320. return defaultValue ?? DateTime.now();
  321. }
  322. // 如果已经是 DateTime 类型,直接返回
  323. if (value is DateTime) {
  324. return value;
  325. }
  326. // 尝试解析为整数时间戳
  327. int timestamp;
  328. if (value is int) {
  329. timestamp = value;
  330. } else if (value is String) {
  331. final parsed = int.tryParse(value);
  332. if (parsed == null) {
  333. // 如果不是数字,尝试作为 ISO 字符串解析
  334. return isoStringToDateTime(value, defaultValue: defaultValue);
  335. }
  336. timestamp = parsed;
  337. } else {
  338. return defaultValue ?? DateTime.now();
  339. }
  340. // 根据时间戳类型转换
  341. if (isSeconds) {
  342. return timestampSecondsToDateTime(timestamp);
  343. } else {
  344. return timestampToDateTime(timestamp);
  345. }
  346. }
  347. /// 从 Map 中安全地获取时间戳并转换为可空的 DateTime
  348. /// 示例:
  349. /// DateTime? updateTime = JsonUtils.tryGetDateTimeFromMap(map, 'update_time'); ///
  350. static DateTime? tryGetDateTimeFromMap(
  351. Map? map,
  352. String key, {
  353. bool isSeconds = false,
  354. }) {
  355. if (map == null || !map.containsKey(key)) {
  356. return null;
  357. }
  358. final value = map[key];
  359. if (value == null) {
  360. return null;
  361. }
  362. // 如果已经是 DateTime 类型,直接返回
  363. if (value is DateTime) {
  364. return value;
  365. }
  366. // 尝试解析为整数时间戳
  367. int timestamp;
  368. if (value is int) {
  369. timestamp = value;
  370. } else if (value is String) {
  371. final parsed = int.tryParse(value);
  372. if (parsed == null) {
  373. // 如果不是数字,尝试作为 ISO 字符串解析
  374. return tryIsoStringToDateTime(value);
  375. }
  376. timestamp = parsed;
  377. } else {
  378. return null;
  379. }
  380. // 根据时间戳类型转换
  381. if (isSeconds) {
  382. return timestampSecondsToDateTime(timestamp);
  383. } else {
  384. return timestampToDateTime(timestamp);
  385. }
  386. }
  387. }