├── .gitignore ├── .vscode └── launch.json ├── README.md ├── example ├── .gitignore ├── .vscode │ └── launch.json ├── analysis_options.yaml ├── bin │ └── example.exe ├── lib │ ├── account.dart │ ├── converters │ │ ├── regex.dart │ │ ├── special_datetime.dart │ │ └── uri.dart │ ├── external_account_alias.dart │ ├── main.dart │ ├── mapper.g.dart │ ├── product.dart │ ├── test.dart │ └── wrapper.dart ├── pubspec.lock └── pubspec.yaml ├── package.code-workspace ├── simple_json ├── .metadata ├── .vscode │ └── launch.json ├── CHANGELOG.md ├── LICENSE ├── README.md ├── build.yaml ├── example │ ├── lib │ │ ├── main.dart │ │ └── mapper.g.dart │ ├── pubspec.lock │ └── pubspec.yaml ├── lib │ ├── simple_json.dart │ └── src │ │ ├── generated_example.dart.md │ │ ├── json_mapper_builder.dart │ │ └── utils.dart ├── pubspec.lock ├── pubspec.yaml └── test │ └── simple_json_test.dart └── simple_json_mapper ├── .gitignore ├── .metadata ├── .vscode └── launch.json ├── CHANGELOG.md ├── LICENSE ├── README.md ├── example ├── lib │ └── main.dart ├── pubspec.lock └── pubspec.yaml ├── lib ├── simple_json_mapper.dart └── src │ ├── annotations.dart │ ├── converters │ ├── datetime.dart │ └── duration.dart │ ├── json_converter.dart │ └── json_mapper.dart ├── pubspec.lock ├── pubspec.yaml └── test ├── basic_converter_test.dart └── test_data └── test.dart /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | .dart_tool/ 26 | .flutter-plugins 27 | .flutter-plugins-dependencies 28 | .packages 29 | .pub-cache/ 30 | .pub/ 31 | build/ 32 | 33 | # Android related 34 | **/android/**/gradle-wrapper.jar 35 | **/android/.gradle 36 | **/android/captures/ 37 | **/android/gradlew 38 | **/android/gradlew.bat 39 | **/android/local.properties 40 | **/android/**/GeneratedPluginRegistrant.java 41 | 42 | # iOS/XCode related 43 | **/ios/**/*.mode1v3 44 | **/ios/**/*.mode2v3 45 | **/ios/**/*.moved-aside 46 | **/ios/**/*.pbxuser 47 | **/ios/**/*.perspectivev3 48 | **/ios/**/*sync/ 49 | **/ios/**/.sconsign.dblite 50 | **/ios/**/.tags* 51 | **/ios/**/.vagrant/ 52 | **/ios/**/DerivedData/ 53 | **/ios/**/Icon? 54 | **/ios/**/Pods/ 55 | **/ios/**/.symlinks/ 56 | **/ios/**/profile 57 | **/ios/**/xcuserdata 58 | **/ios/.generated/ 59 | **/ios/Flutter/App.framework 60 | **/ios/Flutter/Flutter.framework 61 | **/ios/Flutter/Flutter.podspec 62 | **/ios/Flutter/Generated.xcconfig 63 | **/ios/Flutter/app.flx 64 | **/ios/Flutter/app.zip 65 | **/ios/Flutter/flutter_assets/ 66 | **/ios/Flutter/flutter_export_environment.sh 67 | **/ios/ServiceDefinitions.json 68 | **/ios/Runner/GeneratedPluginRegistrant.* 69 | 70 | # Exceptions to above rules. 71 | !**/ios/**/default.mode1v3 72 | !**/ios/**/default.mode2v3 73 | !**/ios/**/default.pbxuser 74 | !**/ios/**/default.perspectivev3 75 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 76 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Dart Builder", 9 | "program": "example/.dart_tool/build/entrypoint/build.dart", 10 | "args": ["serve", "--delete-conflicting-outputs"], 11 | "request": "launch", 12 | "type": "dart" 13 | }, 14 | { 15 | "name": "Dart Example", 16 | "program": "example/lib/main.dart", 17 | "request": "launch", 18 | "type": "dart" 19 | } 20 | ] 21 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Provides [source_gen](https://pub.dev/packages/source_gen) `Generator`s to create code for JSON serialization and de-serialization. 2 | 3 | ## simple_json 4 | - [Package](https://pub.dev/packages/simple_json) 5 | - [Source code](simple_json/) 6 | 7 | The core package providing `Generator`s for JSON-specific tasks. 8 | 9 | Import it into your pubspec `dev_dependencies:` section. 10 | 11 | ## simple_json_mapper 12 | - [Package](https://pub.dev/packages/simple_json_mapper) 13 | - [Source code](simple_json_mapper/) 14 | 15 | The package providing serialization helpers and annotations. 16 | 17 | Import it into your pubspec `dependencies:` section. -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # *.g.dart -------------------------------------------------------------------------------- /example/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Debug Dart Builder", 9 | "program": ".dart_tool/build/entrypoint/build.dart", 10 | "args": [ 11 | "serve", 12 | "--delete-conflicting-outputs" 13 | ], 14 | "request": "launch", 15 | "type": "dart" 16 | }, 17 | { 18 | "name": "Dart Example", 19 | "program": "lib/main.dart", 20 | "request": "launch", 21 | "type": "dart" 22 | } 23 | ] 24 | } -------------------------------------------------------------------------------- /example/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # Specify analysis options. 2 | # 3 | # Until there are meta linter rules, each desired lint must be explicitly enabled. 4 | # See: https://github.com/dart-lang/linter/issues/288 5 | # 6 | # For a list of lints, see: http://dart-lang.github.io/linter/lints/ 7 | # See the configuration guide for more 8 | # https://github.com/dart-lang/sdk/tree/master/pkg/analyzer#configuring-the-analyzer 9 | # 10 | # There are other similar analysis options files in the flutter repos, 11 | # which should be kept in sync with this file: 12 | # 13 | # - analysis_options.yaml (this file) 14 | # - packages/flutter/lib/analysis_options_user.yaml 15 | # - https://github.com/flutter/plugins/blob/master/analysis_options.yaml 16 | # - https://github.com/flutter/engine/blob/master/analysis_options.yaml 17 | # 18 | # This file contains the analysis options used by Flutter tools, such as IntelliJ, 19 | # Android Studio, and the `flutter analyze` command. 20 | 21 | analyzer: 22 | strong-mode: 23 | implicit-casts: false 24 | implicit-dynamic: false 25 | errors: 26 | # treat missing required parameters as a warning (not a hint) 27 | missing_required_param: warning 28 | # treat missing returns as a warning (not a hint) 29 | missing_return: warning 30 | # allow having TODOs in the code 31 | todo: ignore 32 | # Ignore analyzer hints for updating pubspecs when using Future or 33 | # Stream and not importing dart:async 34 | # Please see https://github.com/flutter/flutter/pull/24528 for details. 35 | sdk_version_async_exported_from_core: ignore 36 | exclude: 37 | - "bin/cache/**" 38 | # the following two are relative to the stocks example and the flutter package respectively 39 | # see https://github.com/dart-lang/sdk/issues/28463 40 | - "lib/i18n/messages_*.dart" 41 | - "lib/src/http/**" 42 | - lib/main.reflectable.dart 43 | - test/integration_tests/explorable_widget_test.reflectable.dart 44 | 45 | linter: 46 | rules: 47 | # these rules are documented on and in the same order as 48 | # the Dart Lint rules page to make maintenance easier 49 | # https://github.com/dart-lang/linter/blob/master/example/all.yaml 50 | #- always_declare_return_types 51 | #- always_put_control_body_on_new_line 52 | # - always_put_required_named_parameters_first # we prefer having parameters in the same order as fields https://github.com/flutter/flutter/issues/10219 53 | - always_require_non_null_named_parameters 54 | #- always_specify_types 55 | - annotate_overrides 56 | # - avoid_annotating_with_dynamic # conflicts with always_specify_types 57 | # - avoid_as # required for implicit-casts: true 58 | # - avoid_bool_literals_in_conditional_expressions 59 | # - avoid_catches_without_on_clauses # we do this commonly 60 | # - avoid_catching_errors # we do this commonly 61 | - avoid_classes_with_only_static_members 62 | # - avoid_double_and_int_checks # only useful when targeting JS runtime 63 | - avoid_empty_else 64 | # - avoid_equals_and_hash_code_on_mutable_classes # not yet tested 65 | - avoid_field_initializers_in_const_classes 66 | #- avoid_function_literals_in_foreach_calls 67 | # - avoid_implementing_value_types # not yet tested 68 | - avoid_init_to_null 69 | # - avoid_js_rounded_ints # only useful when targeting JS runtime 70 | - avoid_null_checks_in_equality_operators 71 | # - avoid_positional_boolean_parameters # not yet tested 72 | # - avoid_print # not yet tested 73 | # - avoid_private_typedef_functions # we prefer having typedef (discussion in https://github.com/flutter/flutter/pull/16356) 74 | # - avoid_redundant_argument_values # not yet tested 75 | - avoid_relative_lib_imports 76 | - avoid_renaming_method_parameters 77 | - avoid_return_types_on_setters 78 | # - avoid_returning_null # there are plenty of valid reasons to return null 79 | # - avoid_returning_null_for_future # not yet tested 80 | - avoid_returning_null_for_void 81 | # - avoid_returning_this # there are plenty of valid reasons to return this 82 | # - avoid_setters_without_getters # not yet tested 83 | # - avoid_shadowing_type_parameters # not yet tested 84 | - avoid_single_cascade_in_expression_statements 85 | - avoid_slow_async_io 86 | - avoid_types_as_parameter_names 87 | # - avoid_types_on_closure_parameters # conflicts with always_specify_types 88 | # - avoid_unnecessary_containers # not yet tested 89 | - avoid_unused_constructor_parameters 90 | - avoid_void_async 91 | # - avoid_web_libraries_in_flutter # not yet tested 92 | - await_only_futures 93 | - camel_case_extensions 94 | - camel_case_types 95 | - cancel_subscriptions 96 | # - cascade_invocations # not yet tested 97 | # - close_sinks # not reliable enough 98 | # - comment_references # blocked on https://github.com/flutter/flutter/issues/20765 99 | # - constant_identifier_names # needs an opt-out https://github.com/dart-lang/linter/issues/204 100 | - control_flow_in_finally 101 | # - curly_braces_in_flow_control_structures # not yet tested 102 | # - diagnostic_describe_all_properties # not yet tested 103 | - directives_ordering 104 | - empty_catches 105 | - empty_constructor_bodies 106 | - empty_statements 107 | # - file_names # not yet tested 108 | - flutter_style_todos 109 | - hash_and_equals 110 | - implementation_imports 111 | # - invariant_booleans # too many false positives: https://github.com/dart-lang/linter/issues/811 112 | - iterable_contains_unrelated_type 113 | # - join_return_with_assignment # not yet tested 114 | - library_names 115 | - library_prefixes 116 | # - lines_longer_than_80_chars # not yet tested 117 | - list_remove_unrelated_type 118 | # - literal_only_boolean_expressions # too many false positives: https://github.com/dart-lang/sdk/issues/34181 119 | # - missing_whitespace_between_adjacent_strings # not yet tested 120 | - no_adjacent_strings_in_list 121 | - no_duplicate_case_values 122 | # - no_logic_in_create_state # not yet tested 123 | # - no_runtimeType_toString # not yet tested 124 | - non_constant_identifier_names 125 | # - null_closures # not yet tested 126 | # - omit_local_variable_types # opposite of always_specify_types 127 | # - one_member_abstracts # too many false positives 128 | # - only_throw_errors # https://github.com/flutter/flutter/issues/5792 129 | - overridden_fields 130 | - package_api_docs 131 | - package_names 132 | - package_prefixed_library_names 133 | # - parameter_assignments # we do this commonly 134 | - prefer_adjacent_string_concatenation 135 | - prefer_asserts_in_initializer_lists 136 | # - prefer_asserts_with_message # not yet tested 137 | - prefer_collection_literals 138 | - prefer_conditional_assignment 139 | - prefer_const_constructors 140 | - prefer_const_constructors_in_immutables 141 | - prefer_const_declarations 142 | - prefer_const_literals_to_create_immutables 143 | # - prefer_constructors_over_static_methods # not yet tested 144 | - prefer_contains 145 | # - prefer_double_quotes # opposite of prefer_single_quotes 146 | - prefer_equal_for_default_values 147 | # - prefer_expression_function_bodies # conflicts with https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#consider-using--for-short-functions-and-methods 148 | - prefer_final_fields 149 | - prefer_final_in_for_each 150 | - prefer_final_locals 151 | - prefer_for_elements_to_map_fromIterable 152 | - prefer_foreach 153 | # - prefer_function_declarations_over_variables # not yet tested 154 | - prefer_generic_function_type_aliases 155 | - prefer_if_elements_to_conditional_expressions 156 | - prefer_if_null_operators 157 | - prefer_initializing_formals 158 | - prefer_inlined_adds 159 | # - prefer_int_literals # not yet tested 160 | # - prefer_interpolation_to_compose_strings # not yet tested 161 | - prefer_is_empty 162 | - prefer_is_not_empty 163 | - prefer_is_not_operator 164 | - prefer_iterable_whereType 165 | # - prefer_mixin # https://github.com/dart-lang/language/issues/32 166 | # - prefer_null_aware_operators # disable until NNBD, see https://github.com/flutter/flutter/pull/32711#issuecomment-492930932 167 | # - prefer_relative_imports # not yet tested 168 | - prefer_single_quotes 169 | - prefer_spread_collections 170 | - prefer_typing_uninitialized_variables 171 | - prefer_void_to_null 172 | # - provide_deprecation_message # not yet tested 173 | # - public_member_api_docs # enabled on a case-by-case basis; see e.g. packages/analysis_options.yaml 174 | - recursive_getters 175 | - slash_for_doc_comments 176 | # - sort_child_properties_last # not yet tested 177 | - sort_constructors_first 178 | - sort_pub_dependencies 179 | - sort_unnamed_constructors_first 180 | - test_types_in_equals 181 | - throw_in_finally 182 | # - type_annotate_public_apis # subset of always_specify_types 183 | - type_init_formals 184 | # - unawaited_futures # too many false positives 185 | # - unnecessary_await_in_return # not yet tested 186 | - unnecessary_brace_in_string_interps 187 | - unnecessary_const 188 | # - unnecessary_final # conflicts with prefer_final_locals 189 | - unnecessary_getters_setters 190 | # - unnecessary_lambdas # has false positives: https://github.com/dart-lang/linter/issues/498 191 | - unnecessary_new 192 | - unnecessary_null_aware_assignments 193 | - unnecessary_null_in_if_null_operators 194 | - unnecessary_overrides 195 | - unnecessary_parenthesis 196 | - unnecessary_statements 197 | - unnecessary_string_interpolations 198 | - unnecessary_this 199 | - unrelated_type_equality_checks 200 | # - unsafe_html # not yet tested 201 | - use_full_hex_values_for_flutter_colors 202 | # - use_function_type_syntax_for_parameters # not yet tested 203 | # - use_key_in_widget_constructors # not yet tested 204 | - use_rethrow_when_possible 205 | # - use_setters_to_change_properties # not yet tested 206 | # - use_string_buffers # has false positives: https://github.com/dart-lang/sdk/issues/34182 207 | # - use_to_and_as_if_applicable # has false positives, so we prefer to catch this by code-review 208 | - valid_regexps 209 | - void_checks 210 | -------------------------------------------------------------------------------- /example/bin/example.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlutterDevTools/simple_json/06305c3ccbda0a0ee3b693006a3599313a6c4df2/example/bin/example.exe -------------------------------------------------------------------------------- /example/lib/account.dart: -------------------------------------------------------------------------------- 1 | import 'package:simple_json_example/converters/special_datetime.dart'; 2 | import 'package:simple_json_mapper/simple_json_mapper.dart'; 3 | import 'package:simple_json_example/product.dart'; 4 | 5 | abstract class BaseAccount { 6 | const BaseAccount( 7 | {required this.ownerType, 8 | required this.openDate, 9 | required this.closedDate}); 10 | final AccountOwnerType ownerType; 11 | @JProp(name: 'openingDate') 12 | final DateTime openDate; 13 | 14 | // Converter directly applied to a field. Takes precedence over all converter configurations 15 | @SpecialDateTimeConverter(true) 16 | final DateTime closedDate; 17 | } 18 | 19 | class Account extends BaseAccount { 20 | const Account( 21 | {required this.id, 22 | required this.type, 23 | required this.features, 24 | this.name, 25 | required this.number, 26 | required this.amount, 27 | required this.transactionCount, 28 | required this.isActive, 29 | required this.product, 30 | this.localText, 31 | this.refreshFrequeuncy = const Duration(minutes: 30), 32 | required AccountOwnerType ownerType, 33 | required DateTime closedDate, 34 | required DateTime openDate}) 35 | : super(ownerType: ownerType, openDate: openDate, closedDate: closedDate); 36 | 37 | final String id; 38 | @JEnumProp(serializationType: SerializationType.Index) 39 | final AccountType type; 40 | final List features; 41 | final String? name; 42 | final String number; 43 | final double amount; 44 | 45 | final Duration refreshFrequeuncy; 46 | 47 | @JsonProperty(name: 'tranCount', defaultValue: 11) 48 | final int transactionCount; 49 | 50 | final bool isActive; 51 | 52 | @JProp(ignore: true) 53 | final String? localText; 54 | 55 | final Product product; 56 | } 57 | 58 | enum AccountType { 59 | @EnumValue(value: 25) 60 | Savings, 61 | 62 | @EnumValue(value: 10) 63 | Checking 64 | } 65 | 66 | enum AccountFeature { 67 | Cashback, 68 | Rewards, 69 | } 70 | 71 | enum AccountOwnerType { Individual, Business } 72 | -------------------------------------------------------------------------------- /example/lib/converters/regex.dart: -------------------------------------------------------------------------------- 1 | import 'package:simple_json_mapper/simple_json_mapper.dart'; 2 | 3 | class RegExpConverter extends JsonConverter { 4 | const RegExpConverter(); 5 | 6 | @override 7 | RegExp fromJson(String value) { 8 | return RegExp(value); 9 | } 10 | 11 | @override 12 | String toJson(RegExp value) => value.pattern; 13 | } 14 | -------------------------------------------------------------------------------- /example/lib/converters/special_datetime.dart: -------------------------------------------------------------------------------- 1 | import 'package:simple_json_mapper/simple_json_mapper.dart'; 2 | 3 | class SpecialDateTimeConverter extends JsonConverter { 4 | const SpecialDateTimeConverter([this.shouldPad = false]); 5 | final bool shouldPad; 6 | 7 | @override 8 | DateTime fromJson(String value) { 9 | final dateParts = value.split('-').map((s) => int.parse(s)).toList(); 10 | return DateTime(dateParts[0], dateParts[1], dateParts[2]); 11 | } 12 | 13 | @override 14 | String toJson(DateTime value) => 15 | '${value.year}-${_leftPad(value.month, shouldPad)}-${_leftPad(value.day, shouldPad)}'; 16 | 17 | String _leftPad(int value, bool shouldPad) { 18 | return shouldPad && value.abs().toString().length == 1 19 | ? '0$value' 20 | : value.toString(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /example/lib/converters/uri.dart: -------------------------------------------------------------------------------- 1 | import 'package:simple_json_mapper/simple_json_mapper.dart'; 2 | 3 | class UriConverter extends JsonConverter { 4 | const UriConverter(); 5 | 6 | @override 7 | Uri fromJson(String value) { 8 | return Uri.parse(value); 9 | } 10 | 11 | @override 12 | String toJson(Uri value) => value.toString(); 13 | } 14 | -------------------------------------------------------------------------------- /example/lib/external_account_alias.dart: -------------------------------------------------------------------------------- 1 | import 'package:simple_json_mapper/simple_json_mapper.dart'; 2 | 3 | import 'account.dart'; 4 | 5 | class Alias {} 6 | 7 | // This can be useful for when the types are defined in a package outside of your code. 8 | @JObj() 9 | class ExternalAccountAlias = Account with Alias; 10 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:simple_json_example/converters/regex.dart'; 2 | import 'package:simple_json_example/converters/uri.dart'; 3 | import 'package:simple_json_mapper/simple_json_mapper.dart'; 4 | import 'package:simple_json_example/account.dart'; 5 | import 'package:simple_json_example/product.dart'; 6 | import 'package:simple_json_example/test.dart'; 7 | import 'package:uuid/uuid.dart'; 8 | 9 | import 'mapper.g.dart' as mapper; 10 | 11 | void main() { 12 | mapper.init(); 13 | // Convert all deserialized strings to lowercase and all serialized strings to uppercase. 14 | JsonMapper.registerConverter( 15 | JsonConverter.fromFunction( 16 | fromJson: (value) => value.toLowerCase(), 17 | toJson: (value) => value.toUpperCase(), 18 | ), 19 | ); 20 | 21 | // Converter for transforming all DateTime string values to a special format defined by the given class. 22 | // JsonMapper.registerConverter(SpecialDateTimeConverter()); 23 | const okTest = 24 | Test(name: 'hello', nestedTest: NestedTest(ze: 'ok'), extraProp: 'extra'); 25 | final okTestJson = JsonMapper.serialize(okTest); 26 | print('\nSerialized Test:'); 27 | print(okTestJson); 28 | final okTestDeser = 29 | JsonMapper.deserialize(okTestJson, (Test).toString()); 30 | print('\nRe-serialized Test:'); 31 | print(JsonMapper.serialize(okTestDeser)); 32 | 33 | final product = Product( 34 | name: 'Test', 35 | type: ProductType.Shoe, 36 | productDetails: Uri.parse('http://test.com'), 37 | productMatchPattern: RegExp(r'\w+'), 38 | expiry: DateTime.now(), 39 | sizes: [10, 8, 5.5], 40 | tests: [ 41 | okTest, 42 | const Test(name: 'blah', nestedTest: NestedTest(ze: 'he')), 43 | ], 44 | attributes: {'top': 'kek'}, 45 | parent: Product( 46 | name: 'Parent Test', 47 | productDetails: Uri.parse('http://blah.com'), 48 | productMatchPattern: RegExp(r'\d+'), 49 | type: ProductType.Shirt, 50 | expiry: DateTime.now().subtract(const Duration(days: 1)), 51 | sizes: [22], 52 | tests: [], 53 | attributes: {'bottom': 'bear'}, 54 | ), 55 | timeline: [DateTime.now()]); 56 | // final wrapper = Wrapper(data: product, test: okTest); 57 | // print('Serialized Product Wrapper:'); 58 | // final serializedWrapper = JsonMapper.serialize(wrapper); 59 | // print(serializedWrapper); 60 | // print('\nRe-serialized Product Wrapper:'); 61 | // print(JsonMapper.serialize( 62 | // JsonMapper.deserialize>(serializedWrapper))); 63 | 64 | final account = Account( 65 | id: const Uuid().v4(), 66 | type: AccountType.Checking, 67 | features: [AccountFeature.Cashback, AccountFeature.Rewards], 68 | name: 'Test', 69 | number: 'xxx12414', 70 | amount: 100.50, 71 | transactionCount: 10, 72 | isActive: true, 73 | product: product, 74 | localText: 'ignored text', 75 | ownerType: AccountOwnerType.Individual, 76 | closedDate: DateTime(2020, 5, 16), 77 | openDate: DateTime(2010, 4, 2), 78 | ); 79 | print('Serialized Account:'); 80 | final serializedAccount = JsonMapper.serialize(account); 81 | print(serializedAccount); 82 | print('\nRe-serialized Account:'); 83 | print( 84 | JsonMapper.serialize(JsonMapper.deserialize(serializedAccount))); 85 | 86 | print('\n\nSerialized with Custom Mapper and converters:'); 87 | // Custom mapper that has it own set of converters. Useful for encapsulating for special, adhoc serializations 88 | // e.g. SQLite 89 | final customMapper = CustomJsonMapper( 90 | converters: [ 91 | // Converter for changing all boolean values from boolean to int and vice versa on serialization. 92 | JsonConverter.fromFunction( 93 | fromJson: (value) => value == 1 ? true : false, 94 | toJson: (value) => value ? 1 : 0, 95 | ), 96 | const RegExpConverter(), 97 | const UriConverter(), 98 | ], 99 | ); 100 | // Note the usage of [customerMapper] here. 101 | print(customMapper.serialize(account)); 102 | 103 | print('\n\nSerialized Product:'); 104 | final productSerialized = JsonMapper.serialize([product]); 105 | print(productSerialized); 106 | print('\nRe-serialize Product:'); 107 | print(JsonMapper.serialize( 108 | JsonMapper.deserialize>(productSerialized))); 109 | 110 | // OUTPUT: 111 | /* 112 | Serialized Account: 113 | {"id":"B4FECC31-2429-4631-BA57-DADA21C3D6E0","type":10,"name":"TEST","number":"XXX12414","amount":100.5, 114 | "tranCount":10,"isActive":true,"product":{"name":"TEST","type":"SHOE","expiry":"2020-6-28","sizes":[10.0,8.0,5.5], 115 | "tests":[{"name":"HELLO","nestedTest":{"ze":"OK"}},{"name":"BLAH","nestedTest":{"ze":"HE"}}]},"closedDate": 116 | "2020-05-16","openingDate":"2010-4-2"} 117 | 118 | Re-serialized Account: 119 | {"id":"B4FECC31-2429-4631-BA57-DADA21C3D6E0","type":10,"name":"TEST","number":"XXX12414","amount":100.5, 120 | "tranCount":10,"isActive":true,"product":{"name":"TEST","type":"SHOE","expiry":"2020-6-28","sizes":[10.0,8.0,5.5], 121 | "tests":[{"name":"HELLO","nestedTest":{"ze":"OK"}},{"name":"BLAH","nestedTest":{"ze":"HE"}}]},"closedDate": 122 | "2020-05-16","openingDate":"2010-4-2"} 123 | 124 | 125 | Serialized with Custom Mapper and converters: 126 | {"id":"b4fecc31-2429-4631-ba57-dada21c3d6e0","type":10,"name":"Test","number":"xxx12414","amount":100.5, 127 | "tranCount":10,"isActive":1,"product":{"name":"Test","type":"Shoe","expiry":"2020-06-28T02:15:21.412538", 128 | "sizes":[10.0,8.0,5.5],"tests":[{"name":"hello","nestedTest":{"ze":"ok"}},{"name":"blah","nestedTest":{"ze":"he"}}]}, 129 | "closedDate":"2020-05-16","openingDate":"2010-04-02T00:00:00.000"} 130 | 131 | 132 | Serialized Product: 133 | {"name":"TEST","type":"SHOE","expiry":"2020-6-28","sizes":[10.0,8.0,5.5],"tests":[{"name":"HELLO","nestedTest": 134 | {"ze":"OK"}},{"name":"BLAH","nestedTest":{"ze":"HE"}}]} 135 | 136 | Re-serialize Product: 137 | {"name":"TEST","type":"SHOE","expiry":"2020-6-28","sizes":[10.0,8.0,5.5],"tests":[{"name":"HELLO","nestedTest": 138 | {"ze":"OK"}},{"name":"BLAH","nestedTest":{"ze":"HE"}}]} 139 | */ 140 | } 141 | -------------------------------------------------------------------------------- /example/lib/mapper.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | // Generated and consumed by 'simple_json' 3 | 4 | import 'package:simple_json_mapper/simple_json_mapper.dart'; 5 | import 'package:simple_json_example/product.dart'; 6 | import 'package:simple_json_example/test.dart'; 7 | import 'package:simple_json_example/account.dart'; 8 | import 'dart:core'; 9 | import 'package:simple_json_example/converters/regex.dart'; 10 | import 'package:simple_json_example/converters/special_datetime.dart'; 11 | import 'package:simple_json_example/converters/uri.dart'; 12 | 13 | final _productMapper = JsonObjectMapper( 14 | (CustomJsonMapper mapper, Map json) => Product( 15 | name: mapper.applyDynamicFromJsonConverter(json['name'])!, 16 | type: mapper.applyDynamicFromJsonConverter(ProductType.values.cast().firstWhere( 17 | (value) => value!.toString().split('.').elementAt(1).toLowerCase() == json['type'].toLowerCase(), 18 | orElse: () => null)), 19 | expiry: mapper.applyDynamicFromJsonConverter(json['expiry'])!, 20 | productDetails: mapper.applyDynamicFromJsonConverter(json['productDetails'])!, 21 | sizes: (json['sizes'] as List?)?.cast().map((item) => mapper.applyDynamicFromJsonConverter(item)!).toList(), 22 | tests: (json['tests'] as List).cast>().map((item) => mapper.deserialize(item)!).toList(), 23 | productMatchPattern: mapper.applyDynamicFromJsonConverter(json['productMatchPattern'])!, 24 | attributes: (json['attributes'] as Map).cast(), 25 | parent: mapper.deserialize(json['parent'] as Map?), 26 | timeline: (json['timeline'] as List?)?.map((dynamic item) => mapper.applyDynamicFromJsonConverter(item)!).toList(), 27 | ), 28 | (CustomJsonMapper mapper, Product instance) => { 29 | 'name': mapper.applyDynamicFromInstanceConverter(instance.name), 30 | 'type': mapper.applyDynamicFromInstanceConverter(instance.type?.toString().split('.').elementAt(1)), 31 | 'expiry': mapper.applyDynamicFromInstanceConverter(instance.expiry), 32 | 'productDetails': mapper.applyDynamicFromInstanceConverter(instance.productDetails), 33 | 'sizes': mapper.applyDynamicFromInstanceConverter(instance.sizes), 34 | 'tests': instance.tests.map((item) => mapper.serializeToMap(item)).toList(), 35 | 'productMatchPattern': mapper.applyDynamicFromInstanceConverter(instance.productMatchPattern), 36 | 'attributes': mapper.applyDynamicFromInstanceConverter(instance.attributes), 37 | 'parent': mapper.serializeToMap(instance.parent), 38 | 'timeline': instance.timeline?.map((item) => mapper.applyDynamicFromInstanceConverter(item)).toList(), 39 | }, 40 | ); 41 | 42 | 43 | final _basetestMapper = JsonObjectMapper( 44 | (CustomJsonMapper mapper, Map json) => BaseTest( 45 | name: mapper.applyDynamicFromJsonConverter(json['name'])!, 46 | nestedTest: mapper.deserialize(json['nestedTest'] as Map)!, 47 | ), 48 | (CustomJsonMapper mapper, BaseTest instance) => { 49 | 'name': mapper.applyDynamicFromInstanceConverter(instance.name), 50 | 'nestedTest': mapper.serializeToMap(instance.nestedTest), 51 | }, 52 | ); 53 | 54 | 55 | final _testMapper = JsonObjectMapper( 56 | (CustomJsonMapper mapper, Map json) => Test( 57 | name: mapper.applyDynamicFromJsonConverter(json['name'])!, 58 | nestedTest: mapper.deserialize(json['nestedTest'] as Map)!, 59 | extraProp: mapper.applyDynamicFromJsonConverter(json['extraProp']), 60 | ), 61 | (CustomJsonMapper mapper, Test instance) => { 62 | 'name': mapper.applyDynamicFromInstanceConverter(instance.name), 63 | 'nestedTest': mapper.serializeToMap(instance.nestedTest), 64 | 'extraProp': mapper.applyDynamicFromInstanceConverter(instance.extraProp), 65 | }, 66 | ); 67 | 68 | 69 | final _nestedtestMapper = JsonObjectMapper( 70 | (CustomJsonMapper mapper, Map json) => NestedTest( 71 | ze: mapper.applyDynamicFromJsonConverter(json['ze'])!, 72 | data: mapper.applyDynamicFromJsonConverter(json['data']), 73 | ), 74 | (CustomJsonMapper mapper, NestedTest instance) => { 75 | 'ze': mapper.applyDynamicFromInstanceConverter(instance.ze), 76 | 'data': mapper.applyDynamicFromInstanceConverter(instance.data), 77 | }, 78 | ); 79 | 80 | 81 | final _jsonapiresponseMapper = JsonObjectMapper( 82 | (CustomJsonMapper mapper, Map json) => JsonApiResponse( 83 | errorData: mapper.applyDynamicFromJsonConverter(json['errorData']), 84 | errorMessage: mapper.applyDynamicFromJsonConverter(json['errorMessage'])!, 85 | fieldErrors: (json['fieldErrors'] as List).cast>().map((item) => mapper.deserialize(item)!).toList(), 86 | data: mapper.applyDynamicFromJsonConverter(json['data']), 87 | ), 88 | (CustomJsonMapper mapper, JsonApiResponse instance) => { 89 | 'errorData': mapper.applyDynamicFromInstanceConverter(instance.errorData), 90 | 'errorMessage': mapper.applyDynamicFromInstanceConverter(instance.errorMessage), 91 | 'fieldErrors': instance.fieldErrors.map((item) => mapper.serializeToMap(item)).toList(), 92 | 'data': mapper.applyDynamicFromInstanceConverter(instance.data), 93 | }, 94 | ); 95 | 96 | 97 | final _accountMapper = JsonObjectMapper( 98 | (CustomJsonMapper mapper, Map json) => Account( 99 | id: mapper.applyDynamicFromJsonConverter(json['id'])!, 100 | type: mapper.applyDynamicFromJsonConverter(AccountType.values.cast().firstWhere( 101 | (value) => value!.index == json['type'], 102 | orElse: () => null))!, 103 | features: (json['features'] as List).map((dynamic item) => mapper.applyDynamicFromJsonConverter(AccountFeature.values.cast().firstWhere( 104 | (value) => value!.toString().split('.').elementAt(1).toLowerCase() == item?.toString().toLowerCase(), 105 | orElse: () => null))!).toList(), 106 | name: mapper.applyDynamicFromJsonConverter(json['name']), 107 | number: mapper.applyDynamicFromJsonConverter(json['number'])!, 108 | amount: mapper.applyDynamicFromJsonConverter(json['amount'])!, 109 | transactionCount: mapper.applyDynamicFromJsonConverter(json['tranCount'])!, 110 | isActive: mapper.applyDynamicFromJsonConverter(json['isActive'])!, 111 | product: mapper.deserialize(json['product'] as Map)!, 112 | refreshFrequeuncy: mapper.applyDynamicFromJsonConverter(json['refreshFrequeuncy']) ?? const Duration(minutes: 30), 113 | ownerType: mapper.applyDynamicFromJsonConverter(AccountOwnerType.values.cast().firstWhere( 114 | (value) => value!.toString().split('.').elementAt(1).toLowerCase() == json['ownerType'].toLowerCase(), 115 | orElse: () => null))!, 116 | closedDate: mapper.applyDynamicFromJsonConverter(json['closedDate'], SpecialDateTimeConverter(true))!, 117 | openDate: mapper.applyDynamicFromJsonConverter(json['openingDate'])!, 118 | ), 119 | (CustomJsonMapper mapper, Account instance) => { 120 | 'id': mapper.applyDynamicFromInstanceConverter(instance.id), 121 | 'type': mapper.applyDynamicFromInstanceConverter(instance.type.index), 122 | 'features': instance.features.map((item) => item.toString().split('.').elementAt(1)).toList(), 123 | 'name': mapper.applyDynamicFromInstanceConverter(instance.name), 124 | 'number': mapper.applyDynamicFromInstanceConverter(instance.number), 125 | 'amount': mapper.applyDynamicFromInstanceConverter(instance.amount), 126 | 'tranCount': mapper.applyDynamicFromInstanceConverter(instance.transactionCount), 127 | 'isActive': mapper.applyDynamicFromInstanceConverter(instance.isActive), 128 | 'product': mapper.serializeToMap(instance.product), 129 | 'refreshFrequeuncy': mapper.applyDynamicFromInstanceConverter(instance.refreshFrequeuncy), 130 | 'ownerType': mapper.applyDynamicFromInstanceConverter(instance.ownerType.toString().split('.').elementAt(1)), 131 | 'closedDate': mapper.applyDynamicFromInstanceConverter(instance.closedDate, SpecialDateTimeConverter(true)), 132 | 'openingDate': mapper.applyDynamicFromInstanceConverter(instance.openDate), 133 | }, 134 | ); 135 | 136 | 137 | 138 | final _fieldkeyvaluepairMapper = JsonObjectMapper( 139 | (CustomJsonMapper mapper, Map json) => FieldKeyValuePair( 140 | key: mapper.applyDynamicFromJsonConverter(json['key'])!, 141 | value: mapper.applyDynamicFromJsonConverter(json['value'])!, 142 | ), 143 | (CustomJsonMapper mapper, FieldKeyValuePair instance) => { 144 | 'key': mapper.applyDynamicFromInstanceConverter(instance.key), 145 | 'value': mapper.applyDynamicFromInstanceConverter(instance.value), 146 | }, 147 | ); 148 | 149 | 150 | 151 | 152 | 153 | void init() { 154 | JsonMapper.register(_productMapper); 155 | JsonMapper.register(_basetestMapper); 156 | JsonMapper.register(_testMapper); 157 | JsonMapper.register(_nestedtestMapper); 158 | JsonMapper.register(_jsonapiresponseMapper); 159 | JsonMapper.register(_accountMapper); 160 | JsonMapper.register(_fieldkeyvaluepairMapper); 161 | 162 | JsonMapper.registerConverter(RegExpConverter()); 163 | JsonMapper.registerConverter(SpecialDateTimeConverter()); 164 | JsonMapper.registerConverter(UriConverter()); 165 | 166 | JsonMapper.registerListCast((value) => value?.cast().toList()); 167 | JsonMapper.registerListCast((value) => value?.cast().toList()); 168 | JsonMapper.registerListCast((value) => value?.cast().toList()); 169 | JsonMapper.registerListCast((value) => value?.cast().toList()); 170 | JsonMapper.registerListCast((value) => value?.cast().toList()); 171 | JsonMapper.registerListCast((value) => value?.cast().toList()); 172 | JsonMapper.registerListCast((value) => value?.cast().toList()); 173 | JsonMapper.registerListCast((value) => value?.cast().toList()); 174 | JsonMapper.registerListCast((value) => value?.cast().toList()); 175 | JsonMapper.registerListCast((value) => value?.cast().toList()); 176 | JsonMapper.registerListCast((value) => value?.cast().toList()); 177 | JsonMapper.registerListCast((value) => value?.cast().toList()); 178 | } 179 | -------------------------------------------------------------------------------- /example/lib/product.dart: -------------------------------------------------------------------------------- 1 | import 'package:simple_json_mapper/simple_json_mapper.dart'; 2 | import 'package:simple_json_example/test.dart'; 3 | 4 | enum ProductType { Shoe, Shirt, Bottom } 5 | 6 | @JsonObject() 7 | class Product { 8 | const Product({ 9 | required this.name, 10 | this.type, 11 | required this.expiry, 12 | required this.productDetails, 13 | this.sizes, 14 | required this.tests, 15 | required this.productMatchPattern, 16 | required this.attributes, 17 | this.parent, 18 | this.timeline, 19 | }); 20 | final String name; 21 | final ProductType? type; 22 | final DateTime expiry; 23 | final Uri productDetails; 24 | final RegExp productMatchPattern; 25 | final List? sizes; 26 | final List tests; 27 | final Map attributes; 28 | final Product? parent; 29 | final List? timeline; 30 | } 31 | -------------------------------------------------------------------------------- /example/lib/test.dart: -------------------------------------------------------------------------------- 1 | import 'package:simple_json_mapper/simple_json_mapper.dart'; 2 | 3 | @JObj() 4 | class BaseTest { 5 | const BaseTest({required this.name, required this.nestedTest}); 6 | final String name; 7 | final NestedTest nestedTest; 8 | } 9 | 10 | @JObj() 11 | class Test extends BaseTest { 12 | const Test({ 13 | required String name, 14 | required NestedTest nestedTest, 15 | this.extraProp, 16 | }) : super(name: name, nestedTest: nestedTest); 17 | final String? extraProp; 18 | } 19 | 20 | @JObj() 21 | class NestedTest { 22 | const NestedTest({required this.ze, this.data}); 23 | final dynamic data; 24 | final String ze; 25 | } 26 | 27 | @JObj() 28 | class JsonApiResponse { 29 | const JsonApiResponse({ 30 | this.errorData, 31 | required this.errorMessage, 32 | required this.fieldErrors, 33 | this.data, 34 | }); 35 | 36 | final dynamic data; 37 | final dynamic errorData; 38 | final String errorMessage; 39 | final List fieldErrors; 40 | } 41 | 42 | class FieldKeyValuePair { 43 | const FieldKeyValuePair({required this.key, required this.value}); 44 | final String key; 45 | final String value; 46 | } 47 | -------------------------------------------------------------------------------- /example/lib/wrapper.dart: -------------------------------------------------------------------------------- 1 | import 'package:simple_json_example/test.dart'; 2 | import 'package:simple_json_mapper/simple_json_mapper.dart'; 3 | 4 | // @JObj() 5 | class Wrapper { 6 | Wrapper({required this.data, required this.test}); 7 | final T data; 8 | final Test test; 9 | } 10 | -------------------------------------------------------------------------------- /example/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | _fe_analyzer_shared: 5 | dependency: transitive 6 | description: 7 | name: _fe_analyzer_shared 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "25.0.0" 11 | analyzer: 12 | dependency: transitive 13 | description: 14 | name: analyzer 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "2.2.0" 18 | args: 19 | dependency: transitive 20 | description: 21 | name: args 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "2.0.0" 25 | async: 26 | dependency: transitive 27 | description: 28 | name: async 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "2.5.0" 32 | boolean_selector: 33 | dependency: transitive 34 | description: 35 | name: boolean_selector 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "2.1.0" 39 | build: 40 | dependency: transitive 41 | description: 42 | name: build 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "2.1.0" 46 | build_config: 47 | dependency: transitive 48 | description: 49 | name: build_config 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "1.0.0" 53 | build_daemon: 54 | dependency: transitive 55 | description: 56 | name: build_daemon 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "3.0.0" 60 | build_resolvers: 61 | dependency: transitive 62 | description: 63 | name: build_resolvers 64 | url: "https://pub.dartlang.org" 65 | source: hosted 66 | version: "2.0.4" 67 | build_runner: 68 | dependency: "direct dev" 69 | description: 70 | name: build_runner 71 | url: "https://pub.dartlang.org" 72 | source: hosted 73 | version: "2.1.2" 74 | build_runner_core: 75 | dependency: transitive 76 | description: 77 | name: build_runner_core 78 | url: "https://pub.dartlang.org" 79 | source: hosted 80 | version: "7.1.0" 81 | build_verify: 82 | dependency: "direct dev" 83 | description: 84 | name: build_verify 85 | url: "https://pub.dartlang.org" 86 | source: hosted 87 | version: "2.0.0" 88 | built_collection: 89 | dependency: transitive 90 | description: 91 | name: built_collection 92 | url: "https://pub.dartlang.org" 93 | source: hosted 94 | version: "5.1.1" 95 | built_value: 96 | dependency: transitive 97 | description: 98 | name: built_value 99 | url: "https://pub.dartlang.org" 100 | source: hosted 101 | version: "8.1.2" 102 | charcode: 103 | dependency: transitive 104 | description: 105 | name: charcode 106 | url: "https://pub.dartlang.org" 107 | source: hosted 108 | version: "1.2.0" 109 | checked_yaml: 110 | dependency: transitive 111 | description: 112 | name: checked_yaml 113 | url: "https://pub.dartlang.org" 114 | source: hosted 115 | version: "2.0.1" 116 | cli_util: 117 | dependency: transitive 118 | description: 119 | name: cli_util 120 | url: "https://pub.dartlang.org" 121 | source: hosted 122 | version: "0.3.0" 123 | code_builder: 124 | dependency: transitive 125 | description: 126 | name: code_builder 127 | url: "https://pub.dartlang.org" 128 | source: hosted 129 | version: "4.1.0" 130 | collection: 131 | dependency: transitive 132 | description: 133 | name: collection 134 | url: "https://pub.dartlang.org" 135 | source: hosted 136 | version: "1.15.0" 137 | convert: 138 | dependency: transitive 139 | description: 140 | name: convert 141 | url: "https://pub.dartlang.org" 142 | source: hosted 143 | version: "3.0.0" 144 | coverage: 145 | dependency: transitive 146 | description: 147 | name: coverage 148 | url: "https://pub.dartlang.org" 149 | source: hosted 150 | version: "1.0.2" 151 | crypto: 152 | dependency: transitive 153 | description: 154 | name: crypto 155 | url: "https://pub.dartlang.org" 156 | source: hosted 157 | version: "3.0.0" 158 | dart_style: 159 | dependency: transitive 160 | description: 161 | name: dart_style 162 | url: "https://pub.dartlang.org" 163 | source: hosted 164 | version: "2.0.3" 165 | file: 166 | dependency: transitive 167 | description: 168 | name: file 169 | url: "https://pub.dartlang.org" 170 | source: hosted 171 | version: "6.1.0" 172 | fixnum: 173 | dependency: transitive 174 | description: 175 | name: fixnum 176 | url: "https://pub.dartlang.org" 177 | source: hosted 178 | version: "1.0.0" 179 | frontend_server_client: 180 | dependency: transitive 181 | description: 182 | name: frontend_server_client 183 | url: "https://pub.dartlang.org" 184 | source: hosted 185 | version: "2.1.2" 186 | glob: 187 | dependency: transitive 188 | description: 189 | name: glob 190 | url: "https://pub.dartlang.org" 191 | source: hosted 192 | version: "2.0.1" 193 | graphs: 194 | dependency: transitive 195 | description: 196 | name: graphs 197 | url: "https://pub.dartlang.org" 198 | source: hosted 199 | version: "2.0.0" 200 | http_multi_server: 201 | dependency: transitive 202 | description: 203 | name: http_multi_server 204 | url: "https://pub.dartlang.org" 205 | source: hosted 206 | version: "3.0.0" 207 | http_parser: 208 | dependency: transitive 209 | description: 210 | name: http_parser 211 | url: "https://pub.dartlang.org" 212 | source: hosted 213 | version: "4.0.0" 214 | io: 215 | dependency: transitive 216 | description: 217 | name: io 218 | url: "https://pub.dartlang.org" 219 | source: hosted 220 | version: "1.0.0" 221 | js: 222 | dependency: transitive 223 | description: 224 | name: js 225 | url: "https://pub.dartlang.org" 226 | source: hosted 227 | version: "0.6.3" 228 | json_annotation: 229 | dependency: transitive 230 | description: 231 | name: json_annotation 232 | url: "https://pub.dartlang.org" 233 | source: hosted 234 | version: "4.0.1" 235 | logging: 236 | dependency: transitive 237 | description: 238 | name: logging 239 | url: "https://pub.dartlang.org" 240 | source: hosted 241 | version: "1.0.0" 242 | matcher: 243 | dependency: transitive 244 | description: 245 | name: matcher 246 | url: "https://pub.dartlang.org" 247 | source: hosted 248 | version: "0.12.11" 249 | meta: 250 | dependency: transitive 251 | description: 252 | name: meta 253 | url: "https://pub.dartlang.org" 254 | source: hosted 255 | version: "1.7.0" 256 | mime: 257 | dependency: transitive 258 | description: 259 | name: mime 260 | url: "https://pub.dartlang.org" 261 | source: hosted 262 | version: "1.0.0" 263 | node_preamble: 264 | dependency: transitive 265 | description: 266 | name: node_preamble 267 | url: "https://pub.dartlang.org" 268 | source: hosted 269 | version: "2.0.0" 270 | package_config: 271 | dependency: transitive 272 | description: 273 | name: package_config 274 | url: "https://pub.dartlang.org" 275 | source: hosted 276 | version: "2.0.0" 277 | path: 278 | dependency: transitive 279 | description: 280 | name: path 281 | url: "https://pub.dartlang.org" 282 | source: hosted 283 | version: "1.8.0" 284 | pedantic: 285 | dependency: transitive 286 | description: 287 | name: pedantic 288 | url: "https://pub.dartlang.org" 289 | source: hosted 290 | version: "1.11.0" 291 | pool: 292 | dependency: transitive 293 | description: 294 | name: pool 295 | url: "https://pub.dartlang.org" 296 | source: hosted 297 | version: "1.5.0" 298 | pub_semver: 299 | dependency: transitive 300 | description: 301 | name: pub_semver 302 | url: "https://pub.dartlang.org" 303 | source: hosted 304 | version: "2.0.0" 305 | pubspec_parse: 306 | dependency: transitive 307 | description: 308 | name: pubspec_parse 309 | url: "https://pub.dartlang.org" 310 | source: hosted 311 | version: "1.0.0" 312 | shelf: 313 | dependency: transitive 314 | description: 315 | name: shelf 316 | url: "https://pub.dartlang.org" 317 | source: hosted 318 | version: "1.1.0" 319 | shelf_packages_handler: 320 | dependency: transitive 321 | description: 322 | name: shelf_packages_handler 323 | url: "https://pub.dartlang.org" 324 | source: hosted 325 | version: "3.0.0" 326 | shelf_static: 327 | dependency: transitive 328 | description: 329 | name: shelf_static 330 | url: "https://pub.dartlang.org" 331 | source: hosted 332 | version: "1.0.0" 333 | shelf_web_socket: 334 | dependency: transitive 335 | description: 336 | name: shelf_web_socket 337 | url: "https://pub.dartlang.org" 338 | source: hosted 339 | version: "1.0.1" 340 | simple_json: 341 | dependency: "direct dev" 342 | description: 343 | path: "../simple_json" 344 | relative: true 345 | source: path 346 | version: "2.2.0" 347 | simple_json_mapper: 348 | dependency: "direct main" 349 | description: 350 | path: "../simple_json_mapper" 351 | relative: true 352 | source: path 353 | version: "2.2.0" 354 | source_gen: 355 | dependency: transitive 356 | description: 357 | name: source_gen 358 | url: "https://pub.dartlang.org" 359 | source: hosted 360 | version: "1.1.0" 361 | source_map_stack_trace: 362 | dependency: transitive 363 | description: 364 | name: source_map_stack_trace 365 | url: "https://pub.dartlang.org" 366 | source: hosted 367 | version: "2.1.0" 368 | source_maps: 369 | dependency: transitive 370 | description: 371 | name: source_maps 372 | url: "https://pub.dartlang.org" 373 | source: hosted 374 | version: "0.10.10" 375 | source_span: 376 | dependency: transitive 377 | description: 378 | name: source_span 379 | url: "https://pub.dartlang.org" 380 | source: hosted 381 | version: "1.8.1" 382 | stack_trace: 383 | dependency: transitive 384 | description: 385 | name: stack_trace 386 | url: "https://pub.dartlang.org" 387 | source: hosted 388 | version: "1.10.0" 389 | stream_channel: 390 | dependency: transitive 391 | description: 392 | name: stream_channel 393 | url: "https://pub.dartlang.org" 394 | source: hosted 395 | version: "2.1.0" 396 | stream_transform: 397 | dependency: transitive 398 | description: 399 | name: stream_transform 400 | url: "https://pub.dartlang.org" 401 | source: hosted 402 | version: "2.0.0" 403 | string_scanner: 404 | dependency: transitive 405 | description: 406 | name: string_scanner 407 | url: "https://pub.dartlang.org" 408 | source: hosted 409 | version: "1.1.0" 410 | term_glyph: 411 | dependency: transitive 412 | description: 413 | name: term_glyph 414 | url: "https://pub.dartlang.org" 415 | source: hosted 416 | version: "1.2.0" 417 | test: 418 | dependency: "direct dev" 419 | description: 420 | name: test 421 | url: "https://pub.dartlang.org" 422 | source: hosted 423 | version: "1.17.12" 424 | test_api: 425 | dependency: transitive 426 | description: 427 | name: test_api 428 | url: "https://pub.dartlang.org" 429 | source: hosted 430 | version: "0.4.3" 431 | test_core: 432 | dependency: transitive 433 | description: 434 | name: test_core 435 | url: "https://pub.dartlang.org" 436 | source: hosted 437 | version: "0.4.2" 438 | timing: 439 | dependency: transitive 440 | description: 441 | name: timing 442 | url: "https://pub.dartlang.org" 443 | source: hosted 444 | version: "1.0.0" 445 | typed_data: 446 | dependency: transitive 447 | description: 448 | name: typed_data 449 | url: "https://pub.dartlang.org" 450 | source: hosted 451 | version: "1.3.0" 452 | uuid: 453 | dependency: "direct main" 454 | description: 455 | name: uuid 456 | url: "https://pub.dartlang.org" 457 | source: hosted 458 | version: "3.0.4" 459 | vm_service: 460 | dependency: transitive 461 | description: 462 | name: vm_service 463 | url: "https://pub.dartlang.org" 464 | source: hosted 465 | version: "6.1.0+1" 466 | watcher: 467 | dependency: transitive 468 | description: 469 | name: watcher 470 | url: "https://pub.dartlang.org" 471 | source: hosted 472 | version: "1.0.0" 473 | web_socket_channel: 474 | dependency: transitive 475 | description: 476 | name: web_socket_channel 477 | url: "https://pub.dartlang.org" 478 | source: hosted 479 | version: "2.0.0" 480 | webkit_inspection_protocol: 481 | dependency: transitive 482 | description: 483 | name: webkit_inspection_protocol 484 | url: "https://pub.dartlang.org" 485 | source: hosted 486 | version: "1.0.0" 487 | yaml: 488 | dependency: transitive 489 | description: 490 | name: yaml 491 | url: "https://pub.dartlang.org" 492 | source: hosted 493 | version: "3.1.0" 494 | sdks: 495 | dart: ">=2.12.0 <3.0.0" 496 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: simple_json_example 2 | publish_to: none 3 | 4 | environment: 5 | sdk: ">=2.12.0 <3.0.0" 6 | 7 | dependencies: 8 | simple_json_mapper: ^2.2.0 9 | uuid: ^3.0.4 10 | 11 | dependency_overrides: 12 | simple_json_mapper: 13 | path: ../simple_json_mapper 14 | 15 | dev_dependencies: 16 | build_runner: ^2.1.2 17 | build_verify: ^2.0.0 18 | test: ^1.17.12 19 | simple_json: 20 | path: ../simple_json 21 | -------------------------------------------------------------------------------- /package.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "simple_json" 5 | }, 6 | { 7 | "path": "simple_json_mapper" 8 | }, 9 | { 10 | "path": "example" 11 | } 12 | ], 13 | "settings": {} 14 | } -------------------------------------------------------------------------------- /simple_json/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: c264b70ec3b0cf9cd568eba5d65d0ce47fe57e1d 8 | channel: dev 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /simple_json/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Dart Example", 9 | "program": "example/lib/main.dart", 10 | "request": "launch", 11 | "type": "dart" 12 | } 13 | ] 14 | } -------------------------------------------------------------------------------- /simple_json/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 2.2.0 - 09/07/2021 2 | 3 | - Update dependencies. 4 | 5 | ## 2.1.1 - 03/22/2021 6 | 7 | - Enum `orElse` `null` bug fix. 8 | 9 | ## 2.1.0 - 03/21/2021 10 | 11 | - Support null safety. 12 | 13 | ## 1.2.2 - 01/15/2020 14 | 15 | - Support List of enum. 16 | 17 | ## 1.2.1 - 12/30/2020 18 | 19 | - Fix enum value serialization in edge cases. 20 | 21 | ## 1.2.0 - 12/20/2020 22 | 23 | - Update dependencies and support nullability language changes. 24 | 25 | ## 1.1.8 - 12/20/2020 26 | 27 | - Update dependency versions 28 | 29 | ## 1.1.7 - 10/15/2020 30 | 31 | - Fix bug to allow null enum values. 32 | 33 | ## 1.1.6 - 09/29/2020 34 | 35 | - Fix bug with converter types. 36 | 37 | ## 1.1.5 - 09/29/2020 38 | 39 | - Fix list converter types. 40 | 41 | ## 1.1.4 - 09/29/2020 42 | 43 | - Fix list skipped types. 44 | 45 | ## 1.1.3 - 09/24/2020 46 | 47 | - Add support for automatic registration of custom converters that use the `JsonConvert` class as the super type. 48 | 49 | ## 1.1.2 - 08/31/2020 50 | 51 | - Support `Duration` class serialization. 52 | 53 | ## 1.1.1 - 07/09/2020 54 | 55 | - Bug fix with dynamic type. 56 | 57 | ## 1.1.0 - 07/09/2020 58 | 59 | - Bug fix and keep version in sync. 60 | 61 | ## 1.0.2 - 07/06/2020 62 | 63 | - Fix bug by adding null aware operators. 64 | 65 | ## 1.0.0 - 07/01/2020 66 | 67 | - Fix bugs and remove generic type parameter from the `serialize` and related methods. 68 | 69 | ## 0.4.4 - 07/01/2020 70 | 71 | - Fix generated code that uses `dynamic` type. 72 | 73 | ## 0.4.3 - 07/01/2020 74 | 75 | - Skip `dynamic` type processing. 76 | 77 | ## 0.4.2 - 07/01/2020 78 | 79 | - Add nullable checks to prevent exceptions. 80 | 81 | ## 0.4.1 - 07/01/2020 82 | 83 | - Fix infinite loop bug. 84 | 85 | ## 0.4.0 - 07/01/2020 86 | 87 | - Support list casting for list de-serialization. 88 | 89 | ## 0.3.5 - 07/01/2020 90 | 91 | - Fix bugs with abstract and enum class registrations and importing of implicitly opted enums. 92 | 93 | ## 0.3.4 - 07/01/2020 94 | 95 | - Support `Map` with primitive type arguments. 96 | 97 | ## 0.3.3 - 07/01/2020 98 | 99 | - Fix another bug with missing `unnamedConstructor` for types. 100 | 101 | ## 0.3.2 - 07/01/2020 102 | 103 | - Fix bug with missing `unnamedConstructor` for types. 104 | 105 | ## 0.3.1 - 07/01/2020 106 | 107 | - Fix bug with non-dart library file causing no output. 108 | 109 | ## 0.3.0 - 07/01/2020 110 | 111 | - Fix generator failure when a non-dart library file is found. 112 | - Use explicit types for generated serialization code. 113 | 114 | ## 0.2.6 - 06/28/2020 115 | 116 | - Fix bug with nested implicitly opted types 117 | 118 | ## 0.2.5 - 06/28/2020 119 | 120 | - Ignore external alias type when revealing other supertype. 121 | 122 | ## 0.2.4 - 06/28/2020 123 | 124 | - Added external type serialization support. 125 | 126 | ## 0.2.3 - 06/28/2020 127 | 128 | - Fix bug with `EnumValue` annotation. 129 | 130 | ## 0.2.2 - 06/24/2020 131 | 132 | - Update README. 133 | 134 | ## 0.2.1 - 06/24/2020 135 | 136 | - Update README. 137 | 138 | ## 0.2.0 - 06/24/2020 139 | 140 | - Add support for custom json mappers, converters, and super classes. 141 | - Edge case bug fixes. 142 | 143 | ## 0.1.5 - 06/21/2020 144 | 145 | - Update README. 146 | 147 | ## 0.1.4 - 06/21/2020 148 | 149 | - Update README. 150 | 151 | ## 0.1.3 - 06/21/2020 152 | 153 | - Update README links. 154 | 155 | ## 0.1.2 - 06/21/2020 156 | 157 | - Update README links. 158 | 159 | ## 0.1.1 - 06/21/2020 160 | 161 | - Update README and unannotated, linked class warning message. 162 | 163 | ## 0.1.0 - 06/20/2020 164 | 165 | - Initial release. 166 | -------------------------------------------------------------------------------- /simple_json/LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2020, Flutter Dev Tools 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /simple_json/README.md: -------------------------------------------------------------------------------- 1 | # simple_json 2 | Simple way to dynamically convert from and to JSON using build-time generators given a type. 3 | 4 | **Note**: Ignore the warning and tags indicating that this package is no compatible with the Flutter and other SDKs. This is reported because this generator package uses `dart:mirrors` library which is not supported by those SDKs. In this case, it will all work fine as this package is supposed to be just build-time generators. This package should **ONLY** be added under `dev_dependencies` to work correctly. The supporting [simple_json_mapper](https://pub.dev/packages/simple_json_mapper) package also needs to be included but as a regular dependency under `dependencies`. 5 | 6 | ### How? 7 | 1. A single `mapper.g.dart` is generated at build-time when the `build_runner build` command is executed. [View example of generated file](example/lib/mapper.g.dart). [Advanced example](../example/lib/mapper.g.dart) 8 | 2. This generated file contains the necessary code (serialization and de-serialization logic) to map from and to JSON. 9 | 3. These object mappers are registered with the JSON Mapper in the init function. 10 | 4. The init function is the first line of code that should be executed in your `main.dart` file. 11 | 5. At runtime, all of the mappers are registered (using the aforementioned `init` method) and can then be looked up using the class type parameter passed into the `serialize` or `deserialize` generic methods. 12 | 13 | ### Why? 14 | - Simple 15 | - No messy `.g.dart` files for each serializable file (single root-level file which contains all of the generated code) 16 | - Dynamic serialization and de-serialization without using the actual type directly while still maintaining type-safety. i.e. `JsonMapper.serialize(account)` vs `account.toJson()` (account does not need to have any logic and it is not used directly for the actual serialization) 17 | - Model files stay clean (no extra generated code) and don't care about the serialization logic (SRP) 18 | - No need to specify custom object and iterable type casting 19 | - No bloated reflection on the entire type with linting/analyzer issues 20 | 21 | Dynamic serialization and de-serialization allows for allow for creating great type-safe APIs. A good example is a simple storage service in flutter. 22 | 23 |
24 | storage_service.dart 25 | 26 | ```dart 27 | class StorageService implements IStorageService { 28 | const StorageService(this.preferences); 29 | final SharedPreferences preferences; 30 | 31 | @override 32 | Future get({T Function() defaultFn, bool private = false}) async { 33 | return getWithKey(T.toString(), defaultFn: defaultFn, private: private); 34 | } 35 | 36 | @override 37 | Future getWithKey(String key, 38 | {T Function() defaultFn, bool private = false}) async { 39 | return JsonMapper.deserialize( 40 | await getProvider(private).getString(key)) ?? 41 | defaultFn(); 42 | } 43 | 44 | @override 45 | Future set(T value, [bool private = false]) { 46 | return setWithKey(T.toString(), value, private); 47 | } 48 | 49 | @override 50 | Future setWithKey(String key, T value, [bool private = false]) { 51 | return getProvider(private).setString(key, JsonMapper.serialize(value)); 52 | } 53 | 54 | IStorageProvider getProvider(bool private) { 55 | return private && !AppUtils.isWeb 56 | ? SecureStorage() 57 | : SharedPreferencesStorage(preferences); 58 | } 59 | } 60 | 61 | ``` 62 |
63 | 64 | Using `simple_json`, this `StorageService` has a simple generic type-safe API that can store serialize the models classes before storing them as string making it really simple and boilerplate-free. 65 | 66 | ## Quick Start 67 | 68 | pubspec.yaml (**Note**: `simple_json` must be added under `dev_dependencies`) 69 | ```yaml 70 | dependencies: 71 | simple_json_mapper: ^2.2.0 72 | 73 | dev_dependencies: 74 | simple_json: ^2.2.0 75 | build_runner: ^1.10.0 76 | ``` 77 | 78 | ### Setup 79 | main.dart 80 | ```dart 81 | // Generated file. Can be added to .gitignore 82 | import 'mapper.g.dart' as mapper; 83 | 84 | void main() { 85 | mapper.init(); 86 | ... 87 | } 88 | ``` 89 | 90 | ### Usage 91 | **Model** 92 | ```dart 93 | import 'package:simple_json_mapper/simple_json_mapper.dart'; 94 | 95 | // Required annotation/decorator to opt-in model for json setup. Alias for [JsonObject] 96 | @JObj() 97 | class Account { 98 | const Account({ 99 | this.type, 100 | this.name, 101 | this.number, 102 | this.amount, 103 | this.transactionCount, 104 | this.isActive, 105 | this.product, 106 | this.localText, 107 | }); 108 | // Specify the enum serialization type (index or value based). Alias for [JsonEnumProperty] 109 | // SerializationType.Index: Savings = 0, Checking = 1 110 | // SerializationType.Value: Savings = 'Savings', Checking = 'Checking' 111 | // Enum fields can be annotated with [EnumValue] to provide a custom value. 112 | @JEnumProp(serializationType: SerializationType.Index) 113 | final AccountType type; 114 | final String name; 115 | final String number; 116 | final double amount; 117 | 118 | @JsonProperty(name: 'tranCount', defaultValue: 11) 119 | final int transactionCount; 120 | 121 | final bool isActive; 122 | 123 | // Alias for [JsonProperty] 124 | @JProp(ignore: true) 125 | final String localText; 126 | 127 | final Product product; 128 | } 129 | 130 | @JsonObject() 131 | class Product { 132 | const Product({this.name, this.expiry, this.sizes, this.tests}); 133 | final String name; 134 | final DateTime expiry; 135 | final List sizes; 136 | final List tests; 137 | } 138 | 139 | // Linked models don't require the annotation but it is recommended. 140 | class Test { 141 | const Test({this.name}); 142 | final String name; 143 | } 144 | 145 | enum AccountType { 146 | // Override serialization enum value 147 | @EnumValue(value: 25) 148 | Savings, 149 | @EnumValue(value: 10) 150 | Checking 151 | } 152 | 153 | ``` 154 | 155 | #### Serialization 156 | ```dart 157 | final product = Product( 158 | name: 'Test', 159 | expiry: DateTime.now(), 160 | sizes: [10, 20, 40], 161 | tests: [ 162 | Test(name: 'hello'), 163 | Test(name: 'blah'), 164 | ], 165 | ); 166 | final account = Account( 167 | type: AccountType.Checking, 168 | name: 'Test', 169 | number: 'xxx12414', 170 | amount: 100.50, 171 | transactionCount: 10, 172 | isActive: true, 173 | product: product, 174 | localText: 'ignored text', 175 | ); 176 | final accountJson = JsonMapper.serialize(account); 177 | ``` 178 | 179 | #### De-serialization 180 | 181 | ```dart 182 | final account = JsonMapper.deserialize(accountJson); 183 | ``` 184 | 185 | ### Converters 186 | 187 | ```dart 188 | // Convert all deserialized strings to lowercase and all serialized strings to uppercase. 189 | JsonMapper.registerConverter( 190 | JsonConverter.fromFunction( 191 | fromJson: (value) => value.toLowerCase(), 192 | toJson: (value) => value.toUpperCase(), 193 | ), 194 | ); 195 | 196 | // Converter for transforming all DateTime string values to a special format defined by the given class. 197 | JsonMapper.registerConverter(SpecialDateTimeConverter()); 198 | ``` 199 | 200 | #### Custom JsonMapper 201 | 202 | ```dart 203 | // Custom mapper that has it own set of converters. Useful for encapsulating for special, adhoc serializations 204 | // e.g. SQLite 205 | final customMapper = CustomJsonMapper( 206 | converters: [ 207 | // Converter for changing all boolean values from boolean to int and vice versa on serialization. 208 | JsonConverter.fromFunction( 209 | fromJson: (value) => value == 1 ? true : false, 210 | toJson: (value) => value ? 1 : 0, 211 | ), 212 | ], 213 | ); 214 | // Note the usage of [customerMapper] here. 215 | print(customMapper.serialize(account)); 216 | ``` 217 | 218 | **Refer to the [advanced example](../example/lib/main.dart) for advanced usage of functionalities.** 219 | 220 | ### Generating Mapper File 221 | 222 | *build* 223 | ```bash 224 | # dart 225 | pub get 226 | pub run build_runner build 227 | # flutter 228 | flutter pub get 229 | flutter packages pub run build_runner build 230 | ``` 231 | 232 | *watch* 233 | ```bash 234 | # dart 235 | pub get 236 | pub run build_runner watch 237 | # flutter 238 | flutter pub get 239 | flutter packages pub run build_runner watch 240 | ``` 241 | -------------------------------------------------------------------------------- /simple_json/build.yaml: -------------------------------------------------------------------------------- 1 | builders: 2 | simple_json: 3 | import: "package:simple_json/simple_json.dart" 4 | builder_factories: ["jsonMapperBuilder"] 5 | build_extensions: { "$lib$": ["mapper.g.dart"] } 6 | auto_apply: all_packages 7 | build_to: source -------------------------------------------------------------------------------- /simple_json/example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:simple_json_mapper/simple_json_mapper.dart'; 2 | import 'mapper.g.dart' as mapper; 3 | 4 | void main() { 5 | mapper.init(); 6 | // Be sure to run these commands before running this example 7 | // pub get 8 | // pub run build_runner build 9 | final jsonStr = JsonMapper.serialize(Test(name: 'Blah')); 10 | print('Serialized JSON:'); 11 | print(jsonStr); 12 | print('\nDeserialized and re-serialized JSON:'); 13 | print(JsonMapper.serialize(JsonMapper.deserialize(jsonStr))); 14 | } 15 | 16 | @JObj() 17 | class Test { 18 | const Test({required this.name}); 19 | final String name; 20 | } 21 | -------------------------------------------------------------------------------- /simple_json/example/lib/mapper.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | // Generated and consumed by 'simple_json' 3 | 4 | import 'package:simple_json_mapper/simple_json_mapper.dart'; 5 | import 'package:simple_json_example/main.dart'; 6 | 7 | final _testMapper = JsonObjectMapper( 8 | (CustomJsonMapper mapper, Map json) => Test( 9 | name: mapper.applyFromJsonConverter(json['null']), 10 | ), 11 | (CustomJsonMapper mapper, Test instance) => { 12 | 'null': mapper.applyFromInstanceConverter(instance.name), 13 | }, 14 | ); 15 | 16 | void init() { 17 | JsonMapper.register(_testMapper); 18 | 19 | 20 | 21 | JsonMapper.registerListCast((value) => value?.cast().toList()); 22 | } 23 | -------------------------------------------------------------------------------- /simple_json/example/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | _fe_analyzer_shared: 5 | dependency: transitive 6 | description: 7 | name: _fe_analyzer_shared 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "25.0.0" 11 | analyzer: 12 | dependency: transitive 13 | description: 14 | name: analyzer 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "2.2.0" 18 | args: 19 | dependency: transitive 20 | description: 21 | name: args 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "2.2.0" 25 | async: 26 | dependency: transitive 27 | description: 28 | name: async 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "2.5.0" 32 | build: 33 | dependency: transitive 34 | description: 35 | name: build 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "2.1.0" 39 | build_config: 40 | dependency: transitive 41 | description: 42 | name: build_config 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "1.0.0" 46 | build_daemon: 47 | dependency: transitive 48 | description: 49 | name: build_daemon 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "3.0.0" 53 | build_resolvers: 54 | dependency: transitive 55 | description: 56 | name: build_resolvers 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "2.0.4" 60 | build_runner: 61 | dependency: "direct dev" 62 | description: 63 | name: build_runner 64 | url: "https://pub.dartlang.org" 65 | source: hosted 66 | version: "2.1.2" 67 | build_runner_core: 68 | dependency: transitive 69 | description: 70 | name: build_runner_core 71 | url: "https://pub.dartlang.org" 72 | source: hosted 73 | version: "7.1.0" 74 | built_collection: 75 | dependency: transitive 76 | description: 77 | name: built_collection 78 | url: "https://pub.dartlang.org" 79 | source: hosted 80 | version: "5.1.1" 81 | built_value: 82 | dependency: transitive 83 | description: 84 | name: built_value 85 | url: "https://pub.dartlang.org" 86 | source: hosted 87 | version: "8.1.2" 88 | charcode: 89 | dependency: transitive 90 | description: 91 | name: charcode 92 | url: "https://pub.dartlang.org" 93 | source: hosted 94 | version: "1.2.0" 95 | checked_yaml: 96 | dependency: transitive 97 | description: 98 | name: checked_yaml 99 | url: "https://pub.dartlang.org" 100 | source: hosted 101 | version: "2.0.1" 102 | cli_util: 103 | dependency: transitive 104 | description: 105 | name: cli_util 106 | url: "https://pub.dartlang.org" 107 | source: hosted 108 | version: "0.3.0" 109 | code_builder: 110 | dependency: transitive 111 | description: 112 | name: code_builder 113 | url: "https://pub.dartlang.org" 114 | source: hosted 115 | version: "4.1.0" 116 | collection: 117 | dependency: transitive 118 | description: 119 | name: collection 120 | url: "https://pub.dartlang.org" 121 | source: hosted 122 | version: "1.15.0" 123 | convert: 124 | dependency: transitive 125 | description: 126 | name: convert 127 | url: "https://pub.dartlang.org" 128 | source: hosted 129 | version: "3.0.0" 130 | crypto: 131 | dependency: transitive 132 | description: 133 | name: crypto 134 | url: "https://pub.dartlang.org" 135 | source: hosted 136 | version: "3.0.0" 137 | dart_style: 138 | dependency: transitive 139 | description: 140 | name: dart_style 141 | url: "https://pub.dartlang.org" 142 | source: hosted 143 | version: "2.0.3" 144 | file: 145 | dependency: transitive 146 | description: 147 | name: file 148 | url: "https://pub.dartlang.org" 149 | source: hosted 150 | version: "6.1.0" 151 | fixnum: 152 | dependency: transitive 153 | description: 154 | name: fixnum 155 | url: "https://pub.dartlang.org" 156 | source: hosted 157 | version: "1.0.0" 158 | frontend_server_client: 159 | dependency: transitive 160 | description: 161 | name: frontend_server_client 162 | url: "https://pub.dartlang.org" 163 | source: hosted 164 | version: "2.1.2" 165 | glob: 166 | dependency: transitive 167 | description: 168 | name: glob 169 | url: "https://pub.dartlang.org" 170 | source: hosted 171 | version: "2.0.1" 172 | graphs: 173 | dependency: transitive 174 | description: 175 | name: graphs 176 | url: "https://pub.dartlang.org" 177 | source: hosted 178 | version: "2.0.0" 179 | http_multi_server: 180 | dependency: transitive 181 | description: 182 | name: http_multi_server 183 | url: "https://pub.dartlang.org" 184 | source: hosted 185 | version: "3.0.1" 186 | http_parser: 187 | dependency: transitive 188 | description: 189 | name: http_parser 190 | url: "https://pub.dartlang.org" 191 | source: hosted 192 | version: "4.0.0" 193 | io: 194 | dependency: transitive 195 | description: 196 | name: io 197 | url: "https://pub.dartlang.org" 198 | source: hosted 199 | version: "1.0.3" 200 | js: 201 | dependency: transitive 202 | description: 203 | name: js 204 | url: "https://pub.dartlang.org" 205 | source: hosted 206 | version: "0.6.3" 207 | json_annotation: 208 | dependency: transitive 209 | description: 210 | name: json_annotation 211 | url: "https://pub.dartlang.org" 212 | source: hosted 213 | version: "4.0.1" 214 | logging: 215 | dependency: transitive 216 | description: 217 | name: logging 218 | url: "https://pub.dartlang.org" 219 | source: hosted 220 | version: "1.0.0" 221 | matcher: 222 | dependency: transitive 223 | description: 224 | name: matcher 225 | url: "https://pub.dartlang.org" 226 | source: hosted 227 | version: "0.12.11" 228 | meta: 229 | dependency: transitive 230 | description: 231 | name: meta 232 | url: "https://pub.dartlang.org" 233 | source: hosted 234 | version: "1.7.0" 235 | mime: 236 | dependency: transitive 237 | description: 238 | name: mime 239 | url: "https://pub.dartlang.org" 240 | source: hosted 241 | version: "1.0.0" 242 | package_config: 243 | dependency: transitive 244 | description: 245 | name: package_config 246 | url: "https://pub.dartlang.org" 247 | source: hosted 248 | version: "2.0.0" 249 | path: 250 | dependency: transitive 251 | description: 252 | name: path 253 | url: "https://pub.dartlang.org" 254 | source: hosted 255 | version: "1.8.0" 256 | pedantic: 257 | dependency: transitive 258 | description: 259 | name: pedantic 260 | url: "https://pub.dartlang.org" 261 | source: hosted 262 | version: "1.11.0" 263 | pool: 264 | dependency: transitive 265 | description: 266 | name: pool 267 | url: "https://pub.dartlang.org" 268 | source: hosted 269 | version: "1.5.0" 270 | pub_semver: 271 | dependency: transitive 272 | description: 273 | name: pub_semver 274 | url: "https://pub.dartlang.org" 275 | source: hosted 276 | version: "2.0.0" 277 | pubspec_parse: 278 | dependency: transitive 279 | description: 280 | name: pubspec_parse 281 | url: "https://pub.dartlang.org" 282 | source: hosted 283 | version: "1.0.0" 284 | shelf: 285 | dependency: transitive 286 | description: 287 | name: shelf 288 | url: "https://pub.dartlang.org" 289 | source: hosted 290 | version: "1.2.0" 291 | shelf_web_socket: 292 | dependency: transitive 293 | description: 294 | name: shelf_web_socket 295 | url: "https://pub.dartlang.org" 296 | source: hosted 297 | version: "1.0.1" 298 | simple_json: 299 | dependency: "direct main" 300 | description: 301 | path: ".." 302 | relative: true 303 | source: path 304 | version: "2.2.0" 305 | simple_json_mapper: 306 | dependency: "direct main" 307 | description: 308 | path: "../../simple_json_mapper" 309 | relative: true 310 | source: path 311 | version: "2.2.0" 312 | source_gen: 313 | dependency: transitive 314 | description: 315 | name: source_gen 316 | url: "https://pub.dartlang.org" 317 | source: hosted 318 | version: "1.1.0" 319 | source_span: 320 | dependency: transitive 321 | description: 322 | name: source_span 323 | url: "https://pub.dartlang.org" 324 | source: hosted 325 | version: "1.8.1" 326 | stack_trace: 327 | dependency: transitive 328 | description: 329 | name: stack_trace 330 | url: "https://pub.dartlang.org" 331 | source: hosted 332 | version: "1.10.0" 333 | stream_channel: 334 | dependency: transitive 335 | description: 336 | name: stream_channel 337 | url: "https://pub.dartlang.org" 338 | source: hosted 339 | version: "2.1.0" 340 | stream_transform: 341 | dependency: transitive 342 | description: 343 | name: stream_transform 344 | url: "https://pub.dartlang.org" 345 | source: hosted 346 | version: "2.0.0" 347 | string_scanner: 348 | dependency: transitive 349 | description: 350 | name: string_scanner 351 | url: "https://pub.dartlang.org" 352 | source: hosted 353 | version: "1.1.0" 354 | term_glyph: 355 | dependency: transitive 356 | description: 357 | name: term_glyph 358 | url: "https://pub.dartlang.org" 359 | source: hosted 360 | version: "1.2.0" 361 | timing: 362 | dependency: transitive 363 | description: 364 | name: timing 365 | url: "https://pub.dartlang.org" 366 | source: hosted 367 | version: "1.0.0" 368 | typed_data: 369 | dependency: transitive 370 | description: 371 | name: typed_data 372 | url: "https://pub.dartlang.org" 373 | source: hosted 374 | version: "1.3.0" 375 | watcher: 376 | dependency: transitive 377 | description: 378 | name: watcher 379 | url: "https://pub.dartlang.org" 380 | source: hosted 381 | version: "1.0.0" 382 | web_socket_channel: 383 | dependency: transitive 384 | description: 385 | name: web_socket_channel 386 | url: "https://pub.dartlang.org" 387 | source: hosted 388 | version: "2.1.0" 389 | yaml: 390 | dependency: transitive 391 | description: 392 | name: yaml 393 | url: "https://pub.dartlang.org" 394 | source: hosted 395 | version: "3.1.0" 396 | sdks: 397 | dart: ">=2.12.0 <3.0.0" 398 | -------------------------------------------------------------------------------- /simple_json/example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: simple_json_example 2 | description: simple_json example project 3 | version: 0.1.0 4 | homepage: https://github.com/FlutterDevTools/simple_json 5 | publish_to: none 6 | 7 | environment: 8 | sdk: ">=2.12.0 <3.0.0" 9 | 10 | dependencies: 11 | simple_json_mapper: ^2.2.0 12 | simple_json: 13 | path: ../ 14 | 15 | dependency_overrides: 16 | simple_json_mapper: 17 | path: ../../simple_json_mapper 18 | 19 | dev_dependencies: 20 | build_runner: ^2.1.2 21 | -------------------------------------------------------------------------------- /simple_json/lib/simple_json.dart: -------------------------------------------------------------------------------- 1 | library simple_json; 2 | 3 | import 'package:simple_json/src/json_mapper_builder.dart'; 4 | 5 | JsonMapperBuilder jsonMapperBuilder(_) => JsonMapperBuilder(); 6 | -------------------------------------------------------------------------------- /simple_json/lib/src/generated_example.dart.md: -------------------------------------------------------------------------------- 1 | ```dart 2 | import 'package:simple_json/builder.dart'; 3 | 4 | final _personMapper = JsonObjectMapper( 5 | (Map json) => Person( 6 | firstName: json['firstName'] as String, 7 | lastName: json['lastName'] as String, 8 | dateOfBirth: DateTime.parse(json['dateOfBirth'] as String), 9 | ), 10 | (Person instance) => { 11 | 'firstName': instance.firstName, 12 | 'lastName': instance.lastName, 13 | 'dateOfBirth': instance.dateOfBirth.toIso8601String(), 14 | }, 15 | ); 16 | 17 | void init() { 18 | JsonMapper.register(_personMapper); 19 | } 20 | ``` -------------------------------------------------------------------------------- /simple_json/lib/src/json_mapper_builder.dart: -------------------------------------------------------------------------------- 1 | import 'package:analyzer/dart/constant/value.dart'; 2 | import 'package:analyzer/dart/element/element.dart'; 3 | import 'package:analyzer/dart/element/type.dart'; 4 | import 'package:build/build.dart'; 5 | import 'package:collection/collection.dart' show IterableExtension; 6 | import 'package:glob/glob.dart'; 7 | import 'package:simple_json_mapper/simple_json_mapper.dart'; 8 | import 'package:source_gen/source_gen.dart'; 9 | import 'package:path/path.dart' as p; 10 | 11 | import 'utils.dart'; 12 | 13 | class JsonMapperBuilder implements Builder { 14 | JsonMapperBuilder(); 15 | 16 | static final _allFilesInLib = new Glob('lib/**'); 17 | 18 | final implicitlyOptedTypes = Set(); 19 | final usedElements = Set(); 20 | final converterTypes = {'$DateTime', '$Duration'}; 21 | 22 | @override 23 | Map> get buildExtensions { 24 | return const { 25 | r'$lib$': ['mapper.g.dart'] 26 | }; 27 | } 28 | 29 | static AssetId _allFileOutput(BuildStep buildStep) { 30 | return AssetId( 31 | buildStep.inputId.package, 32 | p.join('lib', 'mapper.g.dart'), 33 | ); 34 | } 35 | 36 | @override 37 | Future build(BuildStep buildStep) async { 38 | final lines = []; 39 | final annotatedClassesInLibrary = []; 40 | final converterClasses = []; 41 | await for (final input in buildStep.findAssets(_allFilesInLib)) { 42 | if (!await buildStep.resolver.isLibrary(input)) continue; 43 | final library = await buildStep.resolver.libraryFor(input); 44 | final reader = LibraryReader(library); 45 | converterClasses.addAll(reader.classes.where((c) => 46 | TypeChecker.fromRuntime(JsonConverter) 47 | .isSuperOf(reader.classes.toList()[0]))); 48 | 49 | annotatedClassesInLibrary.addAll(reader 50 | .annotatedWith(TypeChecker.fromRuntime(JsonObject)) 51 | .where((match) => match.element is ClassElement) 52 | .map((match) => match.element as ClassElement) 53 | .toList()); 54 | } 55 | 56 | converterTypes.addAll(converterClasses 57 | .map((c) => c.supertype!.typeArguments[1]) 58 | .where((type) => !isPrimitiveType(type)) 59 | .map((t) => t.getDisplayString(withNullability: false)) 60 | .toList()); 61 | final annotatedClasses = annotatedClassesInLibrary.toSet(); 62 | final aliases = annotatedClasses.where((libClass) { 63 | final redirectedCtor = libClass.unnamedConstructor?.redirectedConstructor; 64 | final superTypeCtor = libClass.supertype?.element.unnamedConstructor; 65 | return redirectedCtor != null && 66 | superTypeCtor != null && 67 | redirectedCtor == superTypeCtor; 68 | }).toList(); 69 | aliases.forEach((alias) { 70 | annotatedClasses.remove(alias); 71 | annotatedClasses.add(alias.supertype!.element); 72 | }); 73 | 74 | final mappers = annotatedClasses.map((c) => _generateMapper(c)).toList(); 75 | 76 | final allImplicitlyOptedClasses = Set(); 77 | while (true) { 78 | final implicitlyOptedClassTypes = implicitlyOptedTypes 79 | .where((match) => match!.element is ClassElement) 80 | .map((match) => match!.element as ClassElement?) 81 | .toSet() 82 | .difference(annotatedClasses.toSet()) 83 | .difference(allImplicitlyOptedClasses); 84 | if (implicitlyOptedClassTypes.isEmpty) break; 85 | allImplicitlyOptedClasses.addAll(implicitlyOptedClassTypes); 86 | implicitlyOptedTypes.clear(); 87 | mappers.addAll(implicitlyOptedClassTypes.map((c) => _generateMapper(c!))); 88 | } 89 | 90 | print( 91 | 'WARNING: Generated mappings for the following unannotated types: ${allImplicitlyOptedClasses.map((t) => t.toString()).join(', ')}'); 92 | 93 | final classes = [...annotatedClasses, ...allImplicitlyOptedClasses]; 94 | final imports = 95 | _generateHeader([...classes, ...converterClasses, ...usedElements]); 96 | final registrations = _generateInit( 97 | classes 98 | .where((c) => 99 | c!.unnamedConstructor != null && !c.isEnum && !c.isAbstract) 100 | .toList(), 101 | classes, 102 | converterClasses); 103 | 104 | lines.add(imports); 105 | lines.addAll(mappers); 106 | lines.add(registrations); 107 | 108 | await buildStep.writeAsString(_allFileOutput(buildStep), lines.join('\n')); 109 | } 110 | 111 | String _generateMapper(ClassElement element) { 112 | if (element.unnamedConstructor == null || 113 | element.isEnum || 114 | element.isAbstract) return ''; 115 | 116 | final elementName = element.name; 117 | final parameters = element.unnamedConstructor!.parameters; 118 | return ''' 119 | 120 | final _${elementName.toLowerCase()}Mapper = JsonObjectMapper( 121 | (CustomJsonMapper mapper, Map json) => ${elementName}( 122 | ${parameters.map(_generateFromMapItem).where((line) => line != null).join('\n ')} 123 | ), 124 | (CustomJsonMapper mapper, ${elementName} instance) => { 125 | ${parameters.map(_generateToMapItem).where((line) => line != null).join('\n ')} 126 | }, 127 | ); 128 | '''; 129 | } 130 | 131 | String? _generateFromMapItem(ParameterElement param) { 132 | final converterProp = getConverterProp(param); 133 | final prop = getProp(param); 134 | if (prop.ignore ?? false) return null; 135 | final name = param.name; 136 | final jsonName = prop.name ?? name; 137 | final accessorStr = "json['$jsonName']"; 138 | final converterWrapper = (String val, [String? type]) => 139 | 'mapper.applyDynamicFromJsonConverter${type != null ? '<$type>' : ''}($val${converterProp != null ? ', $converterProp' : ''})'; 140 | final String Function([String]) valFn = ([String? asType]) { 141 | final accStr = asType == null 142 | ? converterWrapper( 143 | accessorStr, param.type.isDynamic ? 'dynamic' : null) 144 | : accessorStr; 145 | return '''$accStr${asType != null ? ' as $asType${param.isOptional ? '?' : ''}' : ''}'''; 146 | }; 147 | final String Function(ParameterElement, 148 | {bool explicitType, String name, DartType? type}) _genEnum = 149 | (ParameterElement param, 150 | {DartType? type, String? name, bool explicitType = false}) { 151 | implicitlyOptedTypes.add(param.type); 152 | final enumProp = getEnumProp(param); 153 | final enumValueMap = cleanMap(getEnumValueMap(enumProp, 154 | param: param, enumClassEl: type?.element as ClassElement?)); 155 | final normalizedType = type ?? param.type; 156 | return converterWrapper( 157 | _generateEnumFromMap( 158 | normalizedType, param.name, enumProp, enumValueMap, 159 | compare: explicitType ? 'item?.toString()' : null), 160 | explicitType ? normalizedType.element!.name : null); 161 | }; 162 | var val; 163 | final isList = param.type.isDartCoreList; 164 | final isMap = param.type.isDartCoreMap; 165 | if (isList) { 166 | final typeArgs = (param.type as InterfaceType).typeArguments; 167 | final firstTypeArg = typeArgs.isNotEmpty ? typeArgs.first : null; 168 | if (!isPrimitiveType(firstTypeArg) && !isSkippedType(firstTypeArg)) { 169 | implicitlyOptedTypes.add(firstTypeArg); 170 | final isEnum = firstTypeArg!.element is ClassElement && 171 | (firstTypeArg.element as ClassElement).isEnum; 172 | final mapBody = isEnum 173 | ? _genEnum(param, 174 | type: firstTypeArg, 175 | name: firstTypeArg.getDisplayString(withNullability: false), 176 | explicitType: true) 177 | : _generateDeserialize('item', firstTypeArg); 178 | val = 179 | '''(${valFn('List')})${param.isOptional ? '?' : ''}${isEnum ? '' : '.cast>()'}.map((${isEnum ? 'dynamic ' : ''}item) => $mapBody!).toList()'''; 180 | } else { 181 | final isConverter = isConverterType(firstTypeArg!); 182 | val = 183 | '''(${valFn('List')})${param.isOptional ? '?' : ''}${isConverter ? '' : '.cast<${firstTypeArg.element!.name}>()'}.map((${isConverter ? 'dynamic ' : ''}item) => ${converterWrapper('item', firstTypeArg.element!.name)}!).toList()'''; 184 | } 185 | } else if (isMap) { 186 | // TODO(D10100111001): Handle non primitive types 187 | final typeArgs = (param.type as InterfaceType).typeArguments; 188 | final firstTypeArg = typeArgs.isNotEmpty ? typeArgs.first : null; 189 | final secondTypeArg = typeArgs.isNotEmpty ? typeArgs[1] : null; 190 | if (!isPrimitiveType(firstTypeArg)) 191 | implicitlyOptedTypes.add(firstTypeArg); 192 | if (!isPrimitiveType(secondTypeArg)) 193 | implicitlyOptedTypes.add(secondTypeArg); 194 | val = 195 | '(${valFn('Map')})${param.isOptional ? '?' : ''}${firstTypeArg != null && secondTypeArg != null ? '.cast<${firstTypeArg.element?.name}, ${secondTypeArg.element!.name}>()' : ''}'; 196 | } else if (isParamEnum(param)) { 197 | val = _genEnum(param); 198 | } else if (!isPrimitiveType(param.type) && 199 | !isSkippedType(param.type) && 200 | val == null) { 201 | implicitlyOptedTypes.add(param.type); 202 | val = _generateDeserialize(valFn('Map'), param.type); 203 | } 204 | final useDefaultValue = 205 | (prop.defaultValue != null || param.hasDefaultValue) && 206 | param.isOptional; 207 | return '''$name: ${val ?? valFn()}${useDefaultValue ? ' ?? ${param.defaultValueCode ?? prop.defaultValue.toString()}' : ''}${isList || isMap || param.isOptional || useDefaultValue ? '' : '!'},'''; 208 | } 209 | 210 | String _generateEnumFromMap(DartType type, String name, 211 | JsonEnumProperty enumProp, Map enumValueMap, 212 | {String? compare}) { 213 | final isIndex = enumProp.serializationType == SerializationType.Index; 214 | final value = isIndex 215 | ? 'value!.index' 216 | : "value!.toString().split('.').elementAt(1).toLowerCase()"; 217 | return '''${type.element!.name}.values.cast<${type.element!.name}?>().firstWhere( 218 | (value) => ${_generateMapLookup(enumValueMap, value)} == ${compare != null ? compare : "json['$name']"}${!isIndex ? '.toLowerCase()' : ''}, 219 | orElse: () => null)'''; 220 | } 221 | 222 | String? _generateToMapItem(ParameterElement param) { 223 | final converterProp = getConverterProp(param); 224 | final prop = getProp(param); 225 | if (prop.ignore ?? false) return null; 226 | final name = param.name; 227 | final jsonName = prop.name ?? name; 228 | final converterWrapper = (String val, [String? type]) => 229 | 'mapper.applyDynamicFromInstanceConverter${type != null ? '<$type>' : ''}($val${converterProp != null ? ', $converterProp' : ''})'; 230 | final valFn = () => 'instance.$name'; 231 | var val; 232 | var useTransform = converterProp != null; 233 | 234 | final String Function(ParameterElement, {DartType? type}) _genEnum = 235 | (param, {type}) { 236 | final enumProp = getEnumProp(param); 237 | final enumValueMap = cleanMap(getEnumValueMap(enumProp, 238 | param: param, enumClassEl: type?.element as ClassElement?)); 239 | final normalizedType = type ?? param.type; 240 | return _generateMapLookup(enumValueMap, 241 | '${type != null ? 'item' : valFn()}${param.isOptional ? '?' : ''}${_generateEnumToMap(normalizedType, enumProp)}'); 242 | }; 243 | 244 | if (param.type.isDartCoreList) { 245 | final typeArgs = (param.type as InterfaceType).typeArguments; 246 | final firstTypeArg = typeArgs.isNotEmpty ? typeArgs.first : null; 247 | final isConverter = isConverterType(firstTypeArg); 248 | if (!isPrimitiveType(firstTypeArg)) { 249 | var body = _generateSerialize('item'); 250 | if (!isSkippedType(firstTypeArg)) { 251 | final isEnum = firstTypeArg?.element != null && 252 | firstTypeArg!.element is ClassElement && 253 | (firstTypeArg.element as ClassElement).isEnum; 254 | body = isEnum ? _genEnum(param, type: firstTypeArg) : body; 255 | implicitlyOptedTypes.add(firstTypeArg); 256 | } 257 | val = 258 | '''${valFn()}${param.isOptional ? '?' : ''}.map${firstTypeArg == null || isConverter ? '' : ''}((item) => ${isConverter ? converterWrapper('item') : body}).toList()'''; 259 | } 260 | } else if (param.type.isDartCoreMap) { 261 | // TODO(D10100111001): Handle non primitive types 262 | final typeArgs = (param.type as InterfaceType).typeArguments; 263 | final firstTypeArg = typeArgs.isNotEmpty ? typeArgs.first : null; 264 | final secondTypeArg = typeArgs.isNotEmpty ? typeArgs[1] : null; 265 | if (!isPrimitiveType(firstTypeArg)) 266 | implicitlyOptedTypes.add(firstTypeArg); 267 | if (!isPrimitiveType(secondTypeArg)) 268 | implicitlyOptedTypes.add(secondTypeArg); 269 | } else if (isParamEnum(param)) { 270 | val = _genEnum(param); 271 | useTransform = true; 272 | } else if (!isPrimitiveType(param.type) && 273 | !isSkippedType(param.type) && 274 | val == null) { 275 | implicitlyOptedTypes.add(param.type); 276 | val = _generateSerialize(valFn()); 277 | } 278 | if (val == null) useTransform = true; 279 | final useDefaultValue = prop.defaultValue != null && param.isOptional; 280 | 281 | val = 282 | "${val ?? valFn()}${useDefaultValue ? ' ?? ${param.defaultValueCode ?? prop.defaultValue.toString()}' : ''}"; 283 | return ''''$jsonName': ${useTransform ? converterWrapper(val, param.type.isDynamic ? 'dynamic' : null) : val},'''; 284 | } 285 | 286 | String _generateEnumToMap(DartType type, JsonEnumProperty enumProp) { 287 | return '''${enumProp.serializationType == SerializationType.Index ? '.index' : ".toString().split('.').elementAt(1)"}'''; 288 | } 289 | 290 | String _generateMapLookup(Map map, String val) { 291 | return map.isNotEmpty ? '''(${map.toString()}[${val}] ?? ${val})''' : val; 292 | } 293 | 294 | FieldElement? getMatchingSuperProp(ParameterElement param) { 295 | var superElement = (param.enclosingElement as ConstructorElement) 296 | .enclosingElement 297 | .supertype 298 | ?.element; 299 | while (superElement != null) { 300 | final field = 301 | superElement.fields.firstWhereOrNull((f) => f.name == param.name); 302 | if (field != null) 303 | return field; 304 | else 305 | superElement = superElement.supertype?.element; 306 | } 307 | return null; 308 | } 309 | 310 | DartObject? getPropObject(ParameterElement param, Type annotationType, 311 | {bool getBase = true}) { 312 | final propChecker = TypeChecker.fromRuntime(annotationType); 313 | final field = param.isInitializingFormal 314 | ? (param as FieldFormalParameterElement).field 315 | : getMatchingSuperProp(param); 316 | final jsonPropType = propChecker.firstAnnotationOf(param) ?? 317 | (field != null ? propChecker.firstAnnotationOf(field) : null); 318 | DartObject? obj = jsonPropType; 319 | if (getBase) { 320 | while (true) { 321 | final newObj = obj?.getField('(super)'); 322 | if (newObj != null) 323 | obj = newObj; 324 | else 325 | break; 326 | } 327 | } 328 | return obj; 329 | } 330 | 331 | JsonProperty getProp(ParameterElement param) { 332 | final fieldMap = getPropObject(param, JsonProperty); 333 | final jsonProp = JsonProperty( 334 | ignore: fieldMap?.getField('ignore')?.toBoolValue() ?? false, 335 | name: fieldMap?.getField('name')?.toStringValue(), 336 | defaultValue: 337 | ConstantReader(fieldMap?.getField('defaultValue')).literalValue, 338 | ); 339 | return jsonProp; 340 | } 341 | 342 | String? getConverterProp(ParameterElement param, [DartObject? obj]) { 343 | final obj = getPropObject(param, JsonConverter, getBase: false); 344 | if (obj == null) return null; 345 | final element = obj.type?.element; 346 | if (element == null || element is! ClassElement) return null; 347 | usedElements.add(element); 348 | final List? params = 349 | element.unnamedConstructor?.parameters; 350 | if (params == null) return null; 351 | 352 | final getValue = (ParameterElement p) => obj.getField(p.name); 353 | final valueFn = 354 | (ParameterElement p) => ConstantReader(getValue(p)).literalValue; 355 | final positionalParams = params 356 | .where((p) => p.isPositional && getValue(p) != null) 357 | .map((p) => valueFn(p)) 358 | .toList(); 359 | final namedParams = params 360 | .where((p) => p.isNamed && getValue(p) != null) 361 | .map((p) => '${p.name}: ${valueFn(p)}') 362 | .toList(); 363 | return '${element.name}(${[ 364 | ...positionalParams, 365 | ...namedParams 366 | ].join(', ')})'; 367 | } 368 | 369 | JsonEnumProperty getEnumProp(ParameterElement param) { 370 | final fieldMap = getPropObject(param, JsonEnumProperty); 371 | final jsonProp = JsonEnumProperty( 372 | serializationType: fieldMap != null 373 | ? SerializationType.values.firstWhere((val) => 374 | fieldMap 375 | .getField('serializationType') 376 | ?.getField(Utils.enumToString(val)) != 377 | null) 378 | : SerializationType.Value, 379 | ); 380 | return jsonProp; 381 | } 382 | 383 | Map getEnumValueMap( 384 | JsonEnumProperty enumProp, { 385 | ParameterElement? param, 386 | ClassElement? enumClassEl, 387 | }) { 388 | final propChecker = TypeChecker.fromRuntime(EnumValue); 389 | final enumElement = enumClassEl ?? (param!.type.element as ClassElement?)!; 390 | final enumFields = 391 | enumElement.fields.where((e) => e.isEnumConstant).toList(); 392 | final enumValProps = enumFields 393 | .map((field) => 394 | propChecker.firstAnnotationOf(field, throwOnUnresolved: false)) 395 | .toList(); 396 | return enumFields.asMap().entries.fold({}, 397 | (map, fieldEntry) { 398 | final displayName = fieldEntry.value.name; 399 | final key = enumProp.serializationType == SerializationType.Index 400 | ? ConstantReader(enumElement 401 | .getField(displayName)! 402 | .computeConstantValue()! 403 | .getField(displayName)) 404 | .intValue 405 | : displayName; 406 | final valField = enumValProps[fieldEntry.key]?.getField('value'); 407 | final value = 408 | valField != null ? ConstantReader(valField).literalValue : null; 409 | map[key] = value ?? key; 410 | return map; 411 | }); 412 | } 413 | 414 | Map cleanMap(Map valueMap) { 415 | return valueMap.entries.fold({}, (map, entry) { 416 | if (entry.key != entry.value) map[entry.key] = entry.value; 417 | return map; 418 | }); 419 | } 420 | 421 | String _generateSerialize(String val) { 422 | return 'mapper.serializeToMap($val)'; 423 | } 424 | 425 | String _generateDeserialize(String val, DartType type) { 426 | return 'mapper.deserialize<${type.getDisplayString(withNullability: false)}>($val)'; 427 | } 428 | 429 | bool isPrimitiveType(DartType? type) { 430 | return type != null && 431 | (type.isDartCoreBool || 432 | type.isDartCoreDouble || 433 | type.isDartCoreInt || 434 | type.isDartCoreNum || 435 | type.isDartCoreString); 436 | } 437 | 438 | bool isConverterType(DartType? type) => 439 | type != null && converterTypes.contains(type.element!.name); 440 | 441 | bool isSkippedType(DartType? type) { 442 | return type != null && (isConverterType(type) || type.isDynamic); 443 | } 444 | 445 | bool isParamFieldFormal(ParameterElement param) { 446 | return param.isInitializingFormal; 447 | } 448 | 449 | bool isParamEnum(ParameterElement param) { 450 | return param.type.element is ClassElement && 451 | (param.type.element as ClassElement).isEnum; 452 | } 453 | 454 | String _generateInit( 455 | List registrationElements, 456 | List listCastElements, 457 | List converterClassElements) { 458 | return ''' 459 | void init() { 460 | ${registrationElements.map(_generateRegistration).join('\n ')} 461 | 462 | ${converterClassElements.map(_generateConverter).join('\n ')} 463 | 464 | ${listCastElements.map(_generateListCast).join('\n ')} 465 | } 466 | '''; 467 | } 468 | 469 | String _generateListCast(ClassElement? element) { 470 | return '''JsonMapper.registerListCast((value) => value?.cast<${element!.name}>().toList());'''; 471 | } 472 | 473 | String _generateConverter(ClassElement element) { 474 | return '''JsonMapper.registerConverter(${element.name}());'''; 475 | } 476 | 477 | String _generateRegistration(ClassElement? element) { 478 | return '''JsonMapper.register(_${element!.name.toLowerCase()}Mapper);'''; 479 | } 480 | 481 | String _generateHeader(List elements) { 482 | return [ 483 | '''// GENERATED CODE - DO NOT MODIFY BY HAND''', 484 | '''// Generated and consumed by 'simple_json' ''', 485 | '', 486 | '''import 'package:simple_json_mapper/simple_json_mapper.dart';''', 487 | Utils.dedupe(elements.map(_generateImport).toList()).join('\n') 488 | ].join('\n'); 489 | } 490 | 491 | String _generateImport(Element? element) { 492 | return '''import '${element!.library!.identifier}';'''; 493 | } 494 | 495 | // T toObjectOfType(DartObject dartObject, ParameterizedType type) { 496 | // type.con 497 | // return 498 | // } 499 | 500 | } 501 | -------------------------------------------------------------------------------- /simple_json/lib/src/utils.dart: -------------------------------------------------------------------------------- 1 | class Utils { 2 | static List dedupe(List items) { 3 | return [...Set()..addAll(items)]; 4 | } 5 | 6 | static String enumToString(T enumVal) { 7 | return enumVal.toString().split('.')[1]; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /simple_json/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | _fe_analyzer_shared: 5 | dependency: transitive 6 | description: 7 | name: _fe_analyzer_shared 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "25.0.0" 11 | analyzer: 12 | dependency: "direct main" 13 | description: 14 | name: analyzer 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "2.2.0" 18 | args: 19 | dependency: transitive 20 | description: 21 | name: args 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "2.0.0" 25 | async: 26 | dependency: transitive 27 | description: 28 | name: async 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "2.5.0" 32 | boolean_selector: 33 | dependency: transitive 34 | description: 35 | name: boolean_selector 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "2.1.0" 39 | build: 40 | dependency: "direct main" 41 | description: 42 | name: build 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "2.1.0" 46 | build_config: 47 | dependency: transitive 48 | description: 49 | name: build_config 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "1.0.0" 53 | build_daemon: 54 | dependency: transitive 55 | description: 56 | name: build_daemon 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "3.0.0" 60 | build_resolvers: 61 | dependency: "direct main" 62 | description: 63 | name: build_resolvers 64 | url: "https://pub.dartlang.org" 65 | source: hosted 66 | version: "2.0.4" 67 | build_runner: 68 | dependency: "direct dev" 69 | description: 70 | name: build_runner 71 | url: "https://pub.dartlang.org" 72 | source: hosted 73 | version: "2.1.2" 74 | build_runner_core: 75 | dependency: transitive 76 | description: 77 | name: build_runner_core 78 | url: "https://pub.dartlang.org" 79 | source: hosted 80 | version: "7.1.0" 81 | built_collection: 82 | dependency: transitive 83 | description: 84 | name: built_collection 85 | url: "https://pub.dartlang.org" 86 | source: hosted 87 | version: "5.0.0" 88 | built_value: 89 | dependency: transitive 90 | description: 91 | name: built_value 92 | url: "https://pub.dartlang.org" 93 | source: hosted 94 | version: "8.0.3" 95 | charcode: 96 | dependency: transitive 97 | description: 98 | name: charcode 99 | url: "https://pub.dartlang.org" 100 | source: hosted 101 | version: "1.2.0" 102 | checked_yaml: 103 | dependency: transitive 104 | description: 105 | name: checked_yaml 106 | url: "https://pub.dartlang.org" 107 | source: hosted 108 | version: "2.0.1" 109 | cli_util: 110 | dependency: transitive 111 | description: 112 | name: cli_util 113 | url: "https://pub.dartlang.org" 114 | source: hosted 115 | version: "0.3.0" 116 | code_builder: 117 | dependency: transitive 118 | description: 119 | name: code_builder 120 | url: "https://pub.dartlang.org" 121 | source: hosted 122 | version: "4.1.0" 123 | collection: 124 | dependency: "direct main" 125 | description: 126 | name: collection 127 | url: "https://pub.dartlang.org" 128 | source: hosted 129 | version: "1.15.0" 130 | convert: 131 | dependency: transitive 132 | description: 133 | name: convert 134 | url: "https://pub.dartlang.org" 135 | source: hosted 136 | version: "3.0.0" 137 | coverage: 138 | dependency: transitive 139 | description: 140 | name: coverage 141 | url: "https://pub.dartlang.org" 142 | source: hosted 143 | version: "1.0.2" 144 | crypto: 145 | dependency: transitive 146 | description: 147 | name: crypto 148 | url: "https://pub.dartlang.org" 149 | source: hosted 150 | version: "3.0.0" 151 | dart_style: 152 | dependency: transitive 153 | description: 154 | name: dart_style 155 | url: "https://pub.dartlang.org" 156 | source: hosted 157 | version: "2.0.3" 158 | file: 159 | dependency: transitive 160 | description: 161 | name: file 162 | url: "https://pub.dartlang.org" 163 | source: hosted 164 | version: "6.1.0" 165 | fixnum: 166 | dependency: transitive 167 | description: 168 | name: fixnum 169 | url: "https://pub.dartlang.org" 170 | source: hosted 171 | version: "1.0.0" 172 | frontend_server_client: 173 | dependency: transitive 174 | description: 175 | name: frontend_server_client 176 | url: "https://pub.dartlang.org" 177 | source: hosted 178 | version: "2.1.2" 179 | glob: 180 | dependency: "direct main" 181 | description: 182 | name: glob 183 | url: "https://pub.dartlang.org" 184 | source: hosted 185 | version: "2.0.1" 186 | graphs: 187 | dependency: transitive 188 | description: 189 | name: graphs 190 | url: "https://pub.dartlang.org" 191 | source: hosted 192 | version: "2.0.0" 193 | http_multi_server: 194 | dependency: transitive 195 | description: 196 | name: http_multi_server 197 | url: "https://pub.dartlang.org" 198 | source: hosted 199 | version: "3.0.0" 200 | http_parser: 201 | dependency: transitive 202 | description: 203 | name: http_parser 204 | url: "https://pub.dartlang.org" 205 | source: hosted 206 | version: "4.0.0" 207 | io: 208 | dependency: transitive 209 | description: 210 | name: io 211 | url: "https://pub.dartlang.org" 212 | source: hosted 213 | version: "1.0.0" 214 | js: 215 | dependency: transitive 216 | description: 217 | name: js 218 | url: "https://pub.dartlang.org" 219 | source: hosted 220 | version: "0.6.3" 221 | json_annotation: 222 | dependency: transitive 223 | description: 224 | name: json_annotation 225 | url: "https://pub.dartlang.org" 226 | source: hosted 227 | version: "4.0.1" 228 | logging: 229 | dependency: transitive 230 | description: 231 | name: logging 232 | url: "https://pub.dartlang.org" 233 | source: hosted 234 | version: "1.0.0" 235 | matcher: 236 | dependency: transitive 237 | description: 238 | name: matcher 239 | url: "https://pub.dartlang.org" 240 | source: hosted 241 | version: "0.12.11" 242 | meta: 243 | dependency: transitive 244 | description: 245 | name: meta 246 | url: "https://pub.dartlang.org" 247 | source: hosted 248 | version: "1.7.0" 249 | mime: 250 | dependency: transitive 251 | description: 252 | name: mime 253 | url: "https://pub.dartlang.org" 254 | source: hosted 255 | version: "1.0.0" 256 | node_preamble: 257 | dependency: transitive 258 | description: 259 | name: node_preamble 260 | url: "https://pub.dartlang.org" 261 | source: hosted 262 | version: "2.0.0" 263 | package_config: 264 | dependency: transitive 265 | description: 266 | name: package_config 267 | url: "https://pub.dartlang.org" 268 | source: hosted 269 | version: "2.0.0" 270 | path: 271 | dependency: "direct main" 272 | description: 273 | name: path 274 | url: "https://pub.dartlang.org" 275 | source: hosted 276 | version: "1.8.0" 277 | pedantic: 278 | dependency: transitive 279 | description: 280 | name: pedantic 281 | url: "https://pub.dartlang.org" 282 | source: hosted 283 | version: "1.11.0" 284 | pool: 285 | dependency: transitive 286 | description: 287 | name: pool 288 | url: "https://pub.dartlang.org" 289 | source: hosted 290 | version: "1.5.0" 291 | pub_semver: 292 | dependency: transitive 293 | description: 294 | name: pub_semver 295 | url: "https://pub.dartlang.org" 296 | source: hosted 297 | version: "2.0.0" 298 | pubspec_parse: 299 | dependency: transitive 300 | description: 301 | name: pubspec_parse 302 | url: "https://pub.dartlang.org" 303 | source: hosted 304 | version: "1.0.0" 305 | shelf: 306 | dependency: transitive 307 | description: 308 | name: shelf 309 | url: "https://pub.dartlang.org" 310 | source: hosted 311 | version: "1.1.0" 312 | shelf_packages_handler: 313 | dependency: transitive 314 | description: 315 | name: shelf_packages_handler 316 | url: "https://pub.dartlang.org" 317 | source: hosted 318 | version: "3.0.0" 319 | shelf_static: 320 | dependency: transitive 321 | description: 322 | name: shelf_static 323 | url: "https://pub.dartlang.org" 324 | source: hosted 325 | version: "1.0.0" 326 | shelf_web_socket: 327 | dependency: transitive 328 | description: 329 | name: shelf_web_socket 330 | url: "https://pub.dartlang.org" 331 | source: hosted 332 | version: "1.0.1" 333 | simple_json_mapper: 334 | dependency: "direct main" 335 | description: 336 | name: simple_json_mapper 337 | url: "https://pub.dartlang.org" 338 | source: hosted 339 | version: "2.1.0" 340 | source_gen: 341 | dependency: "direct main" 342 | description: 343 | name: source_gen 344 | url: "https://pub.dartlang.org" 345 | source: hosted 346 | version: "1.1.0" 347 | source_map_stack_trace: 348 | dependency: transitive 349 | description: 350 | name: source_map_stack_trace 351 | url: "https://pub.dartlang.org" 352 | source: hosted 353 | version: "2.1.0" 354 | source_maps: 355 | dependency: transitive 356 | description: 357 | name: source_maps 358 | url: "https://pub.dartlang.org" 359 | source: hosted 360 | version: "0.10.10" 361 | source_span: 362 | dependency: transitive 363 | description: 364 | name: source_span 365 | url: "https://pub.dartlang.org" 366 | source: hosted 367 | version: "1.8.1" 368 | stack_trace: 369 | dependency: transitive 370 | description: 371 | name: stack_trace 372 | url: "https://pub.dartlang.org" 373 | source: hosted 374 | version: "1.10.0" 375 | stream_channel: 376 | dependency: transitive 377 | description: 378 | name: stream_channel 379 | url: "https://pub.dartlang.org" 380 | source: hosted 381 | version: "2.1.0" 382 | stream_transform: 383 | dependency: transitive 384 | description: 385 | name: stream_transform 386 | url: "https://pub.dartlang.org" 387 | source: hosted 388 | version: "2.0.0" 389 | string_scanner: 390 | dependency: transitive 391 | description: 392 | name: string_scanner 393 | url: "https://pub.dartlang.org" 394 | source: hosted 395 | version: "1.1.0" 396 | term_glyph: 397 | dependency: transitive 398 | description: 399 | name: term_glyph 400 | url: "https://pub.dartlang.org" 401 | source: hosted 402 | version: "1.2.0" 403 | test: 404 | dependency: "direct dev" 405 | description: 406 | name: test 407 | url: "https://pub.dartlang.org" 408 | source: hosted 409 | version: "1.17.12" 410 | test_api: 411 | dependency: transitive 412 | description: 413 | name: test_api 414 | url: "https://pub.dartlang.org" 415 | source: hosted 416 | version: "0.4.3" 417 | test_core: 418 | dependency: transitive 419 | description: 420 | name: test_core 421 | url: "https://pub.dartlang.org" 422 | source: hosted 423 | version: "0.4.2" 424 | timing: 425 | dependency: transitive 426 | description: 427 | name: timing 428 | url: "https://pub.dartlang.org" 429 | source: hosted 430 | version: "1.0.0" 431 | typed_data: 432 | dependency: transitive 433 | description: 434 | name: typed_data 435 | url: "https://pub.dartlang.org" 436 | source: hosted 437 | version: "1.3.0" 438 | vm_service: 439 | dependency: transitive 440 | description: 441 | name: vm_service 442 | url: "https://pub.dartlang.org" 443 | source: hosted 444 | version: "6.1.0+1" 445 | watcher: 446 | dependency: transitive 447 | description: 448 | name: watcher 449 | url: "https://pub.dartlang.org" 450 | source: hosted 451 | version: "1.0.0" 452 | web_socket_channel: 453 | dependency: transitive 454 | description: 455 | name: web_socket_channel 456 | url: "https://pub.dartlang.org" 457 | source: hosted 458 | version: "2.0.0" 459 | webkit_inspection_protocol: 460 | dependency: transitive 461 | description: 462 | name: webkit_inspection_protocol 463 | url: "https://pub.dartlang.org" 464 | source: hosted 465 | version: "1.0.0" 466 | yaml: 467 | dependency: transitive 468 | description: 469 | name: yaml 470 | url: "https://pub.dartlang.org" 471 | source: hosted 472 | version: "3.1.0" 473 | sdks: 474 | dart: ">=2.12.0 <3.0.0" 475 | -------------------------------------------------------------------------------- /simple_json/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: simple_json 2 | description: Simple way to dynamically convert from and to JSON using build-time generators given a type. 3 | version: 2.2.0 4 | homepage: https://github.com/FlutterDevTools/simple_json/tree/master/simple_json 5 | 6 | environment: 7 | sdk: '>=2.12.0 <3.0.0' 8 | 9 | dependencies: 10 | simple_json_mapper: ^2.1.0 11 | build_resolvers: ^2.0.4 12 | analyzer: ^2.2.0 13 | build: ^2.1.0 14 | source_gen: ^1.1.0 15 | path: ^1.8.0 16 | glob: ^2.0.1 17 | collection: ^1.15.0 18 | 19 | dev_dependencies: 20 | test: ^1.17.12 21 | build_runner: ^2.1.2 22 | -------------------------------------------------------------------------------- /simple_json/test/simple_json_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:test/test.dart'; 2 | 3 | 4 | void main() { 5 | // test('adds one to input values', () { 6 | // final calculator = Calculator(); 7 | // expect(calculator.addOne(2), 3); 8 | // expect(calculator.addOne(-7), -6); 9 | // expect(calculator.addOne(0), 1); 10 | // expect(() => calculator.addOne(null), throwsNoSuchMethodError); 11 | // }); 12 | } 13 | -------------------------------------------------------------------------------- /simple_json_mapper/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | .dart_tool/ 26 | .flutter-plugins 27 | .flutter-plugins-dependencies 28 | .packages 29 | .pub-cache/ 30 | .pub/ 31 | build/ 32 | 33 | # Android related 34 | **/android/**/gradle-wrapper.jar 35 | **/android/.gradle 36 | **/android/captures/ 37 | **/android/gradlew 38 | **/android/gradlew.bat 39 | **/android/local.properties 40 | **/android/**/GeneratedPluginRegistrant.java 41 | 42 | # iOS/XCode related 43 | **/ios/**/*.mode1v3 44 | **/ios/**/*.mode2v3 45 | **/ios/**/*.moved-aside 46 | **/ios/**/*.pbxuser 47 | **/ios/**/*.perspectivev3 48 | **/ios/**/*sync/ 49 | **/ios/**/.sconsign.dblite 50 | **/ios/**/.tags* 51 | **/ios/**/.vagrant/ 52 | **/ios/**/DerivedData/ 53 | **/ios/**/Icon? 54 | **/ios/**/Pods/ 55 | **/ios/**/.symlinks/ 56 | **/ios/**/profile 57 | **/ios/**/xcuserdata 58 | **/ios/.generated/ 59 | **/ios/Flutter/App.framework 60 | **/ios/Flutter/Flutter.framework 61 | **/ios/Flutter/Flutter.podspec 62 | **/ios/Flutter/Generated.xcconfig 63 | **/ios/Flutter/app.flx 64 | **/ios/Flutter/app.zip 65 | **/ios/Flutter/flutter_assets/ 66 | **/ios/Flutter/flutter_export_environment.sh 67 | **/ios/ServiceDefinitions.json 68 | **/ios/Runner/GeneratedPluginRegistrant.* 69 | 70 | # Exceptions to above rules. 71 | !**/ios/**/default.mode1v3 72 | !**/ios/**/default.mode2v3 73 | !**/ios/**/default.pbxuser 74 | !**/ios/**/default.perspectivev3 75 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 76 | -------------------------------------------------------------------------------- /simple_json_mapper/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 248d746575b713da74144750527356a1c0095546 8 | channel: master 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /simple_json_mapper/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Dart Example", 9 | "program": "example/lib/main.dart", 10 | "request": "launch", 11 | "type": "dart" 12 | } 13 | ] 14 | } -------------------------------------------------------------------------------- /simple_json_mapper/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 2.2.0 - 09/07/2021 2 | 3 | - Update dependencies. 4 | 5 | ## 2.1.0 - 03/21/2021 6 | 7 | - Fix typings and bugs. 8 | 9 | ## 2.0.2 - 03/20/2021 10 | 11 | - Fix list case typing. 12 | 13 | ## 2.0.1 - 03/20/2021 14 | 15 | - Update annotation model requirements. 16 | 17 | ## 2.0.0 - 03/20/2021 18 | 19 | - Null safety, tests, and cleanup. 20 | 21 | ## 1.1.3 - 01/08/2021 22 | 23 | - Support de-serialization using `typeName`. 24 | 25 | ## 1.1.2 - 08/31/2020 26 | 27 | - Support `Duration` class serialization. 28 | 29 | ## 1.1.1 - 07/09/2020 30 | 31 | - Add `verbose` option for logging. 32 | 33 | ## 1.1.0 - 07/09/2020 34 | 35 | - Fix bug with list serialization. 36 | 37 | ## 1.0.2 - 07/02/2020 38 | 39 | - Handle `null` values on both serialization and de-serialization. 40 | 41 | ## 1.0.1 - 07/01/2020 42 | 43 | - Update the `serialize` method API by removing the generic type parameter from `JsonMapper`. 44 | 45 | ## 1.0.0 - 07/01/2020 46 | 47 | - Update the `serialize` method API by removing the generic type parameter. The runtimeType is used to match the correct mapper. 48 | 49 | ## 0.4.0 - 07/01/2020 50 | 51 | - Support serializing and deserializing of lists. `deserializeList` method was removed. Use the normal `deserialize` (where T is a type of `List`) method instead. 52 | 53 | ## 0.3.0 - 07/01/2020 54 | 55 | - Support serializing and deserializing of lists. Deserializing requires the actual item type so a new `deserializeList` method was added. 56 | - Cleanup of API and internal usages. 57 | 58 | ## 0.2.2 - 06/24/2020 59 | 60 | - Keep version in sync with `simple_json`. 61 | 62 | ## 0.2.1 - 06/24/2020 63 | 64 | - Update README. 65 | 66 | ## 0.2.0 - 06/24/2020 67 | 68 | - Add support for custom json mapper and converters. 69 | 70 | ## 0.1.6 - 06/15/2020 71 | 72 | - Fix unintentionally hidden annotations. 73 | 74 | ## 0.1.5 - 06/15/2020 75 | 76 | - Add enum annotations. `JsonEnumProperty` (with alias `JEnumProp`) and `EnumValue`. 77 | 78 | ## 0.1.4 - 06/15/2020 79 | 80 | - Fix bug `JObj` const constructor. 81 | 82 | ## 0.1.3 - 06/15/2020 83 | 84 | - Fix bug with not revealing the new annotations. 85 | 86 | ## 0.1.2 - 06/15/2020 87 | 88 | - Add `JObj` as an alias to `JsonObject` and `JsonProperty` (with `JProp` alias) for controlling class property options. 89 | 90 | ## 0.1.1 - 06/15/2020 91 | 92 | - Add example project. 93 | 94 | ## 0.1.0 - 06/15/2020 95 | 96 | - Initial release. 97 | -------------------------------------------------------------------------------- /simple_json_mapper/LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2020, Flutter Dev Tools 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /simple_json_mapper/README.md: -------------------------------------------------------------------------------- 1 | # simple_json_mapper 2 | Classes and helper functions that support JSON code generation and serialization via the `simple_json` package. -------------------------------------------------------------------------------- /simple_json_mapper/example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:simple_json_mapper/simple_json_mapper.dart'; 2 | 3 | void main() { 4 | // The registration is normally done automatically by the generator (simple_json package) 5 | JsonMapper.register(JsonObjectMapper( 6 | (mapper, map) => Test( 7 | name: map['name'] as String, 8 | ), 9 | (mapper, instance) => { 10 | 'name': instance.name, 11 | }, 12 | )); 13 | 14 | final jsonStr = JsonMapper.serialize(Test(name: 'Blah')); 15 | print('Serialized JSON:'); 16 | print(jsonStr); 17 | print('\nDeserialized and re-serialized JSON:'); 18 | final obj = JsonMapper.deserialize(jsonStr); 19 | print(obj != null ? JsonMapper.serialize(obj) : obj); 20 | } 21 | 22 | @JsonObject() 23 | class Test { 24 | const Test({required this.name}); 25 | final String name; 26 | } 27 | -------------------------------------------------------------------------------- /simple_json_mapper/example/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | simple_json_mapper: 5 | dependency: "direct main" 6 | description: 7 | path: ".." 8 | relative: true 9 | source: path 10 | version: "2.2.0" 11 | sdks: 12 | dart: ">=2.12.0 <3.0.0" 13 | -------------------------------------------------------------------------------- /simple_json_mapper/example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: simple_json_mapper_example 2 | description: simple_json_mapper example project 3 | version: 0.1.0 4 | homepage: https://github.com/FlutterDevTools/simple_json 5 | publish_to: none 6 | 7 | environment: 8 | sdk: ">=2.12.0 <3.0.0" 9 | 10 | dependencies: 11 | simple_json_mapper: 12 | path: ../ 13 | -------------------------------------------------------------------------------- /simple_json_mapper/lib/simple_json_mapper.dart: -------------------------------------------------------------------------------- 1 | library simple_json_mapper; 2 | 3 | export 'src/annotations.dart'; 4 | export 'src/json_mapper.dart'; 5 | export 'src/json_converter.dart'; 6 | -------------------------------------------------------------------------------- /simple_json_mapper/lib/src/annotations.dart: -------------------------------------------------------------------------------- 1 | class JObj extends JsonObject { 2 | const JObj() : super(); 3 | } 4 | 5 | class JsonObject { 6 | const JsonObject(); 7 | } 8 | 9 | class JProp extends JsonProperty { 10 | const JProp({ 11 | bool? ignore, 12 | String? name, 13 | dynamic? defaultValue, 14 | }) : super( 15 | ignore: ignore, 16 | name: name, 17 | defaultValue: defaultValue, 18 | ); 19 | } 20 | 21 | class JsonProperty { 22 | const JsonProperty({ 23 | this.ignore, 24 | this.name, 25 | this.defaultValue, 26 | }); 27 | final bool? ignore; 28 | final String? name; 29 | final dynamic? defaultValue; 30 | } 31 | 32 | enum SerializationType { 33 | Value, 34 | Index, 35 | } 36 | 37 | class JsonEnumProperty { 38 | const JsonEnumProperty({this.serializationType = SerializationType.Value}); 39 | final SerializationType serializationType; 40 | } 41 | 42 | class JEnumProp extends JsonEnumProperty { 43 | const JEnumProp( 44 | {SerializationType serializationType = SerializationType.Value}) 45 | : super(serializationType: serializationType); 46 | } 47 | 48 | class EnumValue { 49 | const EnumValue({this.value}); 50 | final dynamic value; 51 | } 52 | -------------------------------------------------------------------------------- /simple_json_mapper/lib/src/converters/datetime.dart: -------------------------------------------------------------------------------- 1 | import 'package:simple_json_mapper/src/json_converter.dart'; 2 | 3 | class DefaultISO8601DateConverter extends JsonConverter { 4 | const DefaultISO8601DateConverter(); 5 | @override 6 | DateTime? fromJson(String? value) { 7 | return value != null ? DateTime.parse(value) : null; 8 | } 9 | 10 | @override 11 | String? toJson(DateTime? value) { 12 | return value?.toIso8601String(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /simple_json_mapper/lib/src/converters/duration.dart: -------------------------------------------------------------------------------- 1 | import 'package:simple_json_mapper/src/json_converter.dart'; 2 | 3 | class DefaultDurationConverter extends JsonConverter { 4 | const DefaultDurationConverter(); 5 | @override 6 | Duration? fromJson(String? value) { 7 | if (value == null) return null; 8 | final durationParts = value.split(':'); 9 | return Duration( 10 | hours: 11 | (durationParts.length >= 1 ? int.tryParse(durationParts[0]) : null) ?? 12 | 0, 13 | minutes: 14 | (durationParts.length >= 2 ? int.tryParse(durationParts[1]) : null) ?? 15 | 0, 16 | seconds: 17 | (durationParts.length >= 3 ? int.tryParse(durationParts[2]) : null) ?? 18 | 0, 19 | ); 20 | } 21 | 22 | String? format(Duration? d) => 23 | d != null ? d.toString().split('.').first.padLeft(8, "0") : null; 24 | 25 | @override 26 | String? toJson(Duration? value) { 27 | return format(value)?.toString(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /simple_json_mapper/lib/src/json_converter.dart: -------------------------------------------------------------------------------- 1 | abstract class JsonConverter { 2 | const JsonConverter(); 3 | 4 | factory JsonConverter.fromFunction( 5 | {required TTo Function(TFrom value) fromJson, 6 | required TFrom Function(TTo value) toJson}) { 7 | return JsonObjectConverter( 8 | fromJsonFn: fromJson, toJsonFn: toJson); 9 | } 10 | 11 | String get toType => TTo.toString(); 12 | String get fromType => TFrom.toString(); 13 | 14 | TTo fromJson(TFrom value); 15 | TFrom toJson(TTo value); 16 | } 17 | 18 | class JsonObjectConverter extends JsonConverter { 19 | const JsonObjectConverter({required this.fromJsonFn, required this.toJsonFn}); 20 | final TTo Function(TFrom value) fromJsonFn; 21 | final TFrom Function(TTo value) toJsonFn; 22 | 23 | @override 24 | TTo fromJson(TFrom value) { 25 | return fromJsonFn(value); 26 | } 27 | 28 | @override 29 | TFrom toJson(TTo value) { 30 | return toJsonFn(value); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /simple_json_mapper/lib/src/json_mapper.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:simple_json_mapper/simple_json_mapper.dart'; 4 | import 'package:simple_json_mapper/src/converters/duration.dart'; 5 | 6 | import 'converters/datetime.dart'; 7 | import 'json_converter.dart'; 8 | 9 | class JsonObjectMapper { 10 | const JsonObjectMapper(this.fromJsonMap, this.toJsonMap); 11 | 12 | final T Function(CustomJsonMapper mapper, Map map) 13 | fromJsonMap; 14 | final Map Function(CustomJsonMapper mapper, T item) 15 | toJsonMap; 16 | } 17 | 18 | class JsonMapper { 19 | static bool verbose = false; 20 | static CustomJsonMapper _instance = CustomJsonMapper(verbose: verbose); 21 | static bool isMapperRegistered() => _instance.isMapperRegistered(); 22 | static bool isConverterRegistered() => 23 | _instance.isConverterRegistered(); 24 | 25 | static void register(JsonObjectMapper mapper) => 26 | _instance.register(mapper); 27 | 28 | static void registerListCast(ListCastFunction castFn) => 29 | _instance.registerListCast(castFn); 30 | 31 | static String? serialize(T item) => _instance.serialize(item); 32 | 33 | static Map? serializeToMap(T? item) => 34 | _instance.serializeToMap(item); 35 | 36 | static T? deserialize(dynamic jsonVal, [String? typeName]) => 37 | _instance.deserialize(jsonVal, typeName); 38 | 39 | static T? deserializeFromMap(dynamic jsonVal, [String? typeName]) => 40 | _instance.deserializeFromMap(jsonVal, typeName); 41 | 42 | static void registerConverter( 43 | JsonConverter transformer) => 44 | _instance.registerConverter(transformer); 45 | } 46 | 47 | typedef ListCastFunction = List? Function(List? list); 48 | 49 | class CustomJsonMapper { 50 | CustomJsonMapper({this.verbose = false, List? converters}) { 51 | if (converters != null) 52 | _toTypeConverterMap 53 | .addAll(converters.fold({}, (map, converter) { 54 | map[converter.toType] = converter; 55 | return map; 56 | })); 57 | } 58 | 59 | final bool verbose; 60 | 61 | static final _mapper = >{}; 62 | static final _listCasts = {}; 63 | 64 | final _toTypeConverterMap = { 65 | (DateTime).toString(): const DefaultISO8601DateConverter(), 66 | (Duration).toString(): const DefaultDurationConverter(), 67 | }; 68 | 69 | bool isMapperRegistered() { 70 | return _isMapperRegisteredByType(T.toString()); 71 | } 72 | 73 | bool _isMapperRegisteredByType(String type) { 74 | return _mapper.containsKey(type); 75 | } 76 | 77 | bool isConverterRegistered() { 78 | return _isConverterRegisteredByType(T.toString()); 79 | } 80 | 81 | bool _isConverterRegisteredByType(String toType) { 82 | return _toTypeConverterMap.containsKey(toType); 83 | } 84 | 85 | void register(JsonObjectMapper mapper) { 86 | _mapper[T.toString()] = mapper; 87 | } 88 | 89 | void registerListCast(ListCastFunction castFn) { 90 | _listCasts[_typeOf>()] = castFn; 91 | } 92 | 93 | String _typeOf() { 94 | return T.toString(); 95 | } 96 | 97 | String? serialize(T? item) { 98 | if (item == null) return null; 99 | final typeName = item.runtimeType.toString(); 100 | if (verbose) print(typeName); 101 | return json.encode(_isListWithType(typeName) 102 | ? (item as List) 103 | .map((i) => _serializeToMapWithType(typeName, i)) 104 | .toList() 105 | : serializeToMap(item)); 106 | } 107 | 108 | Map? serializeToMap(T? item) { 109 | if (item == null) return null; 110 | final typeName = item.runtimeType.toString(); 111 | return _serializeToMapWithType(typeName, item); 112 | } 113 | 114 | Map? _serializeToMapWithType(String typeName, T? item) { 115 | if (item == null) return null; 116 | final typeMap = _getTypeMapWithType(typeName) as dynamic; 117 | if (verbose) print(typeMap); 118 | return typeMap?.toJsonMap(this, item); 119 | } 120 | 121 | T? deserialize(dynamic jsonVal, [String? typeName]) { 122 | if (jsonVal == null) return null; 123 | final decodedJson = jsonVal is String ? json.decode(jsonVal) : jsonVal; 124 | final isList = _isList(typeName); 125 | assert(!isList || (isList && decodedJson is List)); 126 | if (isList) { 127 | final listCastFn = _listCasts[typeName ?? T.toString()]; 128 | assert(listCastFn != null); 129 | final deserializedList = (decodedJson as List) 130 | .map((json) => 131 | _deserializeFromMapWithType(typeName ?? T.toString(), json)) 132 | .toList(); 133 | return listCastFn != null ? listCastFn(deserializedList) as T : null; 134 | } 135 | 136 | return deserializeFromMap(decodedJson, typeName); 137 | } 138 | 139 | T? deserializeFromMap(dynamic jsonVal, [String? typeName]) { 140 | return _deserializeFromMapWithType(typeName ?? T.toString(), jsonVal) as T?; 141 | } 142 | 143 | T? _deserializeFromMapWithType(String typeName, dynamic jsonVal) { 144 | final typeMap = _getTypeMapWithType(typeName); 145 | return jsonVal != null ? typeMap?.fromJsonMap(this, jsonVal) : null; 146 | } 147 | 148 | static const _ListNameTypeMarker = 'List<'; 149 | static const _ArrayNameTypeMarker = 'Array<'; 150 | 151 | bool _isList([String? typeName]) { 152 | return _isListWithType(typeName ?? T.toString()); 153 | } 154 | 155 | bool _isListWithType(String typeName) { 156 | return typeName.contains(_ListNameTypeMarker) || 157 | typeName.contains(_ArrayNameTypeMarker); 158 | } 159 | 160 | // JsonObjectMapper? _getTypeMap() { 161 | // var typeName = T.toString(); 162 | // final isList = _isList(); 163 | // return isList 164 | // ? _getTypeMapWithType(typeName) 165 | // : _getTypeMapWithType(typeName) as JsonObjectMapper; 166 | // } 167 | 168 | JsonObjectMapper? _getTypeMapWithType(String originalTypeName) { 169 | final typeName = _getInnerTypeFromName(originalTypeName); 170 | final typeMap = _mapper[typeName] as JsonObjectMapper?; 171 | assert(typeMap != null, 'The type ${typeName} is not registered.'); 172 | return typeMap; 173 | } 174 | 175 | // String _getTypeName() { 176 | // var typeName = T.toString(); 177 | // return _getInnerTypeFromName(typeName); 178 | // } 179 | 180 | String _getInnerTypeFromName(String typeName) { 181 | final isList = _isListWithType(typeName); 182 | if (isList) { 183 | var index; 184 | if (typeName.contains(_ListNameTypeMarker)) 185 | index = 186 | typeName.indexOf(_ListNameTypeMarker) + _ListNameTypeMarker.length; 187 | else if (typeName.contains(_ArrayNameTypeMarker)) 188 | index = typeName.indexOf(_ArrayNameTypeMarker) + 189 | _ArrayNameTypeMarker.length; 190 | 191 | if (index != null) 192 | typeName = typeName.substring(index, typeName.length - 1); 193 | } 194 | return typeName; 195 | } 196 | 197 | void registerConverter(JsonConverter transformer) { 198 | _toTypeConverterMap[TTo.toString()] = transformer; 199 | } 200 | 201 | TFrom? applyFromInstanceConverter(TTo value, 202 | [JsonConverter? converter]) { 203 | if (value == null) return null; 204 | final effectiveConverter = converter ?? _toTypeConverterMap[TTo.toString()]; 205 | return effectiveConverter != null 206 | ? effectiveConverter.toJson(value) 207 | : value; 208 | } 209 | 210 | dynamic? applyDynamicFromInstanceConverter(TTo value, 211 | [JsonConverter? converter]) { 212 | return applyFromInstanceConverter(value, converter); 213 | } 214 | 215 | TTo? applyFromJsonConverter(TFrom value, 216 | [JsonConverter? converter]) { 217 | if (value == null) return null; 218 | final effectiveConverter = converter ?? _toTypeConverterMap[TTo.toString()]; 219 | return effectiveConverter != null 220 | ? effectiveConverter.fromJson(value) 221 | : value; 222 | } 223 | 224 | TTo? applyDynamicFromJsonConverter(dynamic value, 225 | [JsonConverter? converter]) { 226 | return applyFromJsonConverter(value, converter); 227 | } 228 | 229 | // static bool _isPrimitveType() { 230 | // return T is bool || T is double || T is int || T is num || T is String; 231 | // } 232 | } 233 | -------------------------------------------------------------------------------- /simple_json_mapper/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | _fe_analyzer_shared: 5 | dependency: transitive 6 | description: 7 | name: _fe_analyzer_shared 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "18.0.0" 11 | analyzer: 12 | dependency: transitive 13 | description: 14 | name: analyzer 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "1.2.0" 18 | args: 19 | dependency: transitive 20 | description: 21 | name: args 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "2.0.0" 25 | async: 26 | dependency: transitive 27 | description: 28 | name: async 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "2.5.0" 32 | boolean_selector: 33 | dependency: transitive 34 | description: 35 | name: boolean_selector 36 | url: "https://pub.dartlang.org" 37 | source: hosted 38 | version: "2.1.0" 39 | charcode: 40 | dependency: transitive 41 | description: 42 | name: charcode 43 | url: "https://pub.dartlang.org" 44 | source: hosted 45 | version: "1.2.0" 46 | cli_util: 47 | dependency: transitive 48 | description: 49 | name: cli_util 50 | url: "https://pub.dartlang.org" 51 | source: hosted 52 | version: "0.3.0" 53 | collection: 54 | dependency: transitive 55 | description: 56 | name: collection 57 | url: "https://pub.dartlang.org" 58 | source: hosted 59 | version: "1.15.0" 60 | convert: 61 | dependency: transitive 62 | description: 63 | name: convert 64 | url: "https://pub.dartlang.org" 65 | source: hosted 66 | version: "3.0.0" 67 | coverage: 68 | dependency: transitive 69 | description: 70 | name: coverage 71 | url: "https://pub.dartlang.org" 72 | source: hosted 73 | version: "1.0.2" 74 | crypto: 75 | dependency: transitive 76 | description: 77 | name: crypto 78 | url: "https://pub.dartlang.org" 79 | source: hosted 80 | version: "3.0.0" 81 | file: 82 | dependency: transitive 83 | description: 84 | name: file 85 | url: "https://pub.dartlang.org" 86 | source: hosted 87 | version: "6.1.0" 88 | frontend_server_client: 89 | dependency: transitive 90 | description: 91 | name: frontend_server_client 92 | url: "https://pub.dartlang.org" 93 | source: hosted 94 | version: "2.1.2" 95 | glob: 96 | dependency: transitive 97 | description: 98 | name: glob 99 | url: "https://pub.dartlang.org" 100 | source: hosted 101 | version: "2.0.0" 102 | http_multi_server: 103 | dependency: transitive 104 | description: 105 | name: http_multi_server 106 | url: "https://pub.dartlang.org" 107 | source: hosted 108 | version: "3.0.0" 109 | http_parser: 110 | dependency: transitive 111 | description: 112 | name: http_parser 113 | url: "https://pub.dartlang.org" 114 | source: hosted 115 | version: "4.0.0" 116 | io: 117 | dependency: transitive 118 | description: 119 | name: io 120 | url: "https://pub.dartlang.org" 121 | source: hosted 122 | version: "1.0.0" 123 | js: 124 | dependency: transitive 125 | description: 126 | name: js 127 | url: "https://pub.dartlang.org" 128 | source: hosted 129 | version: "0.6.3" 130 | logging: 131 | dependency: transitive 132 | description: 133 | name: logging 134 | url: "https://pub.dartlang.org" 135 | source: hosted 136 | version: "1.0.0" 137 | matcher: 138 | dependency: transitive 139 | description: 140 | name: matcher 141 | url: "https://pub.dartlang.org" 142 | source: hosted 143 | version: "0.12.11" 144 | meta: 145 | dependency: transitive 146 | description: 147 | name: meta 148 | url: "https://pub.dartlang.org" 149 | source: hosted 150 | version: "1.3.0" 151 | mime: 152 | dependency: transitive 153 | description: 154 | name: mime 155 | url: "https://pub.dartlang.org" 156 | source: hosted 157 | version: "1.0.0" 158 | node_preamble: 159 | dependency: transitive 160 | description: 161 | name: node_preamble 162 | url: "https://pub.dartlang.org" 163 | source: hosted 164 | version: "2.0.0" 165 | package_config: 166 | dependency: transitive 167 | description: 168 | name: package_config 169 | url: "https://pub.dartlang.org" 170 | source: hosted 171 | version: "2.0.0" 172 | path: 173 | dependency: transitive 174 | description: 175 | name: path 176 | url: "https://pub.dartlang.org" 177 | source: hosted 178 | version: "1.8.0" 179 | pedantic: 180 | dependency: "direct dev" 181 | description: 182 | name: pedantic 183 | url: "https://pub.dartlang.org" 184 | source: hosted 185 | version: "1.11.1" 186 | pool: 187 | dependency: transitive 188 | description: 189 | name: pool 190 | url: "https://pub.dartlang.org" 191 | source: hosted 192 | version: "1.5.0" 193 | pub_semver: 194 | dependency: transitive 195 | description: 196 | name: pub_semver 197 | url: "https://pub.dartlang.org" 198 | source: hosted 199 | version: "2.0.0" 200 | shelf: 201 | dependency: transitive 202 | description: 203 | name: shelf 204 | url: "https://pub.dartlang.org" 205 | source: hosted 206 | version: "1.1.0" 207 | shelf_packages_handler: 208 | dependency: transitive 209 | description: 210 | name: shelf_packages_handler 211 | url: "https://pub.dartlang.org" 212 | source: hosted 213 | version: "3.0.0" 214 | shelf_static: 215 | dependency: transitive 216 | description: 217 | name: shelf_static 218 | url: "https://pub.dartlang.org" 219 | source: hosted 220 | version: "1.0.0" 221 | shelf_web_socket: 222 | dependency: transitive 223 | description: 224 | name: shelf_web_socket 225 | url: "https://pub.dartlang.org" 226 | source: hosted 227 | version: "1.0.1" 228 | source_map_stack_trace: 229 | dependency: transitive 230 | description: 231 | name: source_map_stack_trace 232 | url: "https://pub.dartlang.org" 233 | source: hosted 234 | version: "2.1.0" 235 | source_maps: 236 | dependency: transitive 237 | description: 238 | name: source_maps 239 | url: "https://pub.dartlang.org" 240 | source: hosted 241 | version: "0.10.10" 242 | source_span: 243 | dependency: transitive 244 | description: 245 | name: source_span 246 | url: "https://pub.dartlang.org" 247 | source: hosted 248 | version: "1.8.1" 249 | stack_trace: 250 | dependency: transitive 251 | description: 252 | name: stack_trace 253 | url: "https://pub.dartlang.org" 254 | source: hosted 255 | version: "1.10.0" 256 | stream_channel: 257 | dependency: transitive 258 | description: 259 | name: stream_channel 260 | url: "https://pub.dartlang.org" 261 | source: hosted 262 | version: "2.1.0" 263 | string_scanner: 264 | dependency: transitive 265 | description: 266 | name: string_scanner 267 | url: "https://pub.dartlang.org" 268 | source: hosted 269 | version: "1.1.0" 270 | term_glyph: 271 | dependency: transitive 272 | description: 273 | name: term_glyph 274 | url: "https://pub.dartlang.org" 275 | source: hosted 276 | version: "1.2.0" 277 | test: 278 | dependency: "direct dev" 279 | description: 280 | name: test 281 | url: "https://pub.dartlang.org" 282 | source: hosted 283 | version: "1.17.12" 284 | test_api: 285 | dependency: transitive 286 | description: 287 | name: test_api 288 | url: "https://pub.dartlang.org" 289 | source: hosted 290 | version: "0.4.3" 291 | test_core: 292 | dependency: transitive 293 | description: 294 | name: test_core 295 | url: "https://pub.dartlang.org" 296 | source: hosted 297 | version: "0.4.2" 298 | typed_data: 299 | dependency: transitive 300 | description: 301 | name: typed_data 302 | url: "https://pub.dartlang.org" 303 | source: hosted 304 | version: "1.3.0" 305 | vm_service: 306 | dependency: transitive 307 | description: 308 | name: vm_service 309 | url: "https://pub.dartlang.org" 310 | source: hosted 311 | version: "6.1.0+1" 312 | watcher: 313 | dependency: transitive 314 | description: 315 | name: watcher 316 | url: "https://pub.dartlang.org" 317 | source: hosted 318 | version: "1.0.0" 319 | web_socket_channel: 320 | dependency: transitive 321 | description: 322 | name: web_socket_channel 323 | url: "https://pub.dartlang.org" 324 | source: hosted 325 | version: "2.0.0" 326 | webkit_inspection_protocol: 327 | dependency: transitive 328 | description: 329 | name: webkit_inspection_protocol 330 | url: "https://pub.dartlang.org" 331 | source: hosted 332 | version: "1.0.0" 333 | yaml: 334 | dependency: transitive 335 | description: 336 | name: yaml 337 | url: "https://pub.dartlang.org" 338 | source: hosted 339 | version: "3.1.0" 340 | sdks: 341 | dart: ">=2.12.0 <3.0.0" 342 | -------------------------------------------------------------------------------- /simple_json_mapper/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: simple_json_mapper 2 | description: >- 3 | Classes and helper functions that support JSON code generation and serialization via the 4 | `simple_json` package. 5 | version: 2.2.0 6 | homepage: https://github.com/FlutterDevTools/simple_json 7 | 8 | environment: 9 | sdk: ">=2.12.0 <3.0.0" 10 | 11 | dev_dependencies: 12 | pedantic: ^1.11.1 13 | test: ^1.17.12 14 | -------------------------------------------------------------------------------- /simple_json_mapper/test/basic_converter_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:simple_json_mapper/simple_json_mapper.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | import 'test_data/test.dart'; 5 | 6 | void main() { 7 | const serializedTest = '{"name":"Blah"}'; 8 | setUpAll(() { 9 | // The registration is normally done automatically by the generator (`simple_json package`) 10 | JsonMapper.register(JsonObjectMapper( 11 | (mapper, map) => Test( 12 | name: map['name'] as String, 13 | ), 14 | (mapper, instance) => { 15 | 'name': instance.name, 16 | }, 17 | )); 18 | }); 19 | 20 | group('Serialize', () { 21 | test('Simple model', () { 22 | final jsonStr = JsonMapper.serialize(Test(name: 'Blah')); 23 | expect(jsonStr, equals(serializedTest)); 24 | }); 25 | }); 26 | group('Deserialize', () { 27 | test('Simple model', () { 28 | final obj = JsonMapper.deserialize(serializedTest); 29 | expect(obj, isNotNull); 30 | expect(obj!.name, equals('Blah')); 31 | }); 32 | }); 33 | } 34 | -------------------------------------------------------------------------------- /simple_json_mapper/test/test_data/test.dart: -------------------------------------------------------------------------------- 1 | import 'package:simple_json_mapper/simple_json_mapper.dart'; 2 | 3 | @JObj() 4 | class Test { 5 | const Test({required this.name}); 6 | final String name; 7 | } 8 | --------------------------------------------------------------------------------