From b53638dd7a36b4c61fe49e344d64ee8778dd5f75 Mon Sep 17 00:00:00 2001 From: Kevin Date: Wed, 7 Aug 2024 18:58:21 +0800 Subject: [PATCH] fix: handle decoding error in JSON.parse --- lib/g_json.dart | 14 +++- pubspec.lock | 178 ++++++++++++++++++++++++-------------------- test/json_test.dart | 10 +++ 3 files changed, 121 insertions(+), 81 deletions(-) diff --git a/lib/g_json.dart b/lib/g_json.dart index 6586fa5..9aff8a5 100644 --- a/lib/g_json.dart +++ b/lib/g_json.dart @@ -17,6 +17,9 @@ class _JSONNilReason extends Error { _JSONNilReason.outOfBounds(int index) : message = 'List($index) Index is out of bounds.'; + _JSONNilReason.decode(dynamic error) + : message = 'decode error: ${error.toString()}'; + _JSONNilReason(this.message); @override @@ -183,6 +186,11 @@ class JSON { } static JSON nil = JSON(null); + static JSON nilWith(Error error) { + final j = JSON.nil; + j.error = error; + return j; + } /// Convenience method `type == Type.nil` bool get isNull => _type == Type.nil; @@ -320,7 +328,11 @@ class JSON { if (jsonStr.isEmpty) { return JSON.nil; } - return JSON(json.decode(jsonStr)); + try { + return JSON(json.decode(jsonStr)); + } catch (e) { + return JSON.nilWith(_JSONNilReason.decode(e)); + } } dynamic _unwrap(object) { diff --git a/pubspec.lock b/pubspec.lock index 7fcd7ab..b960b84 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,195 +5,191 @@ packages: dependency: transitive description: name: _fe_analyzer_shared + sha256: "36a321c3d2cbe01cbcb3540a87b8843846e0206df3e691fa7b23e19e78de6d49" url: "https://pub.flutter-io.cn" source: hosted - version: "14.0.0" + version: "65.0.0" analyzer: dependency: transitive description: name: analyzer + sha256: dfe03b90ec022450e22513b5e5ca1f01c0c01de9c3fba2f7fd233cb57a6b9a07 url: "https://pub.flutter-io.cn" source: hosted - version: "0.41.1" + version: "6.3.0" args: dependency: transitive description: name: args + sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 url: "https://pub.flutter-io.cn" source: hosted - version: "1.6.0" + version: "2.4.2" async: dependency: transitive description: name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" url: "https://pub.flutter-io.cn" source: hosted - version: "2.5.0-nullsafety.3" + version: "2.11.0" boolean_selector: dependency: transitive description: name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" url: "https://pub.flutter-io.cn" source: hosted - version: "2.1.0-nullsafety.3" - charcode: - dependency: transitive - description: - name: charcode - url: "https://pub.flutter-io.cn" - source: hosted - version: "1.2.0-nullsafety.3" - cli_util: - dependency: transitive - description: - name: cli_util - url: "https://pub.flutter-io.cn" - source: hosted - version: "0.2.0" + version: "2.1.1" collection: dependency: transitive description: name: collection + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.flutter-io.cn" source: hosted - version: "1.15.0-nullsafety.5" + version: "1.18.0" convert: dependency: transitive description: name: convert + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" url: "https://pub.flutter-io.cn" source: hosted - version: "2.1.1" + version: "3.1.1" coverage: dependency: transitive description: name: coverage + sha256: ac86d3abab0f165e4b8f561280ff4e066bceaac83c424dd19f1ae2c2fcd12ca9 url: "https://pub.flutter-io.cn" source: hosted - version: "0.14.2" + version: "1.7.1" crypto: dependency: transitive description: name: crypto + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab url: "https://pub.flutter-io.cn" source: hosted - version: "2.1.5" + version: "3.0.3" file: dependency: transitive description: name: file + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + url: "https://pub.flutter-io.cn" + source: hosted + version: "7.0.0" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" url: "https://pub.flutter-io.cn" source: hosted - version: "5.2.1" + version: "3.2.0" glob: dependency: transitive description: name: glob + sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" url: "https://pub.flutter-io.cn" source: hosted - version: "1.2.0" + version: "2.1.2" http_multi_server: dependency: transitive description: name: http_multi_server + sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" url: "https://pub.flutter-io.cn" source: hosted - version: "2.2.0" + version: "3.2.1" http_parser: dependency: transitive description: name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" url: "https://pub.flutter-io.cn" source: hosted - version: "3.1.4" - intl: - dependency: transitive - description: - name: intl - url: "https://pub.flutter-io.cn" - source: hosted - version: "0.16.1" + version: "4.0.2" io: dependency: transitive description: name: io + sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" url: "https://pub.flutter-io.cn" source: hosted - version: "0.3.4" + version: "1.0.4" js: dependency: transitive description: name: js + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 url: "https://pub.flutter-io.cn" source: hosted - version: "0.6.3-nullsafety.3" + version: "0.6.7" logging: dependency: transitive description: name: logging + sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" url: "https://pub.flutter-io.cn" source: hosted - version: "0.11.4" + version: "1.2.0" matcher: dependency: transitive description: name: matcher + sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" url: "https://pub.flutter-io.cn" source: hosted - version: "0.12.10-nullsafety.3" + version: "0.12.16" meta: dependency: transitive description: name: meta + sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 url: "https://pub.flutter-io.cn" source: hosted - version: "1.3.0-nullsafety.6" + version: "1.11.0" mime: dependency: transitive description: name: mime + sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e url: "https://pub.flutter-io.cn" source: hosted - version: "0.9.7" - node_interop: - dependency: transitive - description: - name: node_interop - url: "https://pub.flutter-io.cn" - source: hosted - version: "1.2.1" - node_io: - dependency: transitive - description: - name: node_io - url: "https://pub.flutter-io.cn" - source: hosted - version: "1.2.0" + version: "1.0.4" node_preamble: dependency: transitive description: name: node_preamble + sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" url: "https://pub.flutter-io.cn" source: hosted - version: "1.4.12" + version: "2.0.2" package_config: dependency: transitive description: name: package_config + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" url: "https://pub.flutter-io.cn" source: hosted - version: "1.9.3" + version: "2.1.0" path: dependency: transitive description: name: path + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" url: "https://pub.flutter-io.cn" source: hosted - version: "1.8.0-nullsafety.3" + version: "1.8.3" pedantic: dependency: "direct dev" description: name: pedantic + sha256: "55ea8314cd8fd4efca5ce156a67b28d6c16908af01adca9ebf1c8a0437e7be7e" url: "https://pub.flutter-io.cn" source: hosted version: "1.10.0-nullsafety.3" @@ -201,155 +197,177 @@ packages: dependency: transitive description: name: pool + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" url: "https://pub.flutter-io.cn" source: hosted - version: "1.5.0-nullsafety.3" + version: "1.5.1" pub_semver: dependency: transitive description: name: pub_semver + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" url: "https://pub.flutter-io.cn" source: hosted - version: "1.4.4" + version: "2.1.4" shelf: dependency: transitive description: name: shelf + sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 url: "https://pub.flutter-io.cn" source: hosted - version: "0.7.9" + version: "1.4.1" shelf_packages_handler: dependency: transitive description: name: shelf_packages_handler + sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" url: "https://pub.flutter-io.cn" source: hosted - version: "2.0.0" + version: "3.0.2" shelf_static: dependency: transitive description: name: shelf_static + sha256: a41d3f53c4adf0f57480578c1d61d90342cd617de7fc8077b1304643c2d85c1e url: "https://pub.flutter-io.cn" source: hosted - version: "0.2.8" + version: "1.1.2" shelf_web_socket: dependency: transitive description: name: shelf_web_socket + sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1" url: "https://pub.flutter-io.cn" source: hosted - version: "0.2.3" + version: "1.0.4" source_map_stack_trace: dependency: transitive description: name: source_map_stack_trace + sha256: "84cf769ad83aa6bb61e0aa5a18e53aea683395f196a6f39c4c881fb90ed4f7ae" url: "https://pub.flutter-io.cn" source: hosted - version: "2.1.0-nullsafety.4" + version: "2.1.1" source_maps: dependency: transitive description: name: source_maps + sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703" url: "https://pub.flutter-io.cn" source: hosted - version: "0.10.10-nullsafety.3" + version: "0.10.12" source_span: dependency: transitive description: name: source_span + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" url: "https://pub.flutter-io.cn" source: hosted - version: "1.8.0-nullsafety.4" + version: "1.10.0" stack_trace: dependency: transitive description: name: stack_trace + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.flutter-io.cn" source: hosted - version: "1.10.0-nullsafety.6" + version: "1.11.1" stream_channel: dependency: transitive description: name: stream_channel + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 url: "https://pub.flutter-io.cn" source: hosted - version: "2.1.0-nullsafety.3" + version: "2.1.2" string_scanner: dependency: transitive description: name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" url: "https://pub.flutter-io.cn" source: hosted - version: "1.1.0-nullsafety.3" + version: "1.2.0" term_glyph: dependency: transitive description: name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 url: "https://pub.flutter-io.cn" source: hosted - version: "1.2.0-nullsafety.3" + version: "1.2.1" test: dependency: "direct dev" description: name: test + sha256: a1f7595805820fcc05e5c52e3a231aedd0b72972cb333e8c738a8b1239448b6f url: "https://pub.flutter-io.cn" source: hosted - version: "1.16.0-nullsafety.12" + version: "1.24.9" test_api: dependency: transitive description: name: test_api + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" url: "https://pub.flutter-io.cn" source: hosted - version: "0.2.19-nullsafety.6" + version: "0.6.1" test_core: dependency: transitive description: name: test_core + sha256: a757b14fc47507060a162cc2530d9a4a2f92f5100a952c7443b5cad5ef5b106a url: "https://pub.flutter-io.cn" source: hosted - version: "0.3.12-nullsafety.11" + version: "0.5.9" typed_data: dependency: transitive description: name: typed_data + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c url: "https://pub.flutter-io.cn" source: hosted - version: "1.3.0-nullsafety.5" + version: "1.3.2" vm_service: dependency: transitive description: name: vm_service + sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 url: "https://pub.flutter-io.cn" source: hosted - version: "5.5.0" + version: "13.0.0" watcher: dependency: transitive description: name: watcher + sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" url: "https://pub.flutter-io.cn" source: hosted - version: "0.9.7+15" + version: "1.1.0" web_socket_channel: dependency: transitive description: name: web_socket_channel + sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b url: "https://pub.flutter-io.cn" source: hosted - version: "1.1.0" + version: "2.4.0" webkit_inspection_protocol: dependency: transitive description: name: webkit_inspection_protocol + sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" url: "https://pub.flutter-io.cn" source: hosted - version: "0.7.4" + version: "1.2.1" yaml: dependency: transitive description: name: yaml + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" url: "https://pub.flutter-io.cn" source: hosted - version: "2.2.1" + version: "3.1.2" sdks: - dart: ">=2.12.0 <3.0.0" + dart: ">=3.0.0 <4.0.0" diff --git a/test/json_test.dart b/test/json_test.dart index 0885a78..9ccfebe 100644 --- a/test/json_test.dart +++ b/test/json_test.dart @@ -2,6 +2,11 @@ import 'package:g_json/g_json.dart'; import 'package:test/test.dart'; void main() { + test('parse unsupported string', () { + final j = JSON.parse( + '%7B%0A%20%20%22brand%22%20:%20%22Apple%22,%0A%20%20%22version%22%20:%20%22iOS%2017.5.1%22,%0A%20%20%22model%22%20:%20%22iPhone14,2%22%0A%7D'); + assert(j.isNull); + }); test('[equal] json', () { final j1 = JSON({'a': 1, 'b': 2}); final j2 = JSON({'b': 2, 'a': 1}); @@ -49,6 +54,11 @@ void main() { final j4 = JSON(1); assert(j4 != j3); + + final i = JSON(1); + final j = JSON(i); + + assert(j.value == 1); }); test('[setter] json', () { final j1 = JSON({'a': 1, 'b': 2});