├── LICENSE ├── README.md ├── mapper ├── .pubignore ├── lib │ ├── src │ │ ├── builder │ │ │ ├── index.dart │ │ │ ├── comparable_class_element.dart │ │ │ ├── change_analyzer.dart │ │ │ ├── library_visitor.dart │ │ │ └── builder.dart │ │ ├── globals.dart │ │ ├── model │ │ │ ├── index │ │ │ │ ├── conversion_direction.dart │ │ │ │ ├── injectable_values.dart │ │ │ │ ├── descriptors.dart │ │ │ │ ├── options.dart │ │ │ │ └── context.dart │ │ │ ├── value_decorators.dart │ │ │ ├── index.dart │ │ │ ├── converters │ │ │ │ ├── uri_converter.dart │ │ │ │ ├── regexp_converter.dart │ │ │ │ ├── bigint_converter.dart │ │ │ │ ├── duration_converter.dart │ │ │ │ ├── symbol_converter.dart │ │ │ │ ├── uint8list_converter.dart │ │ │ │ ├── enum_converter.dart │ │ │ │ ├── date_converter.dart │ │ │ │ ├── number_converter.dart │ │ │ │ ├── default_converter.dart │ │ │ │ ├── enum_converter_numeric.dart │ │ │ │ ├── base_converter.dart │ │ │ │ ├── map_converter.dart │ │ │ │ ├── default_iterable_converter.dart │ │ │ │ └── enum_converter_short.dart │ │ │ ├── converters.dart │ │ │ └── enum.dart │ │ ├── logic │ │ │ ├── cache_manager.dart │ │ │ ├── reflection_handler.dart │ │ │ ├── type_info_handler.dart │ │ │ ├── adapter_manager.dart │ │ │ └── converter_handler.dart │ │ ├── identifier_casing.dart │ │ └── json_map.dart │ ├── dart_json_mapper.dart │ └── builder_factory.dart ├── analysis_options.yaml ├── pubspec.yaml ├── build.yaml ├── LICENSE └── example │ └── example.dart ├── .github ├── FUNDING.yml └── workflows │ └── pipeline.yml ├── perf-test ├── test │ ├── starlink │ │ ├── _test.dart │ │ ├── json_serializable │ │ │ ├── json_serializable_test.dart │ │ │ ├── index.dart │ │ │ └── model.dart │ │ ├── dart_json_mapper │ │ │ ├── dart_json_mapper_test.dart │ │ │ └── index.dart │ │ └── built_value │ │ │ ├── index.dart │ │ │ ├── built_value_test.dart │ │ │ └── model.dart │ └── unit │ │ ├── test.mixins.dart │ │ ├── test.cache_manager.dart │ │ ├── test.adapter_manager.dart │ │ ├── test.converters.caching.dart │ │ ├── test_issue_225.dart │ │ ├── test_issue_234.dart │ │ ├── _test.dart │ │ ├── test.tuple.dart │ │ ├── test.flatten.dart │ │ ├── test.required.dart │ │ ├── test.injection.dart │ │ ├── test.generics.dart │ │ ├── test.special.cases.dart │ │ ├── test.inheritance.dart │ │ ├── test.integration.dart │ │ ├── test.scheme.dart │ │ ├── test.collections.dart │ │ ├── test.default.value.dart │ │ └── test.raw_json.dart ├── analysis_options.yaml ├── build.yaml └── pubspec.yaml ├── adapters ├── fixnum │ ├── analysis_options.yaml │ ├── build.yaml │ ├── test │ │ ├── _test.dart │ │ └── test.basics.dart │ ├── CHANGELOG.md │ ├── pubspec.yaml │ ├── example │ │ ├── example.dart │ │ └── example.mapper.g.dart │ ├── README.md │ └── lib │ │ └── dart_json_mapper_fixnum.dart ├── flutter │ ├── analysis_options.yaml │ ├── build.yaml │ ├── CHANGELOG.md │ ├── test │ │ ├── _test.dart │ │ └── test.basics.dart │ ├── example │ │ ├── example.dart │ │ └── example.mapper.g.dart │ ├── pubspec.yaml │ ├── README.md │ └── lib │ │ └── dart_json_mapper_flutter.dart ├── mobx │ ├── analysis_options.yaml │ ├── build.yaml │ ├── pubspec.yaml │ ├── test │ │ ├── _test.dart │ │ └── _test.g.dart │ ├── example │ │ ├── example.dart │ │ └── example.mapper.g.dart │ ├── CHANGELOG.md │ └── README.md └── built │ ├── analysis_options.yaml │ ├── CHANGELOG.md │ ├── build.yaml │ ├── test │ ├── _test.dart │ └── test.basics.dart │ ├── pubspec.yaml │ ├── example │ ├── example.dart │ └── example.mapper.g.dart │ ├── README.md │ └── lib │ └── dart_json_mapper_built.dart ├── models ├── starlink │ ├── build.yaml │ ├── lib │ │ ├── starlink.dart │ │ └── model.dart │ └── pubspec.yaml ├── unit_testing │ ├── build.yaml │ ├── lib │ │ ├── immutable.dart │ │ ├── unit_testing.dart │ │ ├── json.dart │ │ ├── model.dart │ │ ├── inheritance.dart │ │ └── generic.dart │ └── pubspec.yaml └── readme.md └── .gitignore /LICENSE: -------------------------------------------------------------------------------- 1 | ./mapper/LICENSE -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ./mapper/README.md -------------------------------------------------------------------------------- /mapper/.pubignore: -------------------------------------------------------------------------------- 1 | analysis_options.yaml -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: k-paxian 2 | -------------------------------------------------------------------------------- /perf-test/test/starlink/_test.dart: -------------------------------------------------------------------------------- 1 | void main() {} 2 | -------------------------------------------------------------------------------- /mapper/lib/src/builder/index.dart: -------------------------------------------------------------------------------- 1 | export 'builder.dart'; 2 | -------------------------------------------------------------------------------- /adapters/fixnum/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:lints/recommended.yaml -------------------------------------------------------------------------------- /adapters/flutter/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:lints/recommended.yaml -------------------------------------------------------------------------------- /adapters/mobx/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:lints/recommended.yaml -------------------------------------------------------------------------------- /mapper/lib/src/globals.dart: -------------------------------------------------------------------------------- 1 | Type typeOf() => T; 2 | 3 | const kIsWeb = identical(0, 0.0); -------------------------------------------------------------------------------- /mapper/lib/src/model/index/conversion_direction.dart: -------------------------------------------------------------------------------- 1 | enum ConversionDirection { fromJson, toJson } 2 | -------------------------------------------------------------------------------- /mapper/lib/src/model/index/injectable_values.dart: -------------------------------------------------------------------------------- 1 | typedef InjectableValues = Map; 2 | -------------------------------------------------------------------------------- /mapper/lib/src/model/value_decorators.dart: -------------------------------------------------------------------------------- 1 | typedef ValueDecoratorFunction = dynamic Function(dynamic value); 2 | -------------------------------------------------------------------------------- /perf-test/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:lints/recommended.yaml 2 | 3 | linter: 4 | rules: 5 | unnecessary_parenthesis: true 6 | prefer_const_constructors: true 7 | prefer_final_locals: true -------------------------------------------------------------------------------- /adapters/built/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:lints/recommended.yaml 2 | 3 | linter: 4 | rules: 5 | unnecessary_parenthesis: true 6 | prefer_const_constructors: true 7 | prefer_final_locals: true -------------------------------------------------------------------------------- /mapper/lib/dart_json_mapper.dart: -------------------------------------------------------------------------------- 1 | export './src/errors.dart'; 2 | export './src/mapper.dart'; 3 | export './src/model/index.dart'; 4 | export './src/globals.dart'; 5 | export './src/json_map.dart'; 6 | export './src/class_info.dart'; 7 | -------------------------------------------------------------------------------- /models/starlink/build.yaml: -------------------------------------------------------------------------------- 1 | targets: 2 | $default: 3 | builders: 4 | reflectable_builder: 5 | generate_for: 6 | - no/files 7 | dart_json_mapper: 8 | generate_for: 9 | - lib/starlink.dart -------------------------------------------------------------------------------- /models/starlink/lib/starlink.dart: -------------------------------------------------------------------------------- 1 | export 'model.dart'; 2 | export 'starlink.mapper.g.dart' 3 | show 4 | starlinkGeneratedAdapter, 5 | initializeJsonMapper, 6 | initializeJsonMapperAsync; 7 | 8 | void main() {} 9 | -------------------------------------------------------------------------------- /models/unit_testing/build.yaml: -------------------------------------------------------------------------------- 1 | targets: 2 | $default: 3 | builders: 4 | reflectable_builder: 5 | generate_for: 6 | - no/files 7 | dart_json_mapper: 8 | generate_for: 9 | - lib/unit_testing.dart -------------------------------------------------------------------------------- /adapters/built/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.0.1 2 | 3 | * Update mapper adapter contract to latest 4 | 5 | ## 1.0.0 6 | 7 | * Update mapper adapter contract to latest 8 | 9 | ## 0.0.1 10 | 11 | * Initial support for BuiltList, BuiltSet, BuiltMap types -------------------------------------------------------------------------------- /adapters/mobx/build.yaml: -------------------------------------------------------------------------------- 1 | targets: 2 | $default: 3 | builders: 4 | dart_json_mapper: 5 | generate_for: 6 | - example/**.dart 7 | - test/_test.dart 8 | reflectable: 9 | generate_for: 10 | - no/files -------------------------------------------------------------------------------- /adapters/built/build.yaml: -------------------------------------------------------------------------------- 1 | targets: 2 | $default: 3 | builders: 4 | dart_json_mapper: 5 | generate_for: 6 | - example/**.dart 7 | - test/_test.dart 8 | reflectable: 9 | generate_for: 10 | - no/files -------------------------------------------------------------------------------- /adapters/fixnum/build.yaml: -------------------------------------------------------------------------------- 1 | targets: 2 | $default: 3 | builders: 4 | dart_json_mapper: 5 | generate_for: 6 | - example/**.dart 7 | - test/_test.dart 8 | reflectable: 9 | generate_for: 10 | - no/files -------------------------------------------------------------------------------- /adapters/flutter/build.yaml: -------------------------------------------------------------------------------- 1 | targets: 2 | $default: 3 | builders: 4 | dart_json_mapper: 5 | generate_for: 6 | - example/**.dart 7 | - test/_test.dart 8 | reflectable: 9 | generate_for: 10 | - no/files -------------------------------------------------------------------------------- /mapper/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:lints/recommended.yaml 2 | 3 | analyzer: 4 | errors: 5 | deprecated_member_use: ignore 6 | linter: 7 | rules: 8 | unnecessary_parenthesis: true 9 | prefer_const_constructors: true 10 | prefer_final_locals: true -------------------------------------------------------------------------------- /models/readme.md: -------------------------------------------------------------------------------- 1 | ## Shared Model Packages 2 | 3 | This folder contains reusable packages defining various models to be consumed by other projects / packages. 4 | 5 | Intention is to illustrate possibility to divide / extract / encapsulate / isolate / modularize model definitions. 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://www.dartlang.org/guides/libraries/private-files 2 | 3 | # Files and directories created by pub 4 | .dart_tool/ 5 | .packages 6 | .pub/ 7 | build/ 8 | # If you're building an application, you may want to check-in your pubspec.lock 9 | pubspec.lock 10 | # Idea stuff 11 | *.iml 12 | .idea -------------------------------------------------------------------------------- /models/unit_testing/lib/immutable.dart: -------------------------------------------------------------------------------- 1 | import 'package:dart_json_mapper/dart_json_mapper.dart'; 2 | 3 | import 'model.dart'; 4 | 5 | @jsonSerializable 6 | class Immutable { 7 | final int id; 8 | final String name; 9 | final Car car; 10 | 11 | const Immutable(this.id, this.name, this.car); 12 | } 13 | -------------------------------------------------------------------------------- /mapper/lib/builder_factory.dart: -------------------------------------------------------------------------------- 1 | import 'package:build/build.dart'; 2 | 3 | import './src/builder/index.dart'; 4 | 5 | DartJsonMapperBuilder dartJsonMapperBuilder(BuilderOptions options) { 6 | final config = Map.from(options.config); 7 | config.putIfAbsent('entry_points', () => ['**.dart']); 8 | return DartJsonMapperBuilder(options); 9 | } 10 | -------------------------------------------------------------------------------- /models/unit_testing/lib/unit_testing.dart: -------------------------------------------------------------------------------- 1 | export './generic.dart'; 2 | export './immutable.dart'; 3 | export './json.dart'; 4 | export './model.dart'; 5 | export './inheritance.dart'; 6 | export 'unit_testing.mapper.g.dart' 7 | show 8 | unitTestingGeneratedAdapter, 9 | initializeJsonMapper, 10 | initializeJsonMapperAsync; 11 | 12 | void main() {} 13 | -------------------------------------------------------------------------------- /adapters/built/test/_test.dart: -------------------------------------------------------------------------------- 1 | library json_mapper_built.test; 2 | 3 | import 'package:dart_json_mapper_built/dart_json_mapper_built.dart' 4 | show builtAdapter; 5 | 6 | import '_test.mapper.g.dart' show initializeJsonMapper; 7 | import 'test.basics.dart'; 8 | 9 | void main() { 10 | initializeJsonMapper(adapters: [builtAdapter]).info(); 11 | 12 | testBasics(); 13 | } 14 | -------------------------------------------------------------------------------- /perf-test/build.yaml: -------------------------------------------------------------------------------- 1 | targets: 2 | $default: 3 | builders: 4 | build_web_compilers:entrypoint: 5 | generate_for: 6 | - test/unit/*.dart 7 | dart_json_mapper: 8 | options: 9 | iterables: List, Set 10 | generate_for: 11 | - test/unit/_test.dart 12 | reflectable_builder: 13 | generate_for: 14 | - no/files -------------------------------------------------------------------------------- /mapper/lib/src/model/index.dart: -------------------------------------------------------------------------------- 1 | export '../identifier_casing.dart'; 2 | export 'adapters.dart'; 3 | export 'annotations.dart'; 4 | export 'converters.dart'; 5 | export 'enum.dart'; 6 | export 'type_info.dart'; 7 | export 'value_decorators.dart'; 8 | 9 | export 'index/context.dart'; 10 | export 'index/conversion_direction.dart'; 11 | export 'index/descriptors.dart'; 12 | export 'index/injectable_values.dart'; 13 | export 'index/options.dart'; -------------------------------------------------------------------------------- /models/starlink/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: starlink 2 | # This package is not intended to be published 3 | publish_to: none 4 | description: > 5 | This package contains classes to define Starlink data structures: 6 | https://api.spacexdata.com/v4/starlink 7 | environment: 8 | sdk: '>=3.0.0 <4.0.0' 9 | dependencies: 10 | dart_json_mapper: 11 | dev_dependencies: 12 | build_runner: 13 | dependency_overrides: 14 | dart_json_mapper: 15 | path: ../../mapper -------------------------------------------------------------------------------- /models/unit_testing/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: unit_testing 2 | # This package is not intended to be published 3 | publish_to: none 4 | description: > 5 | This package contains classes to define data structures for Dart Json Mapper Unit Tests. 6 | environment: 7 | sdk: '>=3.0.0 <4.0.0' 8 | dependencies: 9 | dart_json_mapper: 10 | dev_dependencies: 11 | build_runner: 12 | test: any 13 | dependency_overrides: 14 | dart_json_mapper: 15 | path: ../../mapper -------------------------------------------------------------------------------- /adapters/flutter/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 2.0.2 2 | 3 | * Support for new code converters contract 4 | 5 | ## 2.0.1 6 | 7 | * dartdocs added 8 | 9 | ## 2.0.0 10 | 11 | * null safety support 12 | 13 | ## 1.0.3 14 | 15 | * Support for new code converters contract 16 | 17 | ## 1.0.2 18 | 19 | * Support for new code generation contract 20 | 21 | ## 1.0.1 22 | 23 | * Added support for `Color` type alpha byte 24 | 25 | ## 1.0.0 26 | 27 | * Initial support for `Color` type -------------------------------------------------------------------------------- /perf-test/test/starlink/json_serializable/json_serializable_test.dart: -------------------------------------------------------------------------------- 1 | library perf_test.test; 2 | 3 | import 'dart:convert'; 4 | 5 | import 'package:intl/intl.dart'; 6 | import 'package:json_annotation/json_annotation.dart'; 7 | 8 | part './index.dart'; 9 | part './model.dart'; 10 | part 'json_serializable_test.g.dart'; 11 | 12 | @JsonLiteral('../starlink.json') 13 | Iterable get list => _$listJsonLiteral; 14 | 15 | void main() { 16 | print('\n>> json_serializable'); 17 | testStarlink(list); 18 | } 19 | -------------------------------------------------------------------------------- /mapper/lib/src/model/converters/uri_converter.dart: -------------------------------------------------------------------------------- 1 | import '../index.dart'; 2 | 3 | const uriConverter = UriConverter(); 4 | 5 | /// Uri converter 6 | class UriConverter implements ICustomConverter { 7 | const UriConverter() : super(); 8 | 9 | @override 10 | Uri? fromJSON(dynamic jsonValue, DeserializationContext context) => 11 | jsonValue is String ? Uri.tryParse(jsonValue) : jsonValue; 12 | 13 | @override 14 | String? toJSON(Uri? object, SerializationContext context) => 15 | object?.toString(); 16 | } 17 | -------------------------------------------------------------------------------- /mapper/lib/src/model/converters/regexp_converter.dart: -------------------------------------------------------------------------------- 1 | import '../index.dart'; 2 | 3 | const regExpConverter = RegExpConverter(); 4 | 5 | /// RegExp converter 6 | class RegExpConverter implements ICustomConverter { 7 | const RegExpConverter() : super(); 8 | 9 | @override 10 | RegExp? fromJSON(dynamic jsonValue, DeserializationContext context) => 11 | jsonValue is String ? RegExp(jsonValue) : jsonValue; 12 | 13 | @override 14 | dynamic toJSON(RegExp? object, SerializationContext context) => 15 | object?.pattern; 16 | } 17 | -------------------------------------------------------------------------------- /adapters/flutter/test/_test.dart: -------------------------------------------------------------------------------- 1 | library json_mapper_flutter.test; 2 | 3 | import 'dart:ui'; 4 | 5 | import 'package:dart_json_mapper/dart_json_mapper.dart' 6 | show JsonMapper, jsonSerializable, SerializationOptions; 7 | import 'package:dart_json_mapper_flutter/dart_json_mapper_flutter.dart' 8 | show flutterAdapter; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import '_test.mapper.g.dart' show initializeJsonMapper; 12 | 13 | part 'test.basics.dart'; 14 | 15 | void main() { 16 | initializeJsonMapper(adapters: [flutterAdapter]).info(); 17 | 18 | testBasics(); 19 | } 20 | -------------------------------------------------------------------------------- /perf-test/test/starlink/dart_json_mapper/dart_json_mapper_test.dart: -------------------------------------------------------------------------------- 1 | library perf_test.test; 2 | 3 | import 'dart:convert' show json; 4 | import 'dart:io' show File; 5 | 6 | import 'package:dart_json_mapper/dart_json_mapper.dart'; 7 | import 'package:path/path.dart' as path; 8 | import 'package:starlink/starlink.dart' show Record, initializeJsonMapper; 9 | 10 | part './index.dart'; 11 | 12 | void main() async { 13 | initializeJsonMapper(); 14 | print('\n>> dart_json_mapper'); 15 | testStarlink(json.decode( 16 | await File(path.absolute('test/starlink/starlink.json')).readAsString())); 17 | } 18 | -------------------------------------------------------------------------------- /adapters/fixnum/test/_test.dart: -------------------------------------------------------------------------------- 1 | library json_mapper_fixnum.test; 2 | 3 | import 'package:dart_json_mapper/dart_json_mapper.dart' 4 | show JsonMapper, SerializationOptions, jsonSerializable; 5 | import 'package:dart_json_mapper_fixnum/dart_json_mapper_fixnum.dart' 6 | show fixnumAdapter; 7 | import 'package:fixnum/fixnum.dart' show Int32, Int64; 8 | import 'package:test/test.dart'; 9 | 10 | import '_test.mapper.g.dart' show initializeJsonMapper; 11 | 12 | part 'test.basics.dart'; 13 | 14 | void main() { 15 | initializeJsonMapper(adapters: [fixnumAdapter]).info(); 16 | 17 | testBasics(); 18 | } 19 | -------------------------------------------------------------------------------- /mapper/lib/src/model/converters/bigint_converter.dart: -------------------------------------------------------------------------------- 1 | import '../index.dart'; 2 | 3 | const bigIntConverter = BigIntConverter(); 4 | 5 | /// [BigInt] converter 6 | class BigIntConverter implements ICustomConverter { 7 | const BigIntConverter() : super(); 8 | 9 | @override 10 | Object? fromJSON(dynamic jsonValue, DeserializationContext context) { 11 | return jsonValue is String ? BigInt.tryParse(jsonValue) : jsonValue; 12 | } 13 | 14 | @override 15 | dynamic toJSON(Object? object, SerializationContext context) { 16 | return object is BigInt ? object.toString() : object; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /adapters/fixnum/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.1.4 2 | 3 | * Support for new code converters contract 4 | 5 | ## 1.1.3 6 | 7 | * Support for new code converters contract 8 | 9 | ## 1.1.2 10 | 11 | * Support for new code generation contract 12 | 13 | ## 1.1.1 14 | 15 | * Support for new adapters contract 16 | 17 | ## 1.1.0 18 | 19 | * Support for new adapters contract 20 | 21 | ## 1.0.1 22 | 23 | * Serialize to JSON number instead of string 24 | 25 | ## 1.0.0 26 | 27 | * Support for [Int32, Int64, List, Set, List, Set ] types 28 | 29 | ## 0.1.0 30 | 31 | * Initial support for Int32, Int64 types -------------------------------------------------------------------------------- /adapters/mobx/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: dart_json_mapper_mobx 2 | version: 2.0.5 3 | description: > 4 | This is a dart-json-mapper complementary package 5 | provides support for MobX Stores to persist as JSON. 6 | homepage: https://github.com/k-paxian/dart-json-mapper/tree/master/adapters/mobx 7 | environment: 8 | sdk: '>=3.0.0 <4.0.0' 9 | dependencies: 10 | dart_json_mapper: '>=2.1.12 <3.0.0' 11 | mobx: ^2.0.7 12 | dev_dependencies: 13 | mobx_codegen: 14 | reflectable: 15 | lints: 16 | build_runner: 17 | build_test: 18 | test: 19 | #dependency_overrides: 20 | # dart_json_mapper: 21 | # path: ../../mapper 22 | -------------------------------------------------------------------------------- /mapper/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: dart_json_mapper 2 | version: 2.2.20 3 | description: > 4 | This package allows programmers to annotate Dart objects in order to 5 | serialize / deserialize them from / to JSON. 6 | homepage: https://github.com/k-paxian/dart-json-mapper 7 | environment: 8 | sdk: '>=3.0.0 <4.0.0' 9 | dependencies: 10 | analyzer: ^7.7.0 11 | build: ^2.4.1 12 | build_config: ^1.1.1 13 | intl: ^0.19.0 14 | meta: ^1.17.0 15 | path: ^1.8.3 16 | reflectable: ^5.0.1 17 | collection: ^1.18.0 18 | pubspec_parse: ^1.3.0 19 | dev_dependencies: 20 | lints: 21 | build_runner: 22 | reflectable_builder: ^1.0.1 23 | -------------------------------------------------------------------------------- /adapters/flutter/example/example.dart: -------------------------------------------------------------------------------- 1 | library json_mapper_flutter.example; 2 | 3 | import 'dart:ui' show Color; 4 | 5 | import 'package:dart_json_mapper/dart_json_mapper.dart' 6 | show JsonMapper, jsonSerializable; 7 | import 'package:dart_json_mapper_flutter/dart_json_mapper_flutter.dart' 8 | show flutterAdapter; 9 | 10 | import 'example.mapper.g.dart' show initializeJsonMapper; 11 | 12 | @jsonSerializable 13 | class FlutterClass { 14 | Color color; 15 | 16 | FlutterClass(this.color); 17 | } 18 | 19 | void main() { 20 | initializeJsonMapper(adapters: [flutterAdapter]); 21 | 22 | print(JsonMapper.serialize(FlutterClass(Color(0x003f4f5f)))); 23 | } 24 | -------------------------------------------------------------------------------- /adapters/fixnum/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: dart_json_mapper_fixnum 2 | version: 1.1.4 3 | description: > 4 | This is a dart-json-mapper complementary package 5 | provides support for https://pub.dev/packages/fixnum types in order to 6 | serialize / deserialize them from / to JSON. 7 | homepage: https://github.com/k-paxian/dart-json-mapper/tree/master/adapters/fixnum 8 | environment: 9 | sdk: '>=3.0.0 <4.0.0' 10 | dependencies: 11 | dart_json_mapper: '>=2.1.12 <3.0.0' 12 | fixnum: ^1.0.0 13 | dev_dependencies: 14 | reflectable: 15 | lints: 16 | build_runner: 17 | build_test: 18 | test: 19 | #dependency_overrides: 20 | # dart_json_mapper: 21 | # path: ../../mapper -------------------------------------------------------------------------------- /mapper/lib/src/model/converters/duration_converter.dart: -------------------------------------------------------------------------------- 1 | import '../index.dart'; 2 | 3 | const durationConverter = DurationConverter(); 4 | 5 | /// DurationConverter converter for [Duration] type 6 | class DurationConverter implements ICustomConverter { 7 | const DurationConverter() : super(); 8 | 9 | @override 10 | Duration? fromJSON(dynamic jsonValue, DeserializationContext context) { 11 | return jsonValue is num 12 | ? Duration(microseconds: jsonValue as int) 13 | : jsonValue; 14 | } 15 | 16 | @override 17 | dynamic toJSON(Duration? object, SerializationContext context) { 18 | return object?.inMicroseconds; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /mapper/lib/src/model/converters/symbol_converter.dart: -------------------------------------------------------------------------------- 1 | import '../index.dart'; 2 | 3 | const symbolConverter = SymbolConverter(); 4 | 5 | /// Default converter for [Symbol] type 6 | class SymbolConverter implements ICustomConverter { 7 | const SymbolConverter() : super(); 8 | 9 | @override 10 | Object? fromJSON(dynamic jsonValue, DeserializationContext context) { 11 | return jsonValue is String ? Symbol(jsonValue) : jsonValue; 12 | } 13 | 14 | @override 15 | dynamic toJSON(Object? object, SerializationContext context) { 16 | return object != null 17 | ? RegExp('"(.+)"').allMatches(object.toString()).first.group(1) 18 | : null; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /adapters/built/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: dart_json_mapper_built 2 | version: 1.0.1 3 | description: > 4 | This is a dart-json-mapper complementary package 5 | provides support for https://pub.dev/packages/built_collection types in order to 6 | serialize / deserialize them from / to JSON. 7 | homepage: https://github.com/k-paxian/dart-json-mapper/tree/master/adapters/built 8 | environment: 9 | sdk: '>=3.0.0 <4.0.0' 10 | dependencies: 11 | dart_json_mapper: '>=2.1.12 <3.0.0' 12 | built_collection: ^5.1.1 13 | dev_dependencies: 14 | reflectable: 15 | lints: 16 | build_runner: 17 | build_test: 18 | test: 19 | #dependency_overrides: 20 | # dart_json_mapper: 21 | # path: ../../mapper -------------------------------------------------------------------------------- /adapters/built/example/example.dart: -------------------------------------------------------------------------------- 1 | library json_mapper_fixnum.example; 2 | 3 | import 'package:built_collection/built_collection.dart'; 4 | import 'package:dart_json_mapper/dart_json_mapper.dart' 5 | show JsonMapper, jsonSerializable; 6 | import 'package:dart_json_mapper_built/dart_json_mapper_built.dart' 7 | show builtAdapter; 8 | 9 | import 'example.mapper.g.dart' show initializeJsonMapper; 10 | 11 | @jsonSerializable 12 | class ImmutableClass { 13 | final BuiltList list; 14 | 15 | const ImmutableClass(this.list); 16 | } 17 | 18 | void main() { 19 | initializeJsonMapper(adapters: [builtAdapter]); 20 | 21 | print(JsonMapper.serialize(ImmutableClass(BuiltList.of([1, 2, 3])))); 22 | } 23 | -------------------------------------------------------------------------------- /adapters/flutter/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: dart_json_mapper_flutter 2 | version: 2.0.1 3 | description: > 4 | This is a dart-json-mapper complementary package 5 | provides support for https://github.com/flutter/flutter types in order to 6 | serialize / deserialize them from / to JSON. 7 | homepage: https://github.com/k-paxian/dart-json-mapper/tree/master/adapters/flutter 8 | environment: 9 | sdk: '>=3.0.0 <4.0.0' 10 | dependencies: 11 | dart_json_mapper: '>=2.1.12 <3.0.0' 12 | flutter: 13 | sdk: flutter 14 | dev_dependencies: 15 | reflectable: 16 | flutter_test: 17 | sdk: flutter 18 | lints: 19 | build_runner: 20 | build_test: 21 | #dependency_overrides: 22 | # dart_json_mapper: 23 | # path: ../../mapper -------------------------------------------------------------------------------- /adapters/flutter/test/test.basics.dart: -------------------------------------------------------------------------------- 1 | part of json_mapper_flutter.test; 2 | 3 | /// Sample flutter data class container 4 | @jsonSerializable 5 | class ColorfulItem { 6 | String name; 7 | Color color; 8 | 9 | ColorfulItem(this.name, this.color); 10 | } 11 | 12 | /// Shorthand for serialization options instance 13 | final compactOptions = SerializationOptions(indent: ''); 14 | 15 | void testBasics() { 16 | test('Color type', () { 17 | // given 18 | final color = Color(0x003f4f5f); 19 | 20 | // when 21 | final json = JsonMapper.serialize(ColorfulItem('Item 1', color)); 22 | final target = JsonMapper.deserialize(json)!; 23 | 24 | // then 25 | expect(target.color, color); 26 | }); 27 | } 28 | -------------------------------------------------------------------------------- /mapper/lib/src/model/converters.dart: -------------------------------------------------------------------------------- 1 | export 'converters/base_converter.dart'; 2 | export 'converters/bigint_converter.dart'; 3 | export 'converters/date_converter.dart'; 4 | export 'converters/default_converter.dart'; 5 | export 'converters/default_iterable_converter.dart'; 6 | export 'converters/duration_converter.dart'; 7 | export 'converters/enum_converter.dart'; 8 | export 'converters/enum_converter_numeric.dart'; 9 | export 'converters/enum_converter_short.dart'; 10 | export 'converters/map_converter.dart'; 11 | export 'converters/number_converter.dart'; 12 | export 'converters/regexp_converter.dart'; 13 | export 'converters/symbol_converter.dart'; 14 | export 'converters/uint8list_converter.dart'; 15 | export 'converters/uri_converter.dart'; -------------------------------------------------------------------------------- /mapper/lib/src/model/converters/uint8list_converter.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show base64Decode, base64Encode; 2 | import 'dart:typed_data' show Uint8List; 3 | 4 | import '../index.dart'; 5 | 6 | const uint8ListConverter = Uint8ListConverter(); 7 | 8 | /// [Uint8List] converter to base64 and back 9 | class Uint8ListConverter implements ICustomConverter { 10 | const Uint8ListConverter() : super(); 11 | 12 | @override 13 | Object? fromJSON(dynamic jsonValue, DeserializationContext context) { 14 | return jsonValue is String ? base64Decode(jsonValue) : jsonValue; 15 | } 16 | 17 | @override 18 | dynamic toJSON(Object? object, SerializationContext context) { 19 | return object is Uint8List ? base64Encode(object) : object; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /mapper/lib/src/builder/comparable_class_element.dart: -------------------------------------------------------------------------------- 1 | import 'package:analyzer/dart/element/element.dart'; 2 | 3 | class ComparableClassElement { 4 | ClassElement element; 5 | 6 | ComparableClassElement(this.element); 7 | 8 | String _elementsListAsString(Iterable list) => 9 | list.map((element) => element.displayName).join(''); 10 | 11 | @override 12 | bool operator ==(Object other) => hashCode == other.hashCode; 13 | 14 | @override 15 | String toString() { 16 | return element.displayName; 17 | } 18 | 19 | @override 20 | int get hashCode => 21 | _elementsListAsString(element.accessors).hashCode + 22 | _elementsListAsString(element.methods).hashCode + 23 | _elementsListAsString(element.typeParameters).hashCode + 24 | _elementsListAsString(element.constructors).hashCode + 25 | _elementsListAsString(element.fields).hashCode; 26 | } 27 | -------------------------------------------------------------------------------- /perf-test/test/starlink/dart_json_mapper/index.dart: -------------------------------------------------------------------------------- 1 | part of 'dart_json_mapper_test.dart'; 2 | 3 | void testStarlink(Iterable list) { 4 | final stopwatch = Stopwatch()..start(); 5 | final records = list.map((x) => JsonMapper.fromMap(x)).toList(); 6 | final deserializationMs = stopwatch.elapsedMilliseconds; 7 | final timePerRecordMs = 8 | (deserializationMs / records.length).toStringAsPrecision(2); 9 | print( 10 | 'Deserialization of ${records.length} records executed in ${deserializationMs}ms, at $timePerRecordMs ms per record'); 11 | 12 | final stopwatch2 = Stopwatch()..start(); 13 | JsonMapper.serialize(records); 14 | final serializationMs = stopwatch2.elapsedMilliseconds; 15 | final timePerRecordMs2 = 16 | (serializationMs / records.length).toStringAsPrecision(2); 17 | print( 18 | 'Serialization of ${records.length} records executed in ${serializationMs}ms, at $timePerRecordMs2 ms per record'); 19 | } 20 | -------------------------------------------------------------------------------- /mapper/lib/src/logic/cache_manager.dart: -------------------------------------------------------------------------------- 1 | import 'package:dart_json_mapper/src/model/index.dart'; 2 | 3 | class CacheManager { 4 | final Map _processedObjects = {}; 5 | 6 | String getObjectKey(Object object) => 7 | '${object.runtimeType}-${identityHashCode(object)}'; 8 | 9 | ProcessedObjectDescriptor? getObjectProcessed(Object object, int level) { 10 | ProcessedObjectDescriptor? result; 11 | 12 | if (object.runtimeType.toString() == 'Null' || 13 | object.runtimeType.toString() == 'bool') { 14 | return result; 15 | } 16 | 17 | final key = getObjectKey(object); 18 | if (_processedObjects.containsKey(key)) { 19 | result = _processedObjects[key]; 20 | result!.logUsage(level); 21 | } else { 22 | result = _processedObjects[key] = ProcessedObjectDescriptor(object); 23 | } 24 | return result; 25 | } 26 | 27 | void clear() { 28 | _processedObjects.clear(); 29 | } 30 | } -------------------------------------------------------------------------------- /mapper/build.yaml: -------------------------------------------------------------------------------- 1 | builders: 2 | dart_json_mapper: 3 | target: ":dart_json_mapper" 4 | import: "package:dart_json_mapper/builder_factory.dart" 5 | builder_factories: ["dartJsonMapperBuilder"] 6 | build_extensions: {".dart": [".mapper.g.dart"]} 7 | auto_apply: root_package 8 | build_to: source 9 | defaults: 10 | options: 11 | iterables: List, Set 12 | extension: .mapper.g.dart 13 | formatted: false 14 | generate_for: 15 | exclude: 16 | - lib/**.dart 17 | include: 18 | - benchmark/**.dart 19 | - bin/**.dart 20 | - test/_*.dart 21 | - example/**.dart 22 | - lib/main.dart 23 | - tool/**.dart 24 | - web/**.dart 25 | 26 | targets: 27 | $default: 28 | builders: 29 | dart_json_mapper: 30 | options: 31 | iterables: List, Set 32 | reflectable_builder: 33 | generate_for: 34 | - no/files -------------------------------------------------------------------------------- /mapper/lib/src/model/index/descriptors.dart: -------------------------------------------------------------------------------- 1 | /// Describes resolved property name and value 2 | class PropertyDescriptor { 3 | String name; 4 | dynamic value; 5 | bool raw; // value should be deserialized before use 6 | PropertyDescriptor(this.name, this.value, this.raw); 7 | } 8 | 9 | /// Describes an Object being processed through recursion to track cycling 10 | /// use case. Used to prevent dead loops during recursive process 11 | class ProcessedObjectDescriptor { 12 | dynamic object; 13 | Map usages = {}; // level : usagesCounter 14 | 15 | ProcessedObjectDescriptor(this.object); 16 | 17 | int get levelsCount { 18 | return usages.keys.length; 19 | } 20 | 21 | void logUsage(int level) { 22 | if (usages.containsKey(level)) { 23 | usages.update(level, (value) => ++value); 24 | } else { 25 | usages[level] = 1; 26 | } 27 | } 28 | 29 | @override 30 | String toString() { 31 | return '$object / $usages'; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /adapters/mobx/test/_test.dart: -------------------------------------------------------------------------------- 1 | library json_mapper_mobx.test; 2 | 3 | import 'package:dart_json_mapper/dart_json_mapper.dart' 4 | show 5 | SerializationOptions, 6 | jsonSerializable, 7 | JsonProperty, 8 | JsonMapper, 9 | Json, 10 | typeOf, 11 | ValueDecoratorFunction; 12 | import 'package:dart_json_mapper_mobx/dart_json_mapper_mobx.dart' 13 | show mobXAdapter; 14 | import 'package:mobx/mobx.dart' 15 | show 16 | ObservableList, 17 | ObservableSet, 18 | ObservableMap, 19 | Observable, 20 | Atom, 21 | AtomSpyReporter, 22 | ReactiveContext, 23 | Store, 24 | observable; 25 | import 'package:test/test.dart'; 26 | 27 | import '_test.mapper.g.dart' show initializeJsonMapper; 28 | 29 | part '_test.g.dart'; 30 | part 'test.observables.dart'; 31 | 32 | void main() { 33 | initializeJsonMapper(adapters: [mobXAdapter]).info(); 34 | 35 | testObservables(); 36 | } 37 | -------------------------------------------------------------------------------- /perf-test/test/starlink/json_serializable/index.dart: -------------------------------------------------------------------------------- 1 | part of 'json_serializable_test.dart'; 2 | 3 | void testStarlink(Iterable list) { 4 | final stopwatch = Stopwatch()..start(); 5 | final records = list.map((x) => Record.fromJson(x)).toList(); 6 | final deserializationMs = stopwatch.elapsedMilliseconds; 7 | final timePerRecordMs = 8 | (deserializationMs / records.length).toStringAsPrecision(2); 9 | print( 10 | 'Deserialization of ${records.length} records executed in ${deserializationMs}ms, at $timePerRecordMs ms per record'); 11 | 12 | final stopwatch2 = Stopwatch()..start(); 13 | JsonEncoder.withIndent(' ').convert(records.map((x) => x.toJson()).toList()); 14 | final serializationMs = stopwatch2.elapsedMilliseconds; 15 | final timePerRecordMs2 = 16 | (serializationMs / records.length).toStringAsPrecision(2); 17 | print( 18 | 'Serialization of ${records.length} records executed in ${serializationMs}ms, at $timePerRecordMs2 ms per record'); 19 | } 20 | -------------------------------------------------------------------------------- /perf-test/test/starlink/built_value/index.dart: -------------------------------------------------------------------------------- 1 | part of 'built_value_test.dart'; 2 | 3 | void testStarlink(Iterable list) { 4 | final stopwatch = Stopwatch()..start(); 5 | final records = list 6 | .map((x) => Record.fromJson(JsonEncoder.withIndent('').convert(x))) 7 | .toList(); 8 | final deserializationMs = stopwatch.elapsedMilliseconds; 9 | final timePerRecordMs = 10 | (deserializationMs / records.length).toStringAsPrecision(2); 11 | print( 12 | 'Deserialization of ${records.length} records executed in ${deserializationMs}ms, at $timePerRecordMs ms per record'); 13 | 14 | final stopwatch2 = Stopwatch()..start(); 15 | records.map((x) => x!.toJson()).toList(); 16 | final serializationMs = stopwatch2.elapsedMilliseconds; 17 | final timePerRecordMs2 = 18 | (serializationMs / records.length).toStringAsPrecision(2); 19 | print( 20 | 'Serialization of ${records.length} records executed in ${serializationMs}ms, at $timePerRecordMs2 ms per record'); 21 | } 22 | -------------------------------------------------------------------------------- /perf-test/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: performance_test 2 | # This package is not intended to be published 3 | publish_to: none 4 | description: > 5 | This package contains performance tests for the following JSON interoperability libraries: 6 | - JsonSerializable https://pub.dev/packages/json_serializable 7 | - BuiltValue https://pub.dev/packages/built_value 8 | - DartJsonMapper https://pub.dev/packages/dart_json_mapper 9 | And unit tests for DartJsonMapper 10 | homepage: https://github.com/k-paxian/dart-json-mapper/perf-test 11 | environment: 12 | sdk: '>=3.0.0 <4.0.0' 13 | dependencies: 14 | dart_json_mapper: 15 | json_annotation: ^4.7.0 16 | built_value: 17 | intl: 18 | unit_testing: 19 | starlink: 20 | dev_dependencies: 21 | reflectable_builder: 22 | json_serializable: 23 | built_value_generator: 24 | lints: 25 | path: 26 | build_runner: 27 | build_test: 28 | test: 29 | dependency_overrides: 30 | unit_testing: 31 | path: ../models/unit_testing 32 | starlink: 33 | path: ../models/starlink 34 | dart_json_mapper: 35 | path: ../mapper -------------------------------------------------------------------------------- /adapters/mobx/test/_test.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of '_test.dart'; 4 | 5 | // ************************************************************************** 6 | // StoreGenerator 7 | // ************************************************************************** 8 | 9 | // ignore_for_file: non_constant_identifier_names, unnecessary_brace_in_string_interps, unnecessary_lambdas, prefer_expression_function_bodies, lines_longer_than_80_chars, avoid_as, avoid_annotating_with_dynamic, no_leading_underscores_for_local_identifiers 10 | 11 | mixin _$Test on TestBase, Store { 12 | late final _$valueAtom = Atom(name: 'TestBase.value', context: context); 13 | 14 | @override 15 | String get value { 16 | _$valueAtom.reportRead(); 17 | return super.value; 18 | } 19 | 20 | @override 21 | set value(String value) { 22 | _$valueAtom.reportWrite(value, super.value, () { 23 | super.value = value; 24 | }); 25 | } 26 | 27 | @override 28 | String toString() { 29 | return ''' 30 | value: ${value} 31 | '''; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /adapters/mobx/example/example.dart: -------------------------------------------------------------------------------- 1 | library json_mapper_mobx.example; 2 | 3 | import 'package:dart_json_mapper/dart_json_mapper.dart' 4 | show JsonMapper, jsonSerializable, SerializationOptions; 5 | import 'package:dart_json_mapper_mobx/dart_json_mapper_mobx.dart' 6 | show mobXAdapter; 7 | import 'package:mobx/mobx.dart' show ObservableList; 8 | 9 | import 'example.mapper.g.dart' show initializeJsonMapper; 10 | 11 | /// Example class containing MobX type fields 12 | @jsonSerializable 13 | class MobX { 14 | ObservableList mailingList = ObservableList(); 15 | 16 | MobX(this.mailingList); 17 | } 18 | 19 | void main() { 20 | initializeJsonMapper(adapters: [mobXAdapter]); 21 | 22 | final m = MobX( 23 | ObservableList.of(['aa@test.com', 'bb@test.com', 'cc@test.com'])); 24 | final targetJson = JsonMapper.serialize(m, SerializationOptions(indent: '')); 25 | final instance = JsonMapper.deserialize(targetJson); 26 | 27 | // Serialized object 28 | print(targetJson); 29 | 30 | // Deserialize object 31 | print(instance); 32 | } 33 | -------------------------------------------------------------------------------- /models/unit_testing/lib/json.dart: -------------------------------------------------------------------------------- 1 | final String personJson = '''{ 2 | "skills": [ 3 | "Go", 4 | "Dart", 5 | "Flutter" 6 | ], 7 | "specialDates": [ 8 | "2013-02-28 00:00:00.000", 9 | "2023-02-28 00:00:00.000", 10 | "2003-02-28 00:00:00.000" 11 | ], 12 | "last_promotion_date": "05-13-2008 22:33:44", 13 | "hire_date": "02/28/2003", 14 | "active": true, 15 | "name": "Forest", 16 | "salary": "1200000.25", 17 | "dob": null, 18 | "age": 36, 19 | "lastName": "Gump", 20 | "dyn": "dyn", 21 | "dynNum": 9, 22 | "dynBool": false, 23 | "properties": { 24 | "first": "partridge", 25 | "cash": 23000, 26 | "required": true 27 | }, 28 | "map": { 29 | "first": "partridge", 30 | "cash": 23000, 31 | "required": true 32 | }, 33 | "sym": "foo", 34 | "favouriteColours": [ 35 | "black", 36 | "white" 37 | ], 38 | "eye_color": "blue", 39 | "hairColor": 5, 40 | "vehicles": [ 41 | { 42 | "modelName": "Tesla", 43 | "color": "black" 44 | }, 45 | { 46 | "modelName": "BMW", 47 | "color": "red" 48 | } 49 | ], 50 | "fullName": "Forest Gump" 51 | }'''; 52 | -------------------------------------------------------------------------------- /adapters/fixnum/example/example.dart: -------------------------------------------------------------------------------- 1 | library json_mapper_fixnum.example; 2 | 3 | import 'package:dart_json_mapper/dart_json_mapper.dart' 4 | show JsonMapper, jsonSerializable, SerializationOptions; 5 | import 'package:dart_json_mapper_fixnum/dart_json_mapper_fixnum.dart' 6 | show fixnumAdapter; 7 | import 'package:fixnum/fixnum.dart' show Int32; 8 | 9 | import 'example.mapper.g.dart' show initializeJsonMapper; 10 | 11 | @jsonSerializable 12 | class Int32IntData { 13 | Int32 int32; 14 | 15 | Int32IntData(this.int32); 16 | } 17 | 18 | void main() { 19 | initializeJsonMapper(adapters: [fixnumAdapter]); 20 | 21 | // given 22 | final rawString = '1234567890'; 23 | final json = '{"int32":"$rawString"}'; 24 | 25 | // when 26 | final targetJson = JsonMapper.serialize( 27 | Int32IntData(Int32.parseInt(rawString)), 28 | SerializationOptions(indent: '')); 29 | 30 | // Serialized object 31 | print(targetJson); 32 | 33 | // when 34 | final target = JsonMapper.deserialize(json); 35 | 36 | // Deserialize object 37 | print(target!.int32.toString()); 38 | } 39 | -------------------------------------------------------------------------------- /mapper/lib/src/model/converters/enum_converter.dart: -------------------------------------------------------------------------------- 1 | import '../index.dart'; 2 | 3 | final enumConverter = EnumConverter(); 4 | 5 | /// Long converter for [enum] type 6 | class EnumConverter implements ICustomConverter, ICustomEnumConverter { 7 | EnumConverter() : super(); 8 | 9 | IEnumDescriptor? _enumDescriptor; 10 | 11 | @override 12 | Object? fromJSON(dynamic jsonValue, DeserializationContext context) { 13 | dynamic convert(value) => _enumDescriptor!.values.firstWhere( 14 | (eValue) => eValue.toString() == value.toString(), 15 | orElse: () => null); 16 | return jsonValue is Iterable 17 | ? jsonValue.map(convert).toList() 18 | : convert(jsonValue); 19 | } 20 | 21 | @override 22 | dynamic toJSON(Object? object, SerializationContext context) { 23 | dynamic convert(value) => value.toString(); 24 | return (object is Iterable) 25 | ? object.map(convert).toList() 26 | : convert(object); 27 | } 28 | 29 | @override 30 | void setEnumDescriptor(IEnumDescriptor? enumDescriptor) { 31 | _enumDescriptor = enumDescriptor; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /perf-test/test/unit/test.mixins.dart: -------------------------------------------------------------------------------- 1 | import 'package:dart_json_mapper/dart_json_mapper.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | @Json(discriminatorProperty: 'type') 5 | @jsonSerializable 6 | abstract class A {} 7 | 8 | @jsonSerializable 9 | mixin B on A {} 10 | 11 | @jsonSerializable 12 | class C extends A with B {} 13 | 14 | @jsonSerializable 15 | class MixinContainer { 16 | final Set ints; 17 | final B b; 18 | 19 | const MixinContainer(this.ints, this.b); 20 | } 21 | 22 | void testMixinCases() { 23 | group('[Verify Mixin cases]', () { 24 | test('class C extends A with B', () { 25 | // given 26 | final json = r'''{"ints":[1,2,3],"b":{"type":"C"}}'''; 27 | final instance = MixinContainer( 28 | {1, 2, 3}, 29 | C(), 30 | ); 31 | 32 | // when 33 | final targetJson = JsonMapper.serialize(instance); 34 | final target = JsonMapper.deserialize(targetJson)!; 35 | 36 | // then 37 | expect(targetJson, json); 38 | expect(target, TypeMatcher()); 39 | expect(target.b, TypeMatcher()); 40 | }); 41 | }); 42 | } 43 | -------------------------------------------------------------------------------- /perf-test/test/unit/test.cache_manager.dart: -------------------------------------------------------------------------------- 1 | import 'package:dart_json_mapper/src/logic/cache_manager.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void testCacheManager() { 5 | group('CacheManager', () { 6 | late CacheManager cacheManager; 7 | 8 | setUp(() { 9 | cacheManager = CacheManager(); 10 | }); 11 | 12 | test('should cache and retrieve processed objects', () { 13 | final object = Object(); 14 | final processedObject = cacheManager.getObjectProcessed(object, 0); 15 | expect(processedObject, isNotNull); 16 | final cachedObject = cacheManager.getObjectProcessed(object, 1); 17 | expect(cachedObject, same(processedObject)); 18 | }); 19 | 20 | test('should not cache null or bool objects', () { 21 | expect(cacheManager.getObjectProcessed(true, 0), isNull); 22 | // expect(cacheManager.getObjectProcessed(null, 0), isNull); 23 | }); 24 | 25 | test('should clear the cache', () { 26 | final object = Object(); 27 | cacheManager.getObjectProcessed(object, 0); 28 | cacheManager.clear(); 29 | final processedObject = cacheManager.getObjectProcessed(object, 0); 30 | expect(processedObject, isNotNull); 31 | }); 32 | }); 33 | } -------------------------------------------------------------------------------- /adapters/mobx/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 2.0.5 2 | 3 | * Update mapper adapter contract to latest 4 | 5 | ## 2.0.4 6 | 7 | * Update mapper adapter contract to latest 8 | 9 | ## 2.0.3 10 | 11 | * Align with the latest mobx version 12 | * replace pedantic by lints 13 | 14 | ## 2.0.2 15 | 16 | * Align with the latest mapper version 17 | 18 | ## 2.0.1 19 | 20 | * Support for new code converters contract 21 | 22 | ## 2.0.0 23 | 24 | * mobx 2.0.0-nullsafety.5 support 25 | 26 | ## 1.2.3 27 | 28 | * Support for new code converters contract 29 | 30 | ## 1.2.2 31 | 32 | * Support for new code generation contract 33 | 34 | ## 1.2.1 35 | 36 | * Converter for ObservableMap w/o decorators, when Map is pre-initialized 37 | 38 | ## 1.2.0 39 | 40 | * Support for Observable iterables, w/o decorators 41 | 42 | ## 1.1.0 43 | 44 | * Support for new adapters contract 45 | * mobx version bump 46 | 47 | 48 | ## 1.0.1 49 | 50 | * mobx version bump 51 | 52 | ## 1.0.0 53 | 54 | * pedantic linter adopted 55 | 56 | ## 0.1.0 57 | 58 | * Added support for Observable, ObservableList, ObservableSet, ObservableMap 59 | 60 | ## 0.0.1 61 | 62 | * Added support for ObservableList\, where T in 63 | ```dart 64 | [String, bool, num, int, double, DateTime] 65 | ``` 66 | -------------------------------------------------------------------------------- /perf-test/test/unit/test.adapter_manager.dart: -------------------------------------------------------------------------------- 1 | import 'package:dart_json_mapper/dart_json_mapper.dart'; 2 | import 'package:dart_json_mapper/src/logic/adapter_manager.dart'; 3 | import 'package:test/test.dart'; 4 | 5 | void testAdapterManager() { 6 | group('AdapterManager', () { 7 | late AdapterManager adapterManager; 8 | 9 | setUp(() { 10 | adapterManager = AdapterManager(); 11 | }); 12 | 13 | test('should register and remove adapters', () { 14 | final adapter = JsonMapperAdapter(); 15 | adapterManager.use(adapter); 16 | expect(adapterManager.allEnumValues, isEmpty); 17 | adapterManager.remove(adapter); 18 | expect(adapterManager.allEnumValues, isEmpty); 19 | }); 20 | 21 | test('should enumerate adapters in the correct order', () { 22 | final adapter1 = JsonMapperAdapter(title: 'Adapter 1'); 23 | final adapter2 = JsonMapperAdapter(title: 'Adapter 2'); 24 | adapterManager.use(adapter1, 1); 25 | adapterManager.use(adapter2, 0); 26 | 27 | final enumeratedAdapters = []; 28 | adapterManager.enumerate((adapter) { 29 | enumeratedAdapters.add(adapter); 30 | }); 31 | 32 | expect(enumeratedAdapters.map((a) => a.title).toList(), 33 | ['Adapter 2', 'Adapter 1']); 34 | }); 35 | }); 36 | } -------------------------------------------------------------------------------- /models/starlink/lib/model.dart: -------------------------------------------------------------------------------- 1 | import 'package:dart_json_mapper/dart_json_mapper.dart' 2 | show jsonSerializable, Json, CaseStyle, JsonProperty; 3 | 4 | @jsonSerializable 5 | @Json(caseStyle: CaseStyle.snakeAllCaps) 6 | class SpaceTrack { 7 | String? ccsdsOmmVers, 8 | comment, 9 | originator, 10 | objectName, 11 | objectId, 12 | objectType, 13 | centerName, 14 | refFrame, 15 | timeSystem, 16 | meanElementTheory, 17 | classificationType, 18 | rcsSize, 19 | countryCode, 20 | site, 21 | tleLine0, 22 | tleLine1, 23 | tleLine2; 24 | 25 | num? meanMotion, 26 | eccentricity, 27 | raOfAscNode, 28 | argOfPericenter, 29 | meanAnomaly, 30 | ephemerisType, 31 | noradCatId, 32 | elementSetNo, 33 | revAtEpoch, 34 | bstar, 35 | meanMotionDot, 36 | meanMotionDdot, 37 | semimajorAxis, 38 | period, 39 | apoapsis, 40 | periapsis, 41 | decayed, 42 | file, 43 | gpId; 44 | 45 | DateTime? decayDate, creationDate, epoch; 46 | 47 | @JsonProperty(converterParams: {'format': 'yyyy-MM-dd'}) 48 | DateTime? launchDate; 49 | } 50 | 51 | @jsonSerializable 52 | class Record { 53 | SpaceTrack? spaceTrack; 54 | String? version, id, launch; 55 | } 56 | -------------------------------------------------------------------------------- /mapper/lib/src/model/converters/date_converter.dart: -------------------------------------------------------------------------------- 1 | import 'package:intl/intl.dart'; 2 | 3 | import '../index.dart'; 4 | 5 | const dateConverter = DateConverter(); 6 | 7 | /// Default converter for [DateTime] type 8 | class DateConverter extends BaseCustomConverter implements ICustomConverter { 9 | const DateConverter() : super(); 10 | 11 | @override 12 | Object? fromJSON(dynamic jsonValue, DeserializationContext context) { 13 | final format = getDateFormat(context.jsonPropertyMeta); 14 | 15 | if (jsonValue is String) { 16 | return format != null 17 | ? format.parse(jsonValue) 18 | : DateTime.parse(jsonValue); 19 | } 20 | 21 | return jsonValue; 22 | } 23 | 24 | @override 25 | dynamic toJSON(Object? object, SerializationContext context) { 26 | final format = getDateFormat(context.jsonPropertyMeta); 27 | return format != null && object != null && object is! String 28 | ? format.format(object as DateTime) 29 | : (object is List) 30 | ? object.map((item) => item.toString()).toList() 31 | : object?.toString(); 32 | } 33 | 34 | DateFormat? getDateFormat([JsonProperty? jsonProperty]) { 35 | final String? format = getConverterParameter('format', jsonProperty); 36 | return format != null ? DateFormat(format) : null; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /mapper/lib/src/model/converters/number_converter.dart: -------------------------------------------------------------------------------- 1 | import 'package:intl/intl.dart'; 2 | 3 | import '../index.dart'; 4 | 5 | const numberConverter = NumberConverter(); 6 | 7 | /// Default converter for [num] type 8 | class NumberConverter extends BaseCustomConverter implements ICustomConverter { 9 | const NumberConverter() : super(); 10 | 11 | @override 12 | Object? fromJSON(dynamic jsonValue, DeserializationContext context) { 13 | final format = getNumberFormat(context.jsonPropertyMeta); 14 | return format != null && (jsonValue is String) 15 | ? getNumberFormat(context.jsonPropertyMeta)!.parse(jsonValue) 16 | : (jsonValue is String) 17 | ? num.tryParse(jsonValue) ?? jsonValue 18 | : jsonValue; 19 | } 20 | 21 | @override 22 | dynamic toJSON(Object? object, SerializationContext context) { 23 | final format = getNumberFormat(context.jsonPropertyMeta); 24 | return object != null && format != null 25 | ? getNumberFormat(context.jsonPropertyMeta)!.format(object) 26 | : (object is String) 27 | ? num.tryParse(object) 28 | : object; 29 | } 30 | 31 | NumberFormat? getNumberFormat([JsonProperty? jsonProperty]) { 32 | final String? format = getConverterParameter('format', jsonProperty); 33 | return format != null ? NumberFormat(format) : null; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /mapper/lib/src/builder/change_analyzer.dart: -------------------------------------------------------------------------------- 1 | import 'package:analyzer/dart/element/element.dart'; 2 | 3 | import 'comparable_class_element.dart'; 4 | import 'library_visitor.dart'; 5 | 6 | class ChangeAnalyzer { 7 | LibraryVisitor visitorA; 8 | LibraryVisitor? visitorB; 9 | 10 | ChangeAnalyzer(this.visitorA, this.visitorB); 11 | 12 | Map getClassesMap( 13 | Iterable classes) => 14 | classes.fold({}, (value, element) { 15 | value[element.getDisplayString()] = ComparableClassElement(element); 16 | return value; 17 | }); 18 | 19 | bool get hasChanges { 20 | final classElementsA = visitorA.visitedPublicAnnotatedClassElements; 21 | final classElementsB = visitorB!.visitedPublicAnnotatedClassElements; 22 | 23 | final annotatedClassesCountChanged = 24 | classElementsA.length != classElementsB.length; 25 | late bool anyAnnotatedClassChanged; 26 | 27 | if (!annotatedClassesCountChanged) { 28 | final classesMapA = getClassesMap(classElementsA.values); 29 | final classesMapB = getClassesMap(classElementsB.values); 30 | anyAnnotatedClassChanged = classesMapA.keys 31 | .map((className) => classesMapA[className] != classesMapB[className]) 32 | .fold(false, (dynamic value, element) => value || element); 33 | } 34 | 35 | return annotatedClassesCountChanged || anyAnnotatedClassChanged; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /adapters/flutter/README.md: -------------------------------------------------------------------------------- 1 | [![pub package](https://img.shields.io/pub/v/dart_json_mapper_flutter.svg)](https://pub.dartlang.org/packages/dart_json_mapper_flutter) 2 | 3 | This is a [dart-json-mapper][1] complementary package provides support for https://github.com/flutter/flutter types in order to serialize / deserialize them from / to JSON. 4 | 5 | ## Basic setup 6 | 7 | Beforehand please consult with basic setup section from [dart-json-mapper][1] package. 8 | 9 | Please add the following dependencies to your `pubspec.yaml`: 10 | 11 | ```yaml 12 | dependencies: 13 | dart_json_mapper: 14 | dart_json_mapper_flutter: 15 | dev_dependencies: 16 | build_runner: 17 | ``` 18 | 19 | Usage example 20 | **lib/main.dart** 21 | ```dart 22 | import 'dart:ui' show Color; 23 | import 'package:dart_json_mapper/dart_json_mapper.dart' show JsonMapper, jsonSerializable; 24 | import 'package:dart_json_mapper_flutter/dart_json_mapper_flutter.dart' show flutterAdapter; 25 | 26 | import 'main.mapper.g.dart' show initializeJsonMapper; 27 | 28 | @jsonSerializable 29 | class FlutterClass { 30 | Color color; 31 | 32 | FlutterClass(this.color); 33 | } 34 | 35 | void main() { 36 | initializeJsonMapper(adapters: [flutterAdapter]); 37 | 38 | print(JsonMapper.serialize( 39 | FlutterClass(Color(0x003f4f5f)) 40 | )); 41 | } 42 | ``` 43 | output: 44 | ```json 45 | { 46 | "color": "#003F4F5F" 47 | } 48 | ``` 49 | 50 | [1]: https://github.com/k-paxian/dart-json-mapper -------------------------------------------------------------------------------- /adapters/fixnum/README.md: -------------------------------------------------------------------------------- 1 | [![pub package](https://img.shields.io/pub/v/dart_json_mapper_fixnum.svg)](https://pub.dartlang.org/packages/dart_json_mapper_fixnum) 2 | 3 | This is a [dart-json-mapper][1] complementary package provides support for https://pub.dev/packages/fixnum types in order to serialize / deserialize them from / to JSON. 4 | 5 | ## Basic setup 6 | 7 | Beforehand please consult with basic setup section from [dart-json-mapper][1] package. 8 | 9 | Please add the following dependencies to your `pubspec.yaml`: 10 | 11 | ```yaml 12 | dependencies: 13 | dart_json_mapper: 14 | dart_json_mapper_fixnum: 15 | dev_dependencies: 16 | build_runner: 17 | ``` 18 | 19 | Usage example 20 | **lib/main.dart** 21 | ```dart 22 | import 'package:fixnum/fixnum.dart' show Int32; 23 | import 'package:dart_json_mapper/dart_json_mapper.dart' show JsonMapper, jsonSerializable; 24 | import 'package:dart_json_mapper_fixnum/dart_json_mapper_fixnum.dart' show fixnumAdapter; 25 | 26 | import 'main.mapper.g.dart' show initializeJsonMapper; 27 | 28 | @jsonSerializable 29 | class FixnumClass { 30 | Int32 integer32; 31 | 32 | FixnumClass(this.integer32); 33 | } 34 | 35 | void main() { 36 | initializeJsonMapper(adapters: [fixnumAdapter]); 37 | 38 | print(JsonMapper.serialize( 39 | FixnumClass(Int32(1234567890)) 40 | )); 41 | } 42 | ``` 43 | output: 44 | ```json 45 | { 46 | "integer32": 1234567890 47 | } 48 | ``` 49 | 50 | [1]: https://github.com/k-paxian/dart-json-mapper -------------------------------------------------------------------------------- /perf-test/test/starlink/built_value/built_value_test.dart: -------------------------------------------------------------------------------- 1 | library perf_test.test; 2 | 3 | import 'dart:convert' show json, JsonEncoder; 4 | import 'dart:io' show File; 5 | 6 | import 'package:built_value/built_value.dart'; 7 | import 'package:built_value/iso_8601_date_time_serializer.dart'; 8 | import 'package:built_value/serializer.dart'; 9 | import 'package:built_value/standard_json_plugin.dart'; 10 | import 'package:path/path.dart' as path; 11 | 12 | part './index.dart'; 13 | part './model.dart'; 14 | part 'built_value_test.g.dart'; 15 | 16 | /// Example of how to use built_value serialization. 17 | /// 18 | /// Declare a top level [Serializers] field called serializers. Annotate it 19 | /// with [SerializersFor] and provide a `const` `List` of types you want to 20 | /// be serializable. 21 | /// 22 | /// The built_value code generator will provide the implementation. It will 23 | /// contain serializers for all the types asked for explicitly plus all the 24 | /// types needed transitively via fields. 25 | /// 26 | /// You usually only need to do this once per project. 27 | @SerializersFor([SpaceTrack, Record]) 28 | final Serializers serializers = (_$serializers.toBuilder() 29 | ..add(Iso8601DateTimeSerializer()) 30 | ..addPlugin(StandardJsonPlugin())) 31 | .build(); 32 | 33 | void main() async { 34 | print('\n>> built_value'); 35 | testStarlink(json.decode( 36 | await File(path.absolute('test/starlink/starlink.json')).readAsString())); 37 | } 38 | -------------------------------------------------------------------------------- /perf-test/test/unit/test.converters.caching.dart: -------------------------------------------------------------------------------- 1 | import 'package:dart_json_mapper/dart_json_mapper.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | const myCustomConverter = _MyCustomConverter(); 5 | 6 | class _MyCustomConverter implements ICustomConverter { 7 | static int callsCount = 0; 8 | const _MyCustomConverter(); 9 | 10 | @override 11 | String? fromJSON(dynamic jsonValue, [DeserializationContext? context]) { 12 | callsCount++; 13 | if (jsonValue is int) return jsonValue.toString(); 14 | if (jsonValue is String) return jsonValue; 15 | return null; 16 | } 17 | 18 | @override 19 | dynamic toJSON(String? object, [SerializationContext? context]) { 20 | throw UnimplementedError(); 21 | } 22 | } 23 | 24 | @jsonSerializable 25 | class UserX { 26 | final int id; 27 | 28 | @JsonProperty(converter: myCustomConverter) 29 | final String type; 30 | 31 | const UserX(this.id, this.type); 32 | } 33 | 34 | void testConvertersCaching() { 35 | group('[Verify Custom converters results caching]', () { 36 | test('converter should be called once', () { 37 | // given 38 | 39 | // when 40 | JsonMapper.deserialize('''{"id": 42, "type": "sudoer"}'''); 41 | JsonMapper.deserialize('''{"id": 42, "type": "sudoer"}'''); 42 | JsonMapper.deserialize('''{"id": 42, "type": "sudoer"}'''); 43 | 44 | // then 45 | expect(_MyCustomConverter.callsCount, 1); 46 | }); 47 | }); 48 | } 49 | -------------------------------------------------------------------------------- /mapper/lib/src/logic/reflection_handler.dart: -------------------------------------------------------------------------------- 1 | import 'package:reflectable/reflectable.dart' 2 | show 3 | ClassMirror, 4 | InstanceMirror, 5 | DeclarationMirror, 6 | VariableMirror, 7 | MethodMirror; 8 | 9 | import '../model/annotations.dart'; 10 | 11 | class ReflectionHandler { 12 | static const _serializable = JsonSerializable(); 13 | 14 | static InstanceMirror? safeGetInstanceMirror(Object object) { 15 | InstanceMirror? result; 16 | try { 17 | result = _serializable.reflect(object); 18 | } catch (error) { 19 | return result; 20 | } 21 | return result; 22 | } 23 | 24 | static Type getDeclarationType(DeclarationMirror mirror) { 25 | Type? result = dynamic; 26 | VariableMirror variable; 27 | MethodMirror method; 28 | 29 | try { 30 | variable = mirror as VariableMirror; 31 | result = variable.hasReflectedType ? variable.reflectedType : null; 32 | } catch (error) { 33 | result = result; 34 | } 35 | 36 | try { 37 | method = mirror as MethodMirror; 38 | result = 39 | method.hasReflectedReturnType ? method.reflectedReturnType : null; 40 | } catch (error) { 41 | result = result; 42 | } 43 | 44 | return result ??= dynamic; 45 | } 46 | 47 | static void enumerateAnnotatedClasses(Function(ClassMirror) visitor) { 48 | for (var classMirror in _serializable.annotatedClasses) { 49 | visitor(classMirror); 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /adapters/built/README.md: -------------------------------------------------------------------------------- 1 | [![pub package](https://img.shields.io/pub/v/dart_json_mapper_built.svg)](https://pub.dartlang.org/packages/dart_json_mapper_built) 2 | 3 | This is a [dart-json-mapper][1] complementary package provides support for https://pub.dev/packages/built_collection types in order to serialize / deserialize them from / to JSON. 4 | 5 | ## Basic setup 6 | 7 | Beforehand please consult with basic setup section from [dart-json-mapper][1] package. 8 | 9 | Please add the following dependencies to your `pubspec.yaml`: 10 | 11 | ```yaml 12 | dependencies: 13 | dart_json_mapper: 14 | dart_json_mapper_built: 15 | dev_dependencies: 16 | build_runner: 17 | ``` 18 | 19 | Usage example 20 | **lib/main.dart** 21 | ```dart 22 | import 'package:built_collection/built_collection.dart'; 23 | import 'package:dart_json_mapper/dart_json_mapper.dart' show JsonMapper, jsonSerializable; 24 | import 'package:dart_json_mapper_built/dart_json_mapper_built.dart' show builtAdapter; 25 | 26 | import 'main.mapper.g.dart' show initializeJsonMapper; 27 | 28 | @jsonSerializable 29 | class ImmutableClass { 30 | final BuiltList list; 31 | 32 | const ImmutableClass(this.list); 33 | } 34 | 35 | void main() { 36 | initializeJsonMapper(adapters: [builtAdapter]); 37 | 38 | print(JsonMapper.serialize( 39 | ImmutableClass(BuiltList.of([1, 2, 3])) 40 | )); 41 | } 42 | ``` 43 | output: 44 | ```json 45 | { 46 | "list": [1,2,3] 47 | } 48 | ``` 49 | 50 | [1]: https://github.com/k-paxian/dart-json-mapper -------------------------------------------------------------------------------- /mapper/lib/src/model/converters/default_converter.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show JsonEncoder; 2 | 3 | import '../index.dart'; 4 | 5 | const defaultConverter = DefaultConverter(); 6 | 7 | /// Default converter for all types 8 | class DefaultConverter implements ICustomConverter { 9 | const DefaultConverter() : super(); 10 | 11 | @override 12 | Object? fromJSON(dynamic jsonValue, DeserializationContext context) { 13 | final jsonProperty = context.jsonPropertyMeta; 14 | final typeInfo = context.typeInfo; 15 | 16 | if (jsonProperty?.rawJson == true && typeInfo?.type == String) { 17 | if (jsonValue == null) { 18 | return null; 19 | } 20 | if (jsonValue is Map || jsonValue is List) { 21 | return JsonEncoder().convert(jsonValue); 22 | } 23 | return jsonValue.toString(); 24 | } else { 25 | // If this DefaultConverter is specifically handling a String type (even if not rawJson) 26 | if (typeInfo?.type == String) { 27 | if (jsonValue == null) { 28 | return null; 29 | } 30 | // For non-rawJson strings, ensure it's robustly converted to string. 31 | // Original strict: return jsonValue as String?; 32 | return jsonValue.toString(); 33 | } 34 | // Original pass-through logic for other types this DefaultConverter might handle 35 | return jsonValue; 36 | } 37 | } 38 | 39 | @override 40 | dynamic toJSON(Object? object, SerializationContext context) => object; 41 | } 42 | -------------------------------------------------------------------------------- /adapters/mobx/README.md: -------------------------------------------------------------------------------- 1 | [![pub package](https://img.shields.io/pub/v/dart_json_mapper_mobx.svg)](https://pub.dartlang.org/packages/dart_json_mapper_mobx) 2 | 3 | This is a [dart-json-mapper][1] complementary package provides support for MobX.dart classes in order to serialize / deserialize them from / to JSON. 4 | 5 | ## Basic setup 6 | 7 | Beforehand please consult with basic setup section from [dart-json-mapper][1] package. 8 | 9 | Please add the following dependencies to your `pubspec.yaml`: 10 | 11 | ```yaml 12 | dependencies: 13 | dart_json_mapper: 14 | dart_json_mapper_mobx: 15 | dev_dependencies: 16 | build_runner: 17 | ``` 18 | 19 | Usage example 20 | **lib/main.dart** 21 | ```dart 22 | import 'package:mobx/mobx.dart' show ObservableList; 23 | import 'package:dart_json_mapper/dart_json_mapper.dart' show JsonMapper, jsonSerializable; 24 | import 'package:dart_json_mapper_mobx/dart_json_mapper_mobx.dart' show mobXAdapter; 25 | 26 | import 'main.mapper.g.dart' show initializeJsonMapper; 27 | 28 | @jsonSerializable 29 | class MyMobXClass { 30 | ObservableList mailingList = ObservableList(); 31 | 32 | MyMobXClass(this.mailingList); 33 | } 34 | 35 | void main() { 36 | initializeJsonMapper(adapters: [mobXAdapter]); 37 | 38 | print(JsonMapper.serialize( 39 | MyMobXClass(ObservableList.of(['aa@test.com', 'bb@test.com', 'cc@test.com'])) 40 | )); 41 | } 42 | ``` 43 | output: 44 | ```json 45 | { 46 | "mailingList": ["aa@test.com","bb@test.com","cc@test.com"] 47 | } 48 | ``` 49 | 50 | [1]: https://github.com/k-paxian/dart-json-mapper -------------------------------------------------------------------------------- /mapper/LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2018-2025, Alexander Mazuruk 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 | -------------------------------------------------------------------------------- /mapper/lib/src/model/enum.dart: -------------------------------------------------------------------------------- 1 | /// Virtual class 2 | /// Used as a generic reference to all Enum based types 3 | /// enum ABC {A, B, C}, etc. 4 | abstract class Enum {} 5 | 6 | /// Enum descriptor, defines Enum possible values, mappings, defaultValue, case sensitivity, etc 7 | abstract class IEnumDescriptor { 8 | Iterable values = []; 9 | dynamic defaultValue; 10 | bool? caseInsensitive; 11 | Map mapping = {}; 12 | } 13 | 14 | /// Enum descriptor, defines Enum possible values, mappings, defaultValue, case sensitivity, etc 15 | class EnumDescriptor implements IEnumDescriptor { 16 | /// Defines a mapping for enum values, key is the enum value, value is the target mapping value 17 | /// Example: 18 | /// ```dart 19 | /// EnumDescriptor( 20 | /// values: RecordType.values, 21 | /// mapping: { 22 | /// RecordType.asset: 'Asset', 23 | /// RecordType.series: 'Series' 24 | /// }) 25 | /// ``` 26 | @override 27 | Map mapping; 28 | 29 | /// Defines possible enum values 30 | /// Example: 31 | /// EnumDescriptor(values: RecordType.values) 32 | @override 33 | Iterable values; 34 | 35 | /// Defines possible enum values 36 | /// Example: 37 | /// EnumDescriptor(defaultValue: RecordType.asset) 38 | @override 39 | dynamic defaultValue; 40 | 41 | /// Defines case sensitivity for string based enum values 42 | /// Example: 43 | /// EnumDescriptor(values: RecordType.values, caseInsensitive: true) 44 | @override 45 | bool? caseInsensitive; 46 | 47 | EnumDescriptor( 48 | {this.values = const [], 49 | this.mapping = const {}, 50 | this.defaultValue, 51 | this.caseInsensitive}); 52 | } 53 | -------------------------------------------------------------------------------- /mapper/lib/src/model/converters/enum_converter_numeric.dart: -------------------------------------------------------------------------------- 1 | import '../index.dart'; 2 | 3 | const enumConverterNumeric = ConstEnumConverterNumeric(); 4 | 5 | /// Const wrapper for [EnumConverterNumeric] 6 | class ConstEnumConverterNumeric 7 | implements ICustomConverter, ICustomEnumConverter { 8 | const ConstEnumConverterNumeric(); 9 | 10 | @override 11 | Object? fromJSON(jsonValue, DeserializationContext context) => 12 | _enumConverterNumeric.fromJSON(jsonValue, context); 13 | 14 | @override 15 | dynamic toJSON(object, SerializationContext context) => 16 | _enumConverterNumeric.toJSON(object, context); 17 | 18 | @override 19 | void setEnumDescriptor(IEnumDescriptor? enumDescriptor) { 20 | _enumConverterNumeric.setEnumDescriptor(enumDescriptor); 21 | } 22 | } 23 | 24 | final _enumConverterNumeric = EnumConverterNumeric(); 25 | 26 | /// Numeric index based converter for [enum] type 27 | class EnumConverterNumeric implements ICustomConverter, ICustomEnumConverter { 28 | EnumConverterNumeric() : super(); 29 | 30 | IEnumDescriptor? _enumDescriptor; 31 | 32 | @override 33 | Object? fromJSON(dynamic jsonValue, DeserializationContext context) { 34 | return jsonValue is int 35 | ? jsonValue < _enumDescriptor!.values.length && jsonValue >= 0 36 | ? (_enumDescriptor!.values as List)[jsonValue] 37 | : _enumDescriptor!.defaultValue 38 | : jsonValue; 39 | } 40 | 41 | @override 42 | dynamic toJSON(Object? object, SerializationContext context) { 43 | final valueIndex = (_enumDescriptor!.values as List).indexOf(object); 44 | return valueIndex >= 0 ? valueIndex : _enumDescriptor!.defaultValue; 45 | } 46 | 47 | @override 48 | void setEnumDescriptor(IEnumDescriptor? enumDescriptor) { 49 | _enumDescriptor = enumDescriptor; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /perf-test/test/unit/test_issue_225.dart: -------------------------------------------------------------------------------- 1 | import 'package:dart_json_mapper/dart_json_mapper.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | @jsonSerializable 5 | class PageImpl { 6 | List? content; 7 | bool? last; 8 | int? totalPages; 9 | int? totalElements; 10 | bool? first; 11 | int? size; 12 | int? number; 13 | int? numberOfElements; 14 | bool? empty; 15 | } 16 | 17 | @jsonSerializable 18 | class Advertising { 19 | String? title; 20 | double? price; 21 | int? quantity; 22 | String? description; 23 | List? images; 24 | List? sourceImages; 25 | String? sourceId; 26 | String? sourceUrl; 27 | } 28 | 29 | @jsonSerializable 30 | class AdvertisingPage extends PageImpl { 31 | @override 32 | List? content = []; 33 | } 34 | 35 | void testIssue225() { 36 | group('Issue 225', () { 37 | test('should deserialize generic list correctly', () { 38 | const json = ''' 39 | { 40 | "content":[ 41 | { 42 | "id":25438, 43 | "created":"2024-07-04T18:46:31.048683Z", 44 | "updated":"2024-07-04T20:45:00.030320Z", 45 | "title":"SCOOTER HOVERBOARD BATERIA" 46 | } 47 | ], 48 | "last":false, 49 | "totalPages":23962, 50 | "totalElements":23962, 51 | "first":true, 52 | "size":1, 53 | "number":0, 54 | "numberOfElements":1, 55 | "empty":false 56 | } 57 | '''; 58 | final page = JsonMapper.deserialize(json); 59 | expect(page, isA()); 60 | expect(page?.content, isA>()); 61 | expect(page?.content?.first, isA()); 62 | expect(page?.content?.first.title, 'SCOOTER HOVERBOARD BATERIA'); 63 | }); 64 | }); 65 | } -------------------------------------------------------------------------------- /mapper/lib/src/logic/type_info_handler.dart: -------------------------------------------------------------------------------- 1 | import 'package:collection/collection.dart' show IterableExtension; 2 | 3 | import '../class_info.dart'; 4 | import '../mapper.dart'; 5 | import '../model/index.dart'; 6 | 7 | class TypeInfoHandler { 8 | final JsonMapper _mapper; 9 | 10 | TypeInfoHandler(this._mapper); 11 | 12 | TypeInfo getDeclarationTypeInfo(Type declarationType, Type? valueType) => 13 | getTypeInfo((declarationType == dynamic && valueType != null) 14 | ? valueType 15 | : declarationType); 16 | 17 | TypeInfo getTypeInfo(Type type) { 18 | if (_mapper.typeInfoCache[type] != null) { 19 | return _mapper.typeInfoCache[type]!; 20 | } 21 | var result = TypeInfo(type); 22 | for (var decorator in _mapper.typeInfoDecorators.values) { 23 | decorator.init(_mapper.classes, _mapper.valueDecorators, _mapper.enumValues); 24 | result = decorator.decorate(result); 25 | } 26 | if (_mapper.mixins[result.typeName] != null) { 27 | result.mixinType = _mapper.mixins[result.typeName]!.reflectedType; 28 | } 29 | _mapper.typeInfoCache[type] = result; 30 | return result; 31 | } 32 | 33 | Type? getGenericParameterTypeByIndex(num parameterIndex, TypeInfo genericType) => 34 | genericType.isGeneric && 35 | genericType.parameters.length - 1 >= parameterIndex 36 | ? genericType.parameters.elementAt(parameterIndex as int) 37 | : null; 38 | 39 | Type? getTypeByStringName(String? typeName) => 40 | _mapper.classes.keys.firstWhereOrNull((t) => t.toString() == typeName); 41 | 42 | String? getDiscriminatorProperty( 43 | ClassInfo classInfo, DeserializationOptions? options) => 44 | classInfo 45 | .getMetaWhere((Json meta) => meta.discriminatorProperty != null, 46 | options?.scheme) 47 | ?.discriminatorProperty; 48 | } -------------------------------------------------------------------------------- /perf-test/test/unit/test_issue_234.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'package:dart_json_mapper/dart_json_mapper.dart'; 3 | import 'package:test/test.dart'; 4 | 5 | @JsonSerializable() 6 | @Json(caseStyle: CaseStyle.pascal, ignoreNullMembers: true) 7 | class DTDeviceStatus { 8 | String? deviceIdent; 9 | List gatewayConnections = []; 10 | } 11 | 12 | @JsonSerializable() 13 | @Json(caseStyle: CaseStyle.pascal, ignoreNullMembers: true) 14 | class DTGatewayConnection { 15 | String gwIdent = ''; 16 | DTSignalStrength? signalStrength; 17 | } 18 | 19 | @JsonSerializable() 20 | @Json(ignoreNullMembers: true) 21 | class DTSignalStrength { 22 | @JsonProperty(name: 'Strength') 23 | String strength = 'NoSignal'; 24 | 25 | @JsonProperty(name: 'RSSI') 26 | int? rssi; 27 | 28 | @JsonProperty(name: 'SpreadFactor') 29 | int? spreadFactor; 30 | } 31 | 32 | void testIssue234() { 33 | group('Issue 234 tests', () { 34 | test('Cannot map uppercase ints or doubles', () { 35 | // given 36 | final json = 37 | '''{"Devices": [{"DeviceIdent": "94949494", "GatewayConnections": [{"GwIdent": "39847384", "SignalStrength": {"Strength": "Strong", "RSSI": -74, "SNR": 0.0, "SpreadFactor": 5}}]}]}'''; 38 | 39 | // when 40 | final jsonMap = jsonDecode(json); 41 | final devices = 42 | JsonMapper.deserialize>(jsonMap['Devices']); 43 | 44 | // then 45 | expect(devices, isNotNull); 46 | expect(devices!.length, 1); 47 | final device = devices[0]; 48 | expect(device.gatewayConnections.length, 1); 49 | final gatewayConnection = device.gatewayConnections[0]; 50 | expect(gatewayConnection.signalStrength, isNotNull); 51 | expect(gatewayConnection.signalStrength!.strength, 'Strong'); 52 | expect(gatewayConnection.signalStrength!.rssi, -74); 53 | expect(gatewayConnection.signalStrength!.spreadFactor, 5); 54 | }); 55 | }); 56 | } -------------------------------------------------------------------------------- /mapper/example/example.dart: -------------------------------------------------------------------------------- 1 | import 'package:dart_json_mapper/dart_json_mapper.dart' 2 | show JsonMapper, jsonSerializable, JsonProperty, enumConverterNumeric; 3 | 4 | import 'example.mapper.g.dart' show initializeJsonMapper; 5 | 6 | @jsonSerializable 7 | enum Color { red, blue, green, brown, yellow, black, white } 8 | 9 | @jsonSerializable 10 | class Car { 11 | @JsonProperty(name: 'modelName') 12 | String model; 13 | 14 | Color color; 15 | 16 | Car(this.model, this.color); 17 | 18 | @override 19 | String toString() { 20 | return 'Car{model: $model, color: $color}'; 21 | } 22 | } 23 | 24 | @jsonSerializable 25 | class Person { 26 | List skills = ['Go', 'Dart', 'Flutter']; 27 | 28 | @JsonProperty(name: 'last_promotion_date', ignore: true) 29 | DateTime? lastPromotionDate; 30 | 31 | @JsonProperty(name: 'hire_date') 32 | DateTime hireDate = DateTime(2003, 02, 28); 33 | 34 | bool married = true; 35 | String name = 'Forest'; 36 | 37 | @JsonProperty(ignore: true) 38 | num? salary; 39 | 40 | num? dob; 41 | num age = 36; 42 | var lastName = 'Gump'; 43 | 44 | @JsonProperty(name: 'eye_color') 45 | Color eyeColor = Color.blue; 46 | 47 | @JsonProperty(converter: enumConverterNumeric) 48 | Color hairColor = Color.brown; 49 | 50 | List vehicles = [Car('Tesla', Color.black), Car('BMW', Color.red)]; 51 | 52 | String get fullName => '$name $lastName'; 53 | } 54 | 55 | void main() { 56 | initializeJsonMapper(); 57 | 58 | final personJson = '''{ 59 | "skills": [ 60 | "Go", 61 | "Dart", 62 | "Flutter" 63 | ], 64 | "hire_date": "2003-02-28", 65 | "married": true, 66 | "name": "Forest", 67 | "dob": null, 68 | "age": 36, 69 | "lastName": "Gump", 70 | "eye_color": "Blue", 71 | "hairColor": 3, 72 | "vehicles": [ 73 | { 74 | "modelName": "Tesla", 75 | "color": "Black" 76 | }, 77 | { 78 | "modelName": "BMW", 79 | "color": "Red" 80 | } 81 | ] 82 | }'''; 83 | 84 | // Serialize 85 | print(JsonMapper.serialize(Person())); 86 | 87 | // Deserialize 88 | print(JsonMapper.deserialize(personJson)); 89 | } 90 | -------------------------------------------------------------------------------- /.github/workflows/pipeline.yml: -------------------------------------------------------------------------------- 1 | name: Pipeline 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | 7 | jobs: 8 | test_mapper: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@main 12 | - name: '>> unit & performance tests for mapper <<' 13 | uses: k-paxian/dart-package-publisher@master 14 | with: 15 | testRunOnly: true 16 | credentialJson: ${{ secrets.CREDENTIAL_JSON }} 17 | relativePath: perf-test 18 | 19 | publish_mapper: 20 | needs: [test_mapper] 21 | runs-on: ubuntu-latest 22 | steps: 23 | - uses: actions/checkout@main 24 | - name: '>> publish mapper package to pub.dev <<' 25 | id: publish 26 | uses: k-paxian/dart-package-publisher@master 27 | with: 28 | force: true 29 | credentialJson: ${{ secrets.CREDENTIAL_JSON }} 30 | relativePath: mapper 31 | - name: 'Commit release tag' 32 | if: steps.publish.outputs.success 33 | uses: hole19/git-tag-action@master 34 | env: 35 | TAG: ${{steps.publish.outputs.package}}-${{steps.publish.outputs.localVersion}} 36 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 37 | 38 | publish_adapter: 39 | needs: [publish_mapper] 40 | runs-on: ubuntu-latest 41 | 42 | strategy: 43 | matrix: 44 | adapter: ["flutter", "built", "fixnum", "mobx"] 45 | 46 | steps: 47 | - uses: actions/checkout@main 48 | - run: cp -f ./mapper/LICENSE ./adapters/${{ matrix.adapter }}/LICENSE 49 | - name: '>> test & publish adapter / ${{ matrix.adapter }} <<' 50 | id: publish 51 | uses: k-paxian/dart-package-publisher@master 52 | with: 53 | credentialJson: ${{ secrets.CREDENTIAL_JSON }} 54 | relativePath: adapters/${{ matrix.adapter }} 55 | - name: 'Commit release tag' 56 | if: steps.publish.outputs.success 57 | uses: hole19/git-tag-action@master 58 | env: 59 | TAG: ${{steps.publish.outputs.package}}-${{steps.publish.outputs.localVersion}} 60 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 61 | -------------------------------------------------------------------------------- /adapters/flutter/lib/dart_json_mapper_flutter.dart: -------------------------------------------------------------------------------- 1 | library json_mapper_flutter; 2 | 3 | import 'dart:ui' show Color; 4 | 5 | import 'package:dart_json_mapper/dart_json_mapper.dart' 6 | show 7 | ICustomConverter, 8 | DeserializationContext, 9 | SerializationContext, 10 | JsonMapperAdapter; 11 | 12 | /// Shorthand for ready made converter instance 13 | final colorConverter = ColorConverter(); 14 | 15 | /// [Color] converter 16 | class ColorConverter implements ICustomConverter { 17 | const ColorConverter() : super(); 18 | 19 | @override 20 | Color fromJSON(dynamic jsonValue, DeserializationContext context) { 21 | return jsonValue is Color 22 | ? jsonValue 23 | : jsonValue is String 24 | ? parseColor(jsonValue) 25 | : Color(jsonValue); 26 | } 27 | 28 | @override 29 | dynamic toJSON(Color object, SerializationContext context) { 30 | return colorToString(object); 31 | } 32 | 33 | String colorToString(Color color) { 34 | final aValue = color.alpha.toRadixString(16).padLeft(2, '0'); 35 | final rValue = color.red.toRadixString(16).padLeft(2, '0'); 36 | final gValue = color.green.toRadixString(16).padLeft(2, '0'); 37 | final bValue = color.blue.toRadixString(16).padLeft(2, '0'); 38 | return '#$aValue$rValue$gValue$bValue'.toUpperCase(); 39 | } 40 | 41 | Color parseColor(String value) { 42 | return Color.fromARGB( 43 | int.tryParse(value.substring(1, 3), radix: 16)!, 44 | int.tryParse(value.substring(3, 5), radix: 16)!, 45 | int.tryParse(value.substring(5, 7), radix: 16)!, 46 | int.tryParse(value.substring(7), radix: 16)!); 47 | } 48 | } 49 | 50 | /// Adapter definition, should be passed to the Json Mapper initialization method: 51 | /// initializeJsonMapper(adapters: [flutterAdapter]); 52 | final flutterAdapter = JsonMapperAdapter( 53 | title: 'Flutter Adapter', 54 | refUrl: 'https://github.com/flutter/flutter', 55 | url: 56 | 'https://github.com/k-paxian/dart-json-mapper/tree/master/adapters/flutter', 57 | converters: {Color: colorConverter}, 58 | valueDecorators: {}); 59 | -------------------------------------------------------------------------------- /perf-test/test/unit/_test.dart: -------------------------------------------------------------------------------- 1 | library json_mapper.test; 2 | 3 | import 'package:starlink/starlink.dart' show starlinkGeneratedAdapter; 4 | import 'package:unit_testing/model.dart' show compactOptions; 5 | import 'package:unit_testing/unit_testing.dart' 6 | show unitTestingGeneratedAdapter; 7 | 8 | import '_test.mapper.g.dart' show initializeJsonMapper; 9 | import 'test.collections.dart'; 10 | import 'test.constructors.dart'; 11 | import 'test.converters.caching.dart'; 12 | import 'test.converters.dart'; 13 | import 'test.default.value.dart'; 14 | import 'test.enums.dart'; 15 | import 'test.errors.dart'; 16 | import 'test.flatten.dart'; 17 | import 'test.generics.dart'; 18 | import 'test.inheritance.dart'; 19 | import 'test.injection.dart'; 20 | import 'test.integration.dart'; 21 | import 'test.mixins.dart'; 22 | import 'test.name.casing.dart'; 23 | import 'test.name.path.dart'; 24 | import 'test.partial.deserialization.dart'; 25 | import 'test.required.dart'; 26 | import 'test.scheme.dart'; 27 | import 'test.special.cases.dart'; 28 | import 'test.tuple.dart'; 29 | import 'test.value.decorators.dart'; 30 | import './test.raw_json.dart' as raw_json; 31 | import './test.cache_manager.dart'; 32 | import './test.adapter_manager.dart'; 33 | import './test_issue_234.dart'; 34 | import './test_issue_225.dart'; 35 | 36 | void main() { 37 | initializeJsonMapper( 38 | serializationOptions: compactOptions, 39 | adapters: [starlinkGeneratedAdapter, unitTestingGeneratedAdapter]).info(); 40 | 41 | testCacheManager(); 42 | testAdapterManager(); 43 | testIssue225(); 44 | testIssue234(); 45 | testScheme(); 46 | testDefaultValue(); 47 | testRequired(); 48 | testConvertersCaching(); 49 | testMixinCases(); 50 | testNameCasing(); 51 | testErrorHandling(); 52 | testConverters(); 53 | testValueDecorators(); 54 | testConstructors(); 55 | testPartialDeserialization(); 56 | testIntegration(); 57 | testSpecialCases(); 58 | testGenerics(); 59 | testNamePath(); 60 | testInheritance(); 61 | testInjection(); 62 | testCollections(); 63 | testTupleCases(); 64 | testEnums(); 65 | testFlatten(); 66 | raw_json.main(); 67 | } 68 | -------------------------------------------------------------------------------- /adapters/built/test/test.basics.dart: -------------------------------------------------------------------------------- 1 | import 'package:built_collection/built_collection.dart'; 2 | import 'package:dart_json_mapper/dart_json_mapper.dart'; 3 | import 'package:test/test.dart'; 4 | 5 | /// Sample item class 6 | @jsonSerializable 7 | class Item {} 8 | 9 | /// Container class for built types fields tests 10 | @jsonSerializable 11 | class ItemsList { 12 | BuiltList items = BuiltList.of([Item(), Item()]); 13 | BuiltSet itemsSet = BuiltSet.of([Item(), Item()]); 14 | BuiltMap itemsMap = BuiltMap.of({'1': Item(), '2': Item()}); 15 | } 16 | 17 | /// Ready made instance for options 18 | final compactOptions = SerializationOptions(indent: ''); 19 | 20 | void testBasics() { 21 | group('[Verify BuiltList]', () { 22 | test('BuiltList, BuiltSet, BuiltMap', () { 23 | // given 24 | final json = 25 | '''{"items":[{},{}],"itemsSet":[{},{}],"itemsMap":{"1":{},"2":{}}}'''; 26 | 27 | final adapter = JsonMapperAdapter(valueDecorators: { 28 | typeOf>(): (value) => 29 | BuiltList.of(value.cast()), 30 | typeOf>(): (value) => 31 | BuiltSet.of(value.cast()), 32 | typeOf>(): (value) => (value is BuiltMap) 33 | ? value 34 | : BuiltMap.of(value.cast()), 35 | }); 36 | 37 | // when 38 | JsonMapper().useAdapter(adapter); 39 | 40 | final targetJson = JsonMapper.serialize(ItemsList(), compactOptions); 41 | final instance = JsonMapper.deserialize(targetJson); 42 | 43 | JsonMapper().removeAdapter(adapter); 44 | 45 | // then 46 | expect(targetJson, json); 47 | expect(instance, TypeMatcher()); 48 | expect(instance!.items.length, 2); 49 | expect(instance.items.first, TypeMatcher()); 50 | expect(instance.itemsSet.length, 2); 51 | expect(instance.itemsSet.first, TypeMatcher()); 52 | expect(instance.itemsMap.length, 2); 53 | expect(instance.itemsMap.values.first, TypeMatcher()); 54 | }); 55 | }); 56 | } 57 | -------------------------------------------------------------------------------- /perf-test/test/unit/test.tuple.dart: -------------------------------------------------------------------------------- 1 | import 'package:dart_json_mapper/dart_json_mapper.dart'; 2 | import 'package:test/test.dart'; 3 | import 'package:unit_testing/unit_testing.dart' show defaultOptions; 4 | 5 | /// Motivation: https://github.com/google/json_serializable.dart/blob/master/example/lib/tuple_example.dart 6 | 7 | @jsonSerializable 8 | class Tuple { 9 | final T value1; 10 | final S value2; 11 | 12 | Tuple(this.value1, this.value2); 13 | 14 | factory Tuple.of(Tuple other) => 15 | Tuple(other.value1, other.value2); 16 | } 17 | 18 | @jsonSerializable 19 | @Json(valueDecorators: ConcreteClass.valueDecorators) 20 | class ConcreteClass { 21 | static Map valueDecorators() => { 22 | typeOf>(): (value) => 23 | Tuple.of(value), 24 | typeOf>(): (value) => 25 | Tuple.of(value) 26 | }; 27 | 28 | final Tuple tuple1; 29 | final Tuple tuple2; 30 | 31 | ConcreteClass(this.tuple1, this.tuple2); 32 | } 33 | 34 | void testTupleCases() { 35 | group('[Verify Tuple cases]', () { 36 | test('Tuple as part of concrete class', () { 37 | // given 38 | final json = r''' 39 | { 40 | "tuple1": { 41 | "value1": 1, 42 | "value2": "1970-01-01 00:00:00.024Z" 43 | }, 44 | "tuple2": { 45 | "value1": 42000000, 46 | "value2": "2" 47 | } 48 | }'''; 49 | final instance = ConcreteClass( 50 | Tuple(1, DateTime.fromMillisecondsSinceEpoch(24).toUtc()), 51 | Tuple(const Duration(seconds: 42), BigInt.two), 52 | ); 53 | 54 | // when 55 | final targetJson = JsonMapper.serialize(instance, defaultOptions); 56 | final target = JsonMapper.deserialize(targetJson)!; 57 | 58 | // then 59 | expect(targetJson, json); 60 | expect(target, TypeMatcher()); 61 | expect(target.tuple1, TypeMatcher>()); 62 | expect(target.tuple2, TypeMatcher>()); 63 | expect(target.tuple1.value1, 1); 64 | expect(target.tuple2.value2, BigInt.two); 65 | }); 66 | }); 67 | } 68 | -------------------------------------------------------------------------------- /mapper/lib/src/model/converters/base_converter.dart: -------------------------------------------------------------------------------- 1 | import '../index.dart'; 2 | 3 | typedef SerializeObjectFunction = dynamic Function( 4 | Object? object, SerializationContext context); 5 | typedef DeserializeObjectFunction = dynamic Function( 6 | dynamic object, DeserializationContext context, Type type); 7 | typedef GetConverterFunction = ICustomConverter? Function( 8 | JsonProperty? jsonProperty, TypeInfo typeInfo); 9 | typedef GetConvertedValueFunction = dynamic Function( 10 | ICustomConverter converter, dynamic value, DeserializationContext context); 11 | 12 | /// Abstract class for custom converters implementations 13 | abstract class ICustomConverter { 14 | dynamic toJSON(T object, SerializationContext context); 15 | T fromJSON(dynamic jsonValue, DeserializationContext context); 16 | } 17 | 18 | /// Abstract class for custom iterable converters implementations 19 | abstract class ICustomIterableConverter { 20 | void setIterableInstance(Iterable? instance); 21 | } 22 | 23 | /// Abstract class for custom map converters implementations 24 | abstract class ICustomMapConverter { 25 | void setMapInstance(Map? instance); 26 | } 27 | 28 | /// Abstract class for custom Enum converters implementations 29 | abstract class ICustomEnumConverter { 30 | void setEnumDescriptor(IEnumDescriptor? enumDescriptor); 31 | } 32 | 33 | /// Abstract class for composite converters relying on other converters 34 | abstract class ICompositeConverter { 35 | void setGetConverterFunction(GetConverterFunction getConverter); 36 | void setGetConvertedValueFunction( 37 | GetConvertedValueFunction getConvertedValue); 38 | } 39 | 40 | /// Abstract class for custom recursive converters implementations 41 | abstract class IRecursiveConverter { 42 | void setSerializeObjectFunction(SerializeObjectFunction serializeObject); 43 | void setDeserializeObjectFunction( 44 | DeserializeObjectFunction deserializeObject); 45 | } 46 | 47 | /// Base class for custom type converter having access to parameters provided 48 | /// by the [JsonProperty] meta 49 | class BaseCustomConverter { 50 | const BaseCustomConverter() : super(); 51 | dynamic getConverterParameter(String name, [JsonProperty? jsonProperty]) { 52 | return jsonProperty != null && jsonProperty.converterParams != null 53 | ? jsonProperty.converterParams![name] 54 | : null; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /mapper/lib/src/model/converters/map_converter.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show JsonDecoder; 2 | 3 | import '../index.dart'; 4 | 5 | final mapConverter = MapConverter(); 6 | 7 | /// [Map] converter 8 | class MapConverter 9 | implements 10 | ICustomConverter, 11 | IRecursiveConverter, 12 | ICustomMapConverter { 13 | MapConverter() : super(); 14 | 15 | late SerializeObjectFunction _serializeObject; 16 | late DeserializeObjectFunction _deserializeObject; 17 | Map? _instance; 18 | final _jsonDecoder = JsonDecoder(); 19 | 20 | @override 21 | Map? fromJSON(dynamic jsonValue, DeserializationContext context) { 22 | var result = jsonValue; 23 | final typeInfo = context.typeInfo; 24 | if (jsonValue is String) { 25 | result = _jsonDecoder.convert(jsonValue); 26 | } 27 | if (typeInfo != null && result is Map) { 28 | if (_instance != null && _instance is Map || _instance == null) { 29 | result = result.map((key, value) => MapEntry( 30 | _deserializeObject( 31 | key, 32 | context, 33 | typeInfo.parameters.isEmpty 34 | ? String 35 | : typeInfo.parameters.first), 36 | _deserializeObject( 37 | value, 38 | context, 39 | typeInfo.parameters.isEmpty 40 | ? dynamic 41 | : typeInfo.parameters.last))); 42 | } 43 | if (_instance != null && _instance is Map) { 44 | result.forEach((key, value) => _instance![key] = value); 45 | result = _instance; 46 | } 47 | } 48 | return result; 49 | } 50 | 51 | @override 52 | dynamic toJSON(Map? object, SerializationContext context) => 53 | object?.map((key, value) => MapEntry( 54 | _serializeObject(key, context).toString(), 55 | _serializeObject(value, context))); 56 | 57 | @override 58 | void setSerializeObjectFunction(SerializeObjectFunction serializeObject) { 59 | _serializeObject = serializeObject; 60 | } 61 | 62 | @override 63 | void setDeserializeObjectFunction( 64 | DeserializeObjectFunction deserializeObject) { 65 | _deserializeObject = deserializeObject; 66 | } 67 | 68 | @override 69 | void setMapInstance(Map? instance) { 70 | _instance = instance; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /mapper/lib/src/logic/adapter_manager.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | import 'package:dart_json_mapper/src/model/index.dart'; 3 | 4 | class AdapterManager { 5 | final Map _adapters = {}; 6 | 7 | void use(IJsonMapperAdapter adapter, [int? priority]) { 8 | if (_adapters.containsValue(adapter)) { 9 | return; 10 | } 11 | final nextPriority = priority ?? 12 | (_adapters.keys.isNotEmpty 13 | ? _adapters.keys.reduce((value, item) => max(value, item)) + 1 14 | : 0); 15 | _adapters[nextPriority] = adapter; 16 | } 17 | 18 | void remove(IJsonMapperAdapter adapter) { 19 | _adapters.removeWhere((priority, x) => x == adapter); 20 | } 21 | 22 | void info() => 23 | _adapters.forEach((priority, adapter) => print('$priority : $adapter')); 24 | 25 | void enumerate(Function visitor) { 26 | final sortedKeys = _adapters.keys.toList()..sort(); 27 | final sortedAdapters = sortedKeys.map((key) => _adapters[key]!); 28 | final generatedAdapters = 29 | sortedAdapters.where((adapter) => adapter.isGenerated); 30 | final otherAdapters = 31 | sortedAdapters.where((adapter) => !adapter.isGenerated); 32 | for (var adapter in [...generatedAdapters, ...otherAdapters]) { 33 | visitor(adapter); 34 | } 35 | } 36 | 37 | Map get allEnumValues { 38 | final result = {}; 39 | for (var adapter in _adapters.values) { 40 | result.addAll(adapter.enumValues); 41 | } 42 | return result; 43 | } 44 | 45 | Map get allConverters { 46 | final result = {}; 47 | for (var adapter in _adapters.values) { 48 | result.addAll(adapter.converters); 49 | } 50 | return result; 51 | } 52 | 53 | Map allValueDecorators( 54 | Map inlineDecorators) { 55 | final result = {}; 56 | result.addAll(inlineDecorators); 57 | for (var adapter in _adapters.values) { 58 | result.addAll(adapter.valueDecorators); 59 | } 60 | return result; 61 | } 62 | 63 | Map get allTypeInfoDecorators { 64 | final result = {}; 65 | for (var adapter in _adapters.values) { 66 | result.addAll(adapter.typeInfoDecorators); 67 | } 68 | return result; 69 | } 70 | } -------------------------------------------------------------------------------- /mapper/lib/src/model/converters/default_iterable_converter.dart: -------------------------------------------------------------------------------- 1 | import '../index.dart'; 2 | 3 | final defaultIterableConverter = DefaultIterableConverter(); 4 | 5 | /// Default Iterable converter 6 | class DefaultIterableConverter extends BaseCustomConverter 7 | implements ICustomConverter, ICustomIterableConverter, IRecursiveConverter { 8 | DefaultIterableConverter() : super(); 9 | 10 | Iterable? _instance; 11 | late SerializeObjectFunction _serializeObject; 12 | late DeserializeObjectFunction _deserializeObject; 13 | 14 | @override 15 | dynamic fromJSON(dynamic jsonValue, DeserializationContext context) { 16 | final delimiter = 17 | getConverterParameter('delimiter', context.jsonPropertyMeta); 18 | if (delimiter != null && jsonValue is String) { 19 | jsonValue = jsonValue.split(delimiter); 20 | } 21 | if (_instance != null && jsonValue is Iterable && jsonValue != _instance) { 22 | if (_instance is List) { 23 | (_instance as List).clear(); 24 | for (var item in jsonValue) { 25 | (_instance as List) 26 | .add(_deserializeObject(item, context, context.typeInfo!.type!)); 27 | } 28 | } 29 | if (_instance is Set) { 30 | (_instance as Set).clear(); 31 | for (var item in jsonValue) { 32 | (_instance as Set) 33 | .add(_deserializeObject(item, context, context.typeInfo!.type!)); 34 | } 35 | } 36 | return _instance; 37 | } else if (jsonValue is Iterable) { 38 | return jsonValue 39 | .map((item) => _deserializeObject( 40 | item, context, context.typeInfo!.parameters.first)) 41 | .toList(); 42 | } 43 | return jsonValue; 44 | } 45 | 46 | @override 47 | dynamic toJSON(dynamic object, SerializationContext context) { 48 | final delimiter = 49 | getConverterParameter('delimiter', context.jsonPropertyMeta); 50 | final result = 51 | object?.map((item) => _serializeObject(item, context)).toList(); 52 | if (delimiter != null && result != null) { 53 | return result.join(delimiter); 54 | } 55 | return result; 56 | } 57 | 58 | @override 59 | void setSerializeObjectFunction(SerializeObjectFunction serializeObject) { 60 | _serializeObject = serializeObject; 61 | } 62 | 63 | @override 64 | void setDeserializeObjectFunction( 65 | DeserializeObjectFunction deserializeObject) { 66 | _deserializeObject = deserializeObject; 67 | } 68 | 69 | @override 70 | void setIterableInstance(Iterable? instance) { 71 | _instance = instance; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /mapper/lib/src/model/index/options.dart: -------------------------------------------------------------------------------- 1 | import '../../identifier_casing.dart'; 2 | import 'injectable_values.dart'; 3 | 4 | const defaultDeserializationOptions = DeserializationOptions(); 5 | 6 | /// Declares configuration parameters for Deserialization process 7 | class DeserializationOptions { 8 | /// The most popular ways to combine words into a single string 9 | /// Based on assumption: That all Dart class fields initially 10 | /// given as [CaseStyle.camel] 11 | final CaseStyle? caseStyle; 12 | 13 | /// Scheme to be used 14 | final dynamic scheme; 15 | 16 | /// Process annotated class members only 17 | final bool? processAnnotatedMembersOnly; 18 | 19 | /// Template Instance 20 | /// - for Deserialization output it could be a typed `Iterable`, or `Map`, or else 21 | /// - for Serialization output it could be an instance of `Map` 22 | final dynamic template; 23 | 24 | /// A `Map` of injectable values to be used for direct injection 25 | final InjectableValues? injectableValues; 26 | 27 | /// Declares a fallback target type to deserialize to, when it's not possible to detect 28 | /// it from target type inference OR [template] 29 | final Type? type; 30 | 31 | const DeserializationOptions( 32 | {this.scheme, 33 | this.caseStyle, 34 | this.template, 35 | this.injectableValues, 36 | this.type, 37 | this.processAnnotatedMembersOnly}); 38 | } 39 | 40 | const defaultSerializationOptions = SerializationOptions(indent: ' '); 41 | 42 | /// Declares configuration parameters for Serialization process 43 | /// fully includes [DeserializationOptions] 44 | class SerializationOptions extends DeserializationOptions { 45 | /// JSON Indentation, usually it's just a string of [space] characters 46 | final String? indent; 47 | 48 | /// Null class members 49 | /// will be excluded from serialization process 50 | final bool? ignoreNullMembers; 51 | 52 | /// Class members having [JsonProperty.defaultValue] 53 | /// will be excluded from serialization process 54 | final bool? ignoreDefaultMembers; 55 | 56 | /// Class members having Unknown types 57 | /// will be excluded from serialization process 58 | /// Java Jackson's "@JsonIgnoreProperties(ignoreUnknown = true)" 59 | final bool? ignoreUnknownTypes; 60 | 61 | const SerializationOptions( 62 | {super.scheme, 63 | super.caseStyle, 64 | super.template, 65 | super.processAnnotatedMembersOnly, 66 | this.indent, 67 | this.ignoreNullMembers, 68 | this.ignoreDefaultMembers, 69 | this.ignoreUnknownTypes}) 70 | : super(); 71 | } 72 | -------------------------------------------------------------------------------- /adapters/fixnum/lib/dart_json_mapper_fixnum.dart: -------------------------------------------------------------------------------- 1 | library json_mapper_fixnum; 2 | 3 | import 'package:dart_json_mapper/dart_json_mapper.dart' 4 | show 5 | DefaultTypeInfoDecorator, 6 | typeOf, 7 | DeserializationContext, 8 | SerializationContext, 9 | ICustomConverter, 10 | JsonMapperAdapter; 11 | import 'package:fixnum/fixnum.dart' show Int32, Int64; 12 | 13 | final fixnumTypeInfoDecorator = FixnumTypeInfoDecorator(); 14 | 15 | class FixnumTypeInfoDecorator extends DefaultTypeInfoDecorator { 16 | @override 17 | Type detectTypeByName(String? name) { 18 | switch (name) { 19 | case 'Int32': 20 | return Int32; 21 | case 'Int64': 22 | return Int64; 23 | default: 24 | return super.detectTypeByName(name); 25 | } 26 | } 27 | } 28 | 29 | final int32Converter = Int32Converter(); 30 | 31 | /// [Int32] converter 32 | class Int32Converter implements ICustomConverter { 33 | const Int32Converter() : super(); 34 | 35 | @override 36 | Int32 fromJSON(dynamic jsonValue, DeserializationContext context) { 37 | return jsonValue is Int32 38 | ? jsonValue 39 | : jsonValue is String 40 | ? Int32.parseInt(jsonValue) 41 | : Int32(jsonValue); 42 | } 43 | 44 | @override 45 | dynamic toJSON(Int32 object, SerializationContext context) { 46 | return object.toInt(); 47 | } 48 | } 49 | 50 | final int64Converter = Int64Converter(); 51 | 52 | /// [Int64] converter 53 | class Int64Converter implements ICustomConverter { 54 | const Int64Converter() : super(); 55 | 56 | @override 57 | Int64 fromJSON(dynamic jsonValue, DeserializationContext context) { 58 | return jsonValue is Int64 59 | ? jsonValue 60 | : jsonValue is String 61 | ? Int64.parseInt(jsonValue) 62 | : Int64(jsonValue); 63 | } 64 | 65 | @override 66 | dynamic toJSON(Int64 object, SerializationContext context) { 67 | return object.toInt(); 68 | } 69 | } 70 | 71 | final fixnumAdapter = JsonMapperAdapter( 72 | title: 'Fixnum Adapter', 73 | refUrl: 'https://pub.dev/packages/fixnum', 74 | url: 75 | 'https://github.com/k-paxian/dart-json-mapper/tree/master/adapters/fixnum', 76 | typeInfoDecorators: { 77 | 0: fixnumTypeInfoDecorator 78 | }, 79 | converters: { 80 | Int32: int32Converter, 81 | Int64: int64Converter 82 | }, 83 | valueDecorators: { 84 | typeOf>(): (value) => value.cast(), 85 | typeOf>(): (value) => value.cast(), 86 | typeOf>(): (value) => Set.of(value.cast()), 87 | typeOf>(): (value) => Set.of(value.cast()), 88 | }); 89 | -------------------------------------------------------------------------------- /perf-test/test/unit/test.flatten.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'package:dart_json_mapper/dart_json_mapper.dart'; 3 | import 'package:test/test.dart'; 4 | 5 | // Models as defined in the GitHub issue 6 | @jsonSerializable 7 | class MyObject { 8 | @JsonProperty(name: 'name') 9 | final String name; 10 | 11 | @JsonProperty(flatten: true) 12 | final FlattenObject page; 13 | 14 | MyObject({ 15 | required this.name, 16 | required this.page, 17 | }); 18 | } 19 | 20 | @jsonSerializable 21 | class FlattenObject { 22 | @JsonProperty(name: 'pageNumber') 23 | final int pageNumber; 24 | 25 | @JsonProperty(name: 'pageSize') 26 | final int pageSize; 27 | 28 | FlattenObject({ 29 | required this.pageNumber, 30 | required this.pageSize, 31 | }); 32 | } 33 | 34 | // Note: For these tests to run correctly with dart_json_mapper, 35 | // the necessary .mapper.g.dart files must be generated by build_runner. 36 | // This typically involves: 37 | // 1. Ensuring these classes are discoverable by build_runner (e.g., via a part file 38 | // or being included in a library that build_runner processes). 39 | // 2. Running `dart run build_runner build --delete-conflicting-outputs` 40 | // 3. Importing the generated main adapter initialization file and calling its init method 41 | // (e.g., `import 'path/to/generated_adapter.init.dart'; initializeJsonMapper();`) 42 | // usually in a setupTest.dart or at the beginning of the main test file. 43 | 44 | void testFlatten() { 45 | group('JsonProperty(flatten: true) tests', () { 46 | test('can deserialize with flatten: true', () { 47 | const jsonString = """ 48 | { 49 | "name": "Lost Mine of Phandelver", 50 | "pageNumber": 1, 51 | "pageSize": 10 52 | } 53 | """; 54 | 55 | final decodedJson = jsonDecode(jsonString); 56 | final actual = JsonMapper.deserialize(decodedJson); 57 | 58 | expect(actual, isA()); 59 | expect(actual?.name, 'Lost Mine of Phandelver'); 60 | expect(actual?.page, isA()); 61 | expect(actual?.page.pageNumber, 1); 62 | expect(actual?.page.pageSize, 10); 63 | }); 64 | 65 | test('can serialize with flatten: true', () { 66 | const expectedJsonString = """ 67 | { 68 | "name": "Lost Mine of Phandelver", 69 | "pageNumber": 1, 70 | "pageSize": 10 71 | }"""; 72 | 73 | final myObject = MyObject( 74 | name: 'Lost Mine of Phandelver', 75 | page: FlattenObject(pageNumber: 1, pageSize: 10), 76 | ); 77 | 78 | final actualJson = JsonMapper.serialize(myObject); 79 | final expectedMap = jsonDecode(expectedJsonString); 80 | final actualMap = jsonDecode(actualJson); 81 | 82 | expect(actualMap, equals(expectedMap)); 83 | }); 84 | }); 85 | } 86 | -------------------------------------------------------------------------------- /mapper/lib/src/model/converters/enum_converter_short.dart: -------------------------------------------------------------------------------- 1 | import 'package:collection/collection.dart' show IterableExtension; 2 | 3 | import '../index.dart'; 4 | 5 | final defaultEnumConverter = enumConverterShort; 6 | final enumConverterShort = EnumConverterShort(); 7 | 8 | /// Default converter for [enum] type 9 | class EnumConverterShort implements ICustomConverter, ICustomEnumConverter { 10 | EnumConverterShort() : super(); 11 | 12 | IEnumDescriptor? _enumDescriptor; 13 | 14 | @override 15 | Object? fromJSON(dynamic jsonValue, DeserializationContext context) { 16 | dynamic transformDescriptorValue(value) => 17 | _transformValue(value, context, doubleMapping: true); 18 | dynamic transformJsonValue(value) => 19 | _transformValue(value, context, preTransform: true); 20 | dynamic convert(value) => 21 | _enumDescriptor!.values.firstWhereOrNull((eValue) => 22 | _enumDescriptor!.caseInsensitive == true 23 | ? transformJsonValue(value).toLowerCase() == 24 | transformDescriptorValue(eValue).toLowerCase() 25 | : transformJsonValue(value) == 26 | transformDescriptorValue(eValue)) ?? 27 | _enumDescriptor!.defaultValue; 28 | return jsonValue is Iterable 29 | ? jsonValue.map(convert).toList() 30 | : convert(jsonValue); 31 | } 32 | 33 | @override 34 | dynamic toJSON(Object? object, SerializationContext context) { 35 | dynamic convert(value) => 36 | value != null ? _transformValue(value, context) : null; 37 | return (object is Iterable) 38 | ? object.map(convert).toList() 39 | : convert(object); 40 | } 41 | 42 | @override 43 | void setEnumDescriptor(IEnumDescriptor? enumDescriptor) { 44 | _enumDescriptor = enumDescriptor; 45 | } 46 | 47 | dynamic _transformValue(dynamic value, DeserializationContext context, 48 | {bool doubleMapping = false, bool preTransform = false}) { 49 | final mapping = {}; 50 | mapping.addAll(_enumDescriptor!.mapping); 51 | if (context.jsonPropertyMeta != null && 52 | context.jsonPropertyMeta!.converterParams != null) { 53 | mapping.addAll(context.jsonPropertyMeta!.converterParams!); 54 | } 55 | value = _mapValue(value, mapping); 56 | if (doubleMapping) { 57 | value = _mapValue(value, mapping); 58 | } 59 | if (value is String) { 60 | if (preTransform) { 61 | value = transformIdentifierCaseStyle( 62 | value, context.targetCaseStyle, context.sourceCaseStyle); 63 | } 64 | value = context.transformIdentifier(value); 65 | } 66 | return value; 67 | } 68 | 69 | dynamic _mapValue(dynamic value, Map mapping) => mapping.containsKey(value) 70 | ? mapping[value] 71 | : value.toString().split('.').last; 72 | } 73 | -------------------------------------------------------------------------------- /mapper/lib/src/builder/library_visitor.dart: -------------------------------------------------------------------------------- 1 | import 'package:analyzer/dart/element/element.dart'; 2 | import 'package:analyzer/dart/element/visitor.dart'; 3 | 4 | import '../model/annotations.dart'; 5 | 6 | class LibraryVisitor extends RecursiveElementVisitor { 7 | Map visitedPublicClassElements = {}; 8 | Map visitedPublicAnnotatedClassElements = {}; 9 | Map visitedPublicAnnotatedEnumElements = {}; 10 | Map visitedLibraries = {}; 11 | 12 | final _annotationClassName = jsonSerializable.runtimeType.toString(); 13 | String? packageName; 14 | 15 | LibraryVisitor(this.packageName); 16 | 17 | List get visitedPublicAnnotatedElements { 18 | return [ 19 | ...visitedPublicAnnotatedClassElements.values, 20 | ...visitedPublicAnnotatedEnumElements.values 21 | ]; 22 | } 23 | 24 | @override 25 | void visitLibraryExportElement(LibraryExportElement element) { 26 | _visitLibrary(element.exportedLibrary); 27 | super.visitLibraryExportElement(element); 28 | } 29 | 30 | @override 31 | void visitLibraryImportElement(LibraryImportElement element) { 32 | _visitLibrary(element.importedLibrary); 33 | super.visitLibraryImportElement(element); 34 | } 35 | 36 | @override 37 | void visitClassElement(ClassElement element) { 38 | if (!element.isPrivate && 39 | !visitedPublicClassElements.containsKey(element.id)) { 40 | visitedPublicClassElements.putIfAbsent(element.id, () => element); 41 | if (element.metadata.isNotEmpty && 42 | element.metadata.any((meta) => 43 | meta.computeConstantValue()!.type!.getDisplayString() == 44 | _annotationClassName)) { 45 | visitedPublicAnnotatedClassElements.putIfAbsent( 46 | element.id, () => element); 47 | } 48 | } 49 | super.visitClassElement(element); 50 | } 51 | 52 | @override 53 | void visitEnumElement(EnumElement element) { 54 | if (!element.isPrivate && 55 | !visitedPublicAnnotatedEnumElements.containsKey(element.id)) { 56 | visitedPublicAnnotatedEnumElements.putIfAbsent(element.id, () => element); 57 | if (element.metadata.isNotEmpty && 58 | element.metadata.any((meta) => 59 | meta.computeConstantValue()!.type!.getDisplayString() == 60 | _annotationClassName)) { 61 | visitedPublicAnnotatedEnumElements.putIfAbsent( 62 | element.id, () => element); 63 | } 64 | } 65 | super.visitEnumElement(element); 66 | } 67 | 68 | void _visitLibrary(LibraryElement? element) { 69 | final identifier = element?.identifier; 70 | if (identifier != null && 71 | !visitedLibraries.containsKey(identifier) && 72 | (identifier.startsWith('asset:') || 73 | identifier.startsWith(packageName!))) { 74 | visitedLibraries.putIfAbsent(identifier, () => element); 75 | element!.visitChildren(this); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /models/unit_testing/lib/model.dart: -------------------------------------------------------------------------------- 1 | import 'package:dart_json_mapper/dart_json_mapper.dart'; 2 | 3 | final compactOptions = SerializationOptions(indent: ''); 4 | final defaultOptions = defaultSerializationOptions; 5 | 6 | @jsonSerializable 7 | enum Color { red, blue, gray, grayMetallic, green, brown, yellow, black, white } 8 | 9 | @jsonSerializable 10 | class Tire { 11 | final num thickness; 12 | final Color color; 13 | const Tire(this.thickness, this.color); 14 | } 15 | 16 | @jsonSerializable 17 | class Wheel { 18 | final Tire tire; 19 | const Wheel(this.tire); 20 | } 21 | 22 | @jsonSerializable 23 | class Car { 24 | @JsonProperty(name: 'modelName') 25 | String? model; 26 | 27 | Color? color; 28 | 29 | @JsonProperty(ignoreIfNull: true) 30 | Car? replacement; 31 | 32 | Car(this.model, this.color); 33 | } 34 | 35 | @jsonSerializable 36 | class ComposableCar { 37 | final Wheel leftWheel; 38 | final Wheel rightWheel; 39 | const ComposableCar(this.leftWheel, this.rightWheel); 40 | } 41 | 42 | extension TitledCar on Car { 43 | String get title => '$model-$color'; 44 | } 45 | 46 | @jsonSerializable 47 | class Person { 48 | List skills = ['Go', 'Dart', 'Flutter']; 49 | 50 | List specialDates = [ 51 | DateTime(2013, 02, 28), 52 | DateTime(2023, 02, 28), 53 | DateTime(2003, 02, 28) 54 | ]; 55 | 56 | @JsonProperty( 57 | name: 'last_promotion_date', 58 | converterParams: {'format': 'MM-dd-yyyy H:m:s'}) 59 | DateTime lastPromotionDate = DateTime(2008, 05, 13, 22, 33, 44); 60 | 61 | @JsonProperty(name: 'hire_date', converterParams: {'format': 'MM/dd/yyyy'}) 62 | DateTime hireDate = DateTime(2003, 02, 28); 63 | 64 | @JsonProperty(ignore: true) 65 | bool married = true; 66 | 67 | bool active = true; 68 | 69 | String name = 'Forest'; 70 | 71 | @JsonProperty(converterParams: {'format': '##.##'}) 72 | num salary = 1200000.246; 73 | num? dob; 74 | num age = 36; 75 | 76 | var lastName = 'Gump'; 77 | 78 | dynamic dyn = 'dyn'; 79 | dynamic dynNum = 9; 80 | dynamic dynBool = false; 81 | 82 | Map properties = {'first': 'partridge', 'cash': 23000, 'required': true}; 83 | 84 | Map map = { 85 | 'first': 'partridge', 86 | 'cash': 23000, 87 | 'required': true 88 | }; 89 | 90 | Symbol sym = Symbol('foo'); 91 | 92 | List favouriteColours = [Color.black, Color.white]; 93 | 94 | @JsonProperty(name: 'eye_color') 95 | Color eyeColor = Color.blue; 96 | 97 | @JsonProperty(converter: enumConverterNumeric) 98 | Color hairColor = Color.brown; 99 | 100 | List vehicles = [Car('Tesla', Color.black), Car('BMW', Color.red)]; 101 | 102 | String get fullName => '$name $lastName'; 103 | 104 | Person(); 105 | } 106 | 107 | @jsonSerializable 108 | class GettersOnly { 109 | int _nextId = 0; 110 | String get nextCatId => 'c${_nextId++}'; 111 | String get nextDogId => 'h${_nextId++}'; 112 | } 113 | -------------------------------------------------------------------------------- /mapper/lib/src/builder/builder.dart: -------------------------------------------------------------------------------- 1 | import 'package:analyzer/dart/element/element.dart'; 2 | // ignore: implementation_imports 3 | import 'package:analyzer/src/dart/element/element.dart' show LibraryElementImpl; 4 | import 'package:build/build.dart'; 5 | import 'package:pubspec_parse/pubspec_parse.dart'; 6 | // ignore: implementation_imports 7 | import 'package:reflectable_builder/src/builder_implementation.dart' 8 | show BuilderImplementation; 9 | 10 | import 'reflectable_source_wrapper.dart'; 11 | 12 | class DartJsonMapperBuilder implements Builder { 13 | BuilderOptions builderOptions; 14 | Map wrappersMap = {}; 15 | 16 | DartJsonMapperBuilder(this.builderOptions); 17 | 18 | String get _extension => 19 | builderOptions.config['extension'] ?? '.mapper.g.dart'; 20 | 21 | bool get _formatted => builderOptions.config['formatted'] ?? false; 22 | 23 | @override 24 | Map> get buildExtensions => { 25 | '.dart': [_extension] 26 | }; 27 | 28 | ReflectableSourceWrapper getWrapperForLibrary(LibraryElement inputLibrary, 29 | Pubspec mapperPubspec, Pubspec inputPubspec) { 30 | var result = wrappersMap[inputLibrary.identifier]; 31 | if (result == null) { 32 | result = ReflectableSourceWrapper( 33 | inputLibrary, builderOptions.config, mapperPubspec, inputPubspec); 34 | wrappersMap.putIfAbsent(inputLibrary.identifier, () => result); 35 | } 36 | return result; 37 | } 38 | 39 | Future getPubspec(String package, BuildStep buildStep) async { 40 | final assetId = AssetId(package, 'pubspec.yaml'); 41 | final content = await buildStep.readAsString(assetId); 42 | return Pubspec.parse(content, sourceUrl: assetId.uri); 43 | } 44 | 45 | @override 46 | Future build(BuildStep buildStep) async { 47 | final inputId = buildStep.inputId; 48 | final outputId = inputId.changeExtension(_extension); 49 | final inputLibrary = await buildStep.inputLibrary; 50 | final incrementalBuild = wrappersMap[inputLibrary.identifier] != null; 51 | final wrapper = getWrapperForLibrary( 52 | inputLibrary, 53 | await getPubspec('dart_json_mapper', buildStep), 54 | await getPubspec(buildStep.inputId.package, buildStep)); 55 | if (incrementalBuild && wrapper.hasNoIncrementalChanges(inputLibrary)) { 56 | await buildStep.writeAsString(outputId, wrapper.lastOutput!); 57 | return; 58 | } 59 | final resolver = buildStep.resolver; 60 | final visibleLibraries = await resolver.libraries.toList(); 61 | final builderImplementation = BuilderImplementation(); 62 | final generatedSource = await builderImplementation.buildMirrorLibrary( 63 | resolver, 64 | inputId, 65 | outputId, 66 | inputLibrary, 67 | visibleLibraries.cast(), 68 | _formatted, 69 | []); 70 | final wrappedSource = wrapper.wrap(generatedSource)!; 71 | await buildStep.writeAsString(outputId, wrappedSource); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /perf-test/test/unit/test.required.dart: -------------------------------------------------------------------------------- 1 | import 'package:dart_json_mapper/dart_json_mapper.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | @jsonSerializable 5 | class MyNullableFieldsExample { 6 | List? myList; 7 | Map? myMap; 8 | Set? mySet; 9 | } 10 | 11 | @jsonSerializable 12 | class TransactionsRequestModel { 13 | final String? accountType; 14 | 15 | TransactionsRequestModel({ 16 | this.accountType, 17 | }); 18 | } 19 | 20 | @jsonSerializable 21 | class Preferences { 22 | final String defaultCountryIsoCode; 23 | 24 | /// can be null if user didn't specify his will yet 25 | final bool? autoImportContacts; 26 | final Metadata metadata; 27 | 28 | Preferences({ 29 | required this.metadata, 30 | required this.defaultCountryIsoCode, 31 | required this.autoImportContacts, 32 | }); 33 | 34 | @override 35 | String toString() => 36 | 'Preferences(countryIsoCode: $defaultCountryIsoCode, autoImportContacts: $autoImportContacts, metadata: $metadata)'; 37 | } 38 | 39 | @jsonSerializable 40 | class Metadata { 41 | @JsonProperty(ignoreForSerialization: true) 42 | final String id; 43 | final String createdBy; 44 | @JsonProperty(defaultValue: false) 45 | final bool deleted; 46 | 47 | Metadata({ 48 | required this.id, 49 | required this.createdBy, 50 | this.deleted = false, 51 | }); 52 | 53 | @override 54 | String toString() { 55 | return 'Metadata(id: $id, createdBy: $createdBy)'; 56 | } 57 | } 58 | 59 | void testRequired() { 60 | group('[Verify required fields]', () { 61 | test('ignoreForSerialization:true vs required annotated field', () { 62 | // given 63 | final json = r''' 64 | { 65 | "defaultCountryIsoCode": "US", 66 | "metadata": { 67 | "createdBy": "e5PPxnqulIgBslobDZPXVweoTCC2", 68 | "id": "e5PPxnqulIgBslobDZPXVweoTCC2" 69 | } 70 | } 71 | '''; 72 | 73 | // when 74 | final target = JsonMapper.deserialize(json)!; 75 | final targetJson = JsonMapper.serialize(target); 76 | 77 | // then 78 | expect(target.metadata.id, 'e5PPxnqulIgBslobDZPXVweoTCC2'); 79 | expect(targetJson, 80 | '{"defaultCountryIsoCode":"US","autoImportContacts":null,"metadata":{"createdBy":"e5PPxnqulIgBslobDZPXVweoTCC2","deleted":false}}'); 81 | }); 82 | 83 | test('Should handle null fields', () { 84 | // given 85 | final json = r'''{"myList":null,"myMap":null,"mySet":null}'''; 86 | 87 | // when 88 | final targetJson = JsonMapper.toJson(MyNullableFieldsExample()); 89 | 90 | // then 91 | expect(targetJson, json); 92 | }); 93 | 94 | test('toMap vs toJson parity', () { 95 | // given 96 | final json = r'''{"accountType":null}'''; 97 | 98 | // when 99 | final targetJson = 100 | JsonMapper.toJson(TransactionsRequestModel(accountType: null)); 101 | final target = 102 | JsonMapper.toMap(TransactionsRequestModel(accountType: null)); 103 | 104 | // then 105 | expect(targetJson, json); 106 | expect(target!.containsKey('accountType'), true); 107 | expect(target.containsValue(null), true); 108 | }); 109 | }); 110 | } 111 | -------------------------------------------------------------------------------- /perf-test/test/unit/test.injection.dart: -------------------------------------------------------------------------------- 1 | import 'package:dart_json_mapper/dart_json_mapper.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | class ParentInjected1 { 5 | String? lastName; 6 | List children = []; 7 | } 8 | 9 | @jsonSerializable 10 | class ChildInjected1 { 11 | String? firstName; 12 | 13 | @JsonProperty(inject: true) 14 | ParentInjected1? parent; 15 | 16 | @JsonProperty(inject: true) 17 | String? nickname; 18 | } 19 | 20 | class ParentInjected2 { 21 | String? lastName; 22 | List children = []; 23 | } 24 | 25 | @jsonSerializable 26 | class ChildInjected2 { 27 | String? firstName; 28 | 29 | @JsonProperty(inject: true) 30 | ParentInjected2? parent; 31 | 32 | @JsonProperty(name: 'data/nick', inject: true) 33 | String? nickname; 34 | 35 | ChildInjected2(this.parent); 36 | } 37 | 38 | class ParentInjected3 { 39 | String? lastName; 40 | List children = []; 41 | } 42 | 43 | @jsonSerializable 44 | class ChildInjected3 { 45 | String? firstName; 46 | 47 | @JsonProperty(inject: true) 48 | ParentInjected3? parent; 49 | 50 | @JsonProperty(inject: true) 51 | String? nickname; 52 | 53 | ChildInjected3(this.parent); 54 | } 55 | 56 | void testInjection() { 57 | group('[Verify injected fields]', () { 58 | test('Referencing to injected object', () { 59 | // given 60 | final json1 = '''{"firstName": "Alice"}'''; 61 | final json2 = '''{"firstName": "Bob"}'''; 62 | final json3 = '''{"firstName": "Eve"}'''; 63 | 64 | // when 65 | ParentInjected1 parentInstance1 = ParentInjected1()..lastName = "Doe"; 66 | final childInstance1 = JsonMapper.deserialize( 67 | json1, 68 | DeserializationOptions( 69 | injectableValues: {'parent': parentInstance1, 'nickname': "Ally"}), 70 | )!; 71 | parentInstance1.children.add(childInstance1); 72 | 73 | ParentInjected2 parentInstance2 = ParentInjected2()..lastName = "Doe"; 74 | final childInstance2 = JsonMapper.deserialize( 75 | json2, 76 | DeserializationOptions(injectableValues: { 77 | 'parent': parentInstance2, 78 | 'data': {'nick': "Bobby"} 79 | }))!; 80 | parentInstance2.children.add(childInstance2); 81 | 82 | ParentInjected3 parentInstance3 = ParentInjected3()..lastName = "Doe"; 83 | final childInstance3 = JsonMapper.deserialize( 84 | json3, 85 | DeserializationOptions( 86 | injectableValues: {'parent': parentInstance3}))!; 87 | parentInstance3.children.add(childInstance3); 88 | 89 | // then 90 | expect(parentInstance1.lastName, "Doe"); 91 | expect(childInstance1.parent, parentInstance1); 92 | expect(childInstance1.firstName, "Alice"); 93 | expect(childInstance1.nickname, "Ally"); 94 | 95 | expect(parentInstance2.lastName, "Doe"); 96 | expect(childInstance2.parent, parentInstance2); 97 | expect(childInstance2.firstName, "Bob"); 98 | expect(childInstance2.nickname, "Bobby"); 99 | 100 | expect(parentInstance3.lastName, "Doe"); 101 | expect(childInstance3.parent, parentInstance3); 102 | expect(childInstance3.firstName, "Eve"); 103 | expect(childInstance3.nickname, null); 104 | }); 105 | }); 106 | } 107 | -------------------------------------------------------------------------------- /adapters/fixnum/test/test.basics.dart: -------------------------------------------------------------------------------- 1 | part of '_test.dart'; 2 | 3 | @jsonSerializable 4 | class Int32IntData { 5 | Int32 int32; 6 | 7 | Int32IntData(this.int32); 8 | } 9 | 10 | @jsonSerializable 11 | class Int64IntData { 12 | Int64 int64; 13 | 14 | Int64IntData(this.int64); 15 | } 16 | 17 | final compactOptions = SerializationOptions(indent: ''); 18 | 19 | void testBasics() { 20 | test('Int32 converter', () { 21 | // given 22 | final rawString = '1234567890'; 23 | final json = '{"int32":$rawString}'; 24 | 25 | // when 26 | final targetJson = JsonMapper.serialize( 27 | Int32IntData(Int32.parseInt(rawString)), compactOptions); 28 | // then 29 | expect(targetJson, json); 30 | 31 | // when 32 | final target = JsonMapper.deserialize(json); 33 | // then 34 | expect(rawString, target!.int32.toString()); 35 | }); 36 | 37 | test('Int64 converter', () { 38 | // given 39 | final rawString = '1234567890123456789'; 40 | final json = '{"int64":$rawString}'; 41 | 42 | // when 43 | final targetJson = JsonMapper.serialize( 44 | Int64IntData(Int64.parseInt(rawString)), compactOptions); 45 | // then 46 | expect(targetJson, json); 47 | 48 | // when 49 | final target = JsonMapper.deserialize(json); 50 | // then 51 | expect(rawString, target!.int64.toString()); 52 | }); 53 | 54 | test('List', () { 55 | // given 56 | final json = '[2112454933,2112454934]'; 57 | 58 | // when 59 | final instance = JsonMapper.deserialize>(json); 60 | // then 61 | expect(instance!, TypeMatcher>()); 62 | expect(instance[0], Int32(2112454933)); 63 | expect(instance[1], Int32(2112454934)); 64 | 65 | // when 66 | final targetJson = JsonMapper.serialize(instance, compactOptions); 67 | // then 68 | expect(targetJson, json); 69 | }); 70 | 71 | test('Set', () { 72 | // given 73 | final json = '[2112454933,2112454934]'; 74 | 75 | // when 76 | final instance = JsonMapper.deserialize>(json); 77 | // then 78 | expect(instance, TypeMatcher>()); 79 | expect(instance!.elementAt(0), Int32(2112454933)); 80 | expect(instance.elementAt(1), Int32(2112454934)); 81 | 82 | // when 83 | final targetJson = JsonMapper.serialize(instance, compactOptions); 84 | // then 85 | expect(targetJson, json); 86 | }); 87 | 88 | test('List', () { 89 | // given 90 | final json = '[1234567890123456789,1234567890123456787]'; 91 | 92 | // when 93 | final instance = JsonMapper.deserialize>(json); 94 | // then 95 | expect(instance!, TypeMatcher>()); 96 | expect(instance[0], Int64(1234567890123456789)); 97 | expect(instance[1], Int64(1234567890123456787)); 98 | 99 | // when 100 | final targetJson = JsonMapper.serialize(instance, compactOptions); 101 | // then 102 | expect(targetJson, json); 103 | }); 104 | 105 | test('Set', () { 106 | // given 107 | final json = '[1234567890123456789,1234567890123456787]'; 108 | 109 | // when 110 | final instance = JsonMapper.deserialize>(json); 111 | // then 112 | expect(instance!, TypeMatcher>()); 113 | expect(instance.elementAt(0), Int64(1234567890123456789)); 114 | expect(instance.elementAt(1), Int64(1234567890123456787)); 115 | 116 | // when 117 | final targetJson = JsonMapper.serialize(instance, compactOptions); 118 | // then 119 | expect(targetJson, json); 120 | }); 121 | } 122 | -------------------------------------------------------------------------------- /mapper/lib/src/identifier_casing.dart: -------------------------------------------------------------------------------- 1 | /// The most popular ways to combine multiple words as a single string 2 | enum CaseStyle { camel, pascal, kebab, snake, snakeAllCaps } 3 | 4 | /// Default case style when not specified explicitly 5 | const defaultCaseStyle = CaseStyle.camel; 6 | 7 | /// Converts [input] of certain [caseStyle] to List of words 8 | List toWords(String input, [CaseStyle? caseStyle = defaultCaseStyle]) { 9 | final effectiveCaseStyle = caseStyle ?? defaultCaseStyle; 10 | switch (effectiveCaseStyle) { 11 | case CaseStyle.snake: 12 | case CaseStyle.snakeAllCaps: 13 | return input.split('_'); 14 | case CaseStyle.kebab: 15 | return input.split('-'); 16 | case CaseStyle.pascal: 17 | if (input == input.toUpperCase()) { 18 | return [input]; 19 | } 20 | return deCapitalize(input) 21 | .replaceAllMapped(RegExp('([a-z0-9])([A-Z])'), 22 | (match) => '${match.group(1)} ${match.group(2)}') 23 | .replaceAllMapped(RegExp('([A-Z])([A-Z])(?=[a-z])'), 24 | (match) => '${match.group(1)} ${match.group(2)}') 25 | .toLowerCase() 26 | .split(' '); 27 | case CaseStyle.camel: 28 | if (input == input.toUpperCase()) { 29 | return [input]; 30 | } 31 | return input 32 | .replaceAllMapped(RegExp('([a-z0-9])([A-Z])'), 33 | (match) => '${match.group(1)} ${match.group(2)}') 34 | .replaceAllMapped(RegExp('([A-Z])([A-Z])(?=[a-z])'), 35 | (match) => '${match.group(1)} ${match.group(2)}') 36 | .toLowerCase() 37 | .split(' '); 38 | default: 39 | return input.split(' '); 40 | } 41 | } 42 | 43 | /// Omits leading words from [input] when they are equal to [prefix] words 44 | String skipPrefix(String prefix, String input, 45 | [CaseStyle? caseStyle = defaultCaseStyle]) { 46 | final effectiveCaseStyle = caseStyle ?? defaultCaseStyle; 47 | final prefixWords = toWords(prefix, effectiveCaseStyle); 48 | final inputWords = toWords(input, effectiveCaseStyle); 49 | int index = -1; 50 | final result = inputWords.where((element) { 51 | index++; 52 | if (index < prefixWords.length) { 53 | return prefixWords[index] != element; 54 | } 55 | return true; 56 | }); 57 | return transformIdentifierCaseStyle(result.join(' '), caseStyle, null); 58 | } 59 | 60 | String capitalize(String input) => input.replaceFirstMapped( 61 | RegExp(r'(^|\s)[a-z]'), (match) => match.group(0)!.toUpperCase()); 62 | 63 | String deCapitalize(String input) => input.replaceFirstMapped( 64 | RegExp(r'(^|\s)[A-Z]'), (match) => match.group(0)!.toLowerCase()); 65 | 66 | /// Transforms identifier from [sourceCaseStyle] to [targetCaseStyle] 67 | String transformIdentifierCaseStyle( 68 | String source, CaseStyle? targetCaseStyle, CaseStyle? sourceCaseStyle) { 69 | if (sourceCaseStyle == targetCaseStyle) { 70 | return source; 71 | } 72 | switch (targetCaseStyle) { 73 | case CaseStyle.kebab: 74 | return toWords(source, sourceCaseStyle).join('-'); 75 | case CaseStyle.snake: 76 | return toWords(source, sourceCaseStyle).join('_'); 77 | case CaseStyle.snakeAllCaps: 78 | return toWords(source, sourceCaseStyle).join('_').toUpperCase(); 79 | case CaseStyle.pascal: 80 | return toWords(source, sourceCaseStyle) 81 | .map((word) => capitalize(word)) 82 | .join(''); 83 | case CaseStyle.camel: 84 | return deCapitalize(toWords(source, sourceCaseStyle) 85 | .map((word) => word.toLowerCase()) 86 | .map((e) => capitalize(e)) 87 | .join('')); 88 | default: 89 | return source; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /mapper/lib/src/json_map.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show JsonDecoder; 2 | 3 | import 'package:collection/collection.dart' show IterableExtension; 4 | 5 | import 'model/index.dart'; 6 | 7 | /// Provides logic for traversing Json object tree 8 | class JsonMap { 9 | final pathDelimiter = '/'; 10 | 11 | final Map map; 12 | final List? parentMaps; 13 | final Json? jsonMeta; 14 | 15 | const JsonMap(this.map, [this.jsonMeta, this.parentMaps = const []]); 16 | 17 | static final JsonDecoder _jsonDecoder = const JsonDecoder(); 18 | 19 | static bool isValidJSON(dynamic jsonValue) { 20 | try { 21 | if (jsonValue is String) { 22 | _jsonDecoder.convert(jsonValue); 23 | return true; 24 | } 25 | return false; 26 | } on FormatException { 27 | return false; 28 | } 29 | } 30 | 31 | bool hasProperty(String name) { 32 | return _isPathExists(_getPath(name)); 33 | } 34 | 35 | dynamic getPropertyValue(String name) { 36 | dynamic result; 37 | final path = _getPath(name); 38 | _isPathExists(path, (m, k) { 39 | result = (m is Map && m.containsKey(k) && k != path) ? m[k] : m; 40 | }); 41 | return result; 42 | } 43 | 44 | void setPropertyValue(String name, dynamic value) { 45 | _isPathExists(_getPath(name), (m, k) {}, true, value); 46 | } 47 | 48 | String _decodePath(String path) { 49 | if (path.startsWith('#')) { 50 | path = Uri.decodeComponent(path).substring(1); 51 | } 52 | return path; 53 | } 54 | 55 | String _getPath(String propertyName) { 56 | final rootObjectSegments = jsonMeta != null && jsonMeta!.name != null 57 | ? _decodePath(jsonMeta!.name!).split(pathDelimiter) 58 | : []; 59 | final propertySegments = _decodePath(propertyName).split(pathDelimiter); 60 | rootObjectSegments.addAll(propertySegments); 61 | rootObjectSegments.removeWhere((value) => value == ''); 62 | return rootObjectSegments.join(pathDelimiter); 63 | } 64 | 65 | bool _isPathExists(String path, 66 | [Function? propertyVisitor, bool? autoCreate, dynamic autoValue]) { 67 | final segments = path 68 | .split(pathDelimiter) 69 | .map((p) => p.replaceAll('~1', pathDelimiter).replaceAll('~0', '~')) 70 | .toList(); 71 | dynamic current = map; 72 | var existingSegmentsCount = 0; 73 | for (var segment in segments) { 74 | final idx = int.tryParse(segment); 75 | if (segment == JsonProperty.parentReference) { 76 | final nearestParent = 77 | parentMaps!.lastWhereOrNull((element) => element.map != current); 78 | if (nearestParent != null) { 79 | current = nearestParent.map; 80 | existingSegmentsCount++; 81 | } 82 | continue; 83 | } 84 | if (current is List && 85 | idx != null && 86 | (current.length > idx) && 87 | (idx >= 0) && 88 | current.elementAt(idx) != null) { 89 | current = current.elementAt(idx); 90 | existingSegmentsCount++; 91 | } 92 | if (current is Map && current.containsKey(segment)) { 93 | current = current[segment]; 94 | existingSegmentsCount++; 95 | } else { 96 | if (autoCreate == true) { 97 | existingSegmentsCount++; 98 | final isLastSegment = segments.length == existingSegmentsCount; 99 | current[segment] = isLastSegment ? autoValue : {}; 100 | current = current[segment]; 101 | } 102 | } 103 | } 104 | if (propertyVisitor != null && current != null) { 105 | propertyVisitor(current, segments.last); 106 | } 107 | return segments.length == existingSegmentsCount && 108 | existingSegmentsCount > 0; 109 | } 110 | } -------------------------------------------------------------------------------- /perf-test/test/unit/test.generics.dart: -------------------------------------------------------------------------------- 1 | import 'package:dart_json_mapper/dart_json_mapper.dart'; 2 | import 'package:test/test.dart'; 3 | import 'package:unit_testing/unit_testing.dart' 4 | show 5 | MyCarModel, 6 | Color, 7 | EntityModel, 8 | Car, 9 | Foo, 10 | Bar, 11 | ApiResultUserModel, 12 | ApiResult, 13 | UserModel; 14 | 15 | void testGenerics() { 16 | group('[Verify generics cases]', () { 17 | test('ApiResult', () { 18 | // given 19 | final json = '''{"success":true,"result":{"id":1,"name":"aa"}}'''; 20 | 21 | // when 22 | final target = ApiResult().fromJson(json); 23 | // or 24 | final target2 = JsonMapper.deserialize(json); 25 | 26 | // then 27 | expect(target!.result!.id, 1); 28 | expect(target.result!.name, 'aa'); 29 | expect(target.success, true); 30 | 31 | expect(target2!.result!.id, 1); 32 | expect(target2.result!.name, 'aa'); 33 | expect(target2.success, true); 34 | 35 | expect(target.toJson(), json); 36 | expect(target.toJson(), target2.toJson()); 37 | }); 38 | 39 | test('BarBase', () { 40 | // given 41 | final json = '''{"foo":{}}'''; 42 | final bar = Bar()..foo = Foo(); 43 | 44 | // when 45 | final targetJson = bar.toJson(); 46 | final target = Bar().fromJson(json)!; 47 | 48 | // then 49 | expect(targetJson, json); 50 | expect(target, TypeMatcher()); 51 | expect(target.foo, TypeMatcher()); 52 | }); 53 | 54 | test('Generic AbstractEntityModel, OOP paradigm(inheritance)', () { 55 | // given 56 | const carModel = MyCarModel( 57 | uuid: 'uid', 58 | parentUuid: 'parentUid', 59 | model: 'Tesla S3', 60 | color: Color.black); 61 | 62 | // when 63 | final json = carModel.toJson(); 64 | 65 | // then 66 | expect(json, { 67 | 'technicalName': 'MyCarModel', 68 | 'parentUuid': 'parentUid', 69 | 'uuid': 'uid', 70 | 'model': 'Tesla S3', 71 | 'color': 'black' 72 | }); 73 | }); 74 | 75 | test('Generic Entity Model, composition', () { 76 | /// https://en.wikipedia.org/wiki/Composition_over_inheritance 77 | /// In this case class Car is `composed` with generic EntityModel as `EntityModel` 78 | /// Car is a useful payload, EntityModel is a generic information container for payload T 79 | 80 | // given 81 | final carModel = EntityModel( 82 | uuid: 'uid', parentUuid: 'parentUid', entity: Car('x', Color.blue)); 83 | final adapter = JsonMapperAdapter(valueDecorators: { 84 | // Value decorator is needed to convert generic instance 85 | // `EntityModel` to concrete type instance `EntityModel` 86 | typeOf>(): (value) => EntityModel.of(value) 87 | }); 88 | JsonMapper().useAdapter(adapter); 89 | 90 | // when 91 | final modelJson = carModel.toJson(); 92 | final entityJson = carModel.entityToJson(); 93 | final entityInstance = carModel.newEntityFromModelJson(modelJson)!; 94 | 95 | // then 96 | expect(modelJson, { 97 | 'technicalName': 'EntityModel', 98 | 'parentUuid': 'parentUid', 99 | 'uuid': 'uid', 100 | 'modelName': 'x', 101 | 'color': 'blue' 102 | }); 103 | 104 | expect(entityJson, {'modelName': 'x', 'color': 'blue'}); 105 | 106 | expect(entityInstance, TypeMatcher()); 107 | expect(entityInstance.model, 'x'); 108 | expect(entityInstance.color, Color.blue); 109 | 110 | JsonMapper().removeAdapter(adapter); 111 | }); 112 | }); 113 | } 114 | -------------------------------------------------------------------------------- /perf-test/test/unit/test.special.cases.dart: -------------------------------------------------------------------------------- 1 | import 'package:dart_json_mapper/dart_json_mapper.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | @jsonSerializable 5 | class A { 6 | final int a; 7 | 8 | A(this.a); 9 | 10 | @override 11 | bool operator ==(Object other) => 12 | runtimeType == other.runtimeType && a == (other as A).a; 13 | 14 | @override 15 | int get hashCode => a.hashCode; 16 | } 17 | 18 | @jsonSerializable 19 | class B { 20 | final A a; 21 | 22 | B(this.a); 23 | } 24 | 25 | @jsonSerializable 26 | class AA { 27 | BB? content; 28 | } 29 | 30 | @jsonSerializable 31 | class BB { 32 | List? content; 33 | } 34 | 35 | @jsonSerializable 36 | class GetQueryParameters { 37 | num? page; 38 | num? limit; 39 | 40 | @JsonProperty(name: 'field_searchable.0') 41 | bool? fieldSearchable; 42 | 43 | @JsonProperty(converterParams: {'delimiter': ','}) 44 | List? types; 45 | } 46 | 47 | @jsonSerializable 48 | class UnbalancedGetSet { 49 | String? _id; 50 | 51 | String get id { 52 | // <--- returns a non null value 53 | return _id ?? ""; 54 | } 55 | 56 | set id( 57 | String? /*expects a nullable value that my come like that from the server*/ 58 | id) { 59 | _id = (id ?? ""); 60 | } 61 | } 62 | 63 | void testSpecialCases() { 64 | group('[Verify special cases]', () { 65 | test('A/B inception deserialization', () { 66 | // given 67 | final json = '{"content":{"content":[]}}'; 68 | 69 | // when 70 | final target = JsonMapper.deserialize(json)!; 71 | 72 | // then 73 | expect(target, TypeMatcher()); 74 | expect(target.content, TypeMatcher()); 75 | expect(target.content!.content, TypeMatcher>()); 76 | }); 77 | 78 | test('A/B circular reference serialization with overridden hashCode', () { 79 | // given 80 | final json = '[{"a":1},{"a":1},{"a":{"a":1}}]'; 81 | final a = A(1); 82 | final b = B(A(1)); 83 | 84 | // when 85 | final target = JsonMapper.serialize([a, a, b]); 86 | 87 | // then 88 | expect(target, json); 89 | }); 90 | }); 91 | 92 | group('[Verify unbalanced setter/getter types]', () { 93 | test('should be ok to have different types for getter & setter', () { 94 | // given 95 | final inputJson = '{"id":null}'; 96 | final targetJson = '{"id":""}'; 97 | 98 | // when 99 | final target = JsonMapper.deserialize(inputJson)!; 100 | final outputJson = JsonMapper.serialize(target); 101 | 102 | // then 103 | expect(target, TypeMatcher()); 104 | expect(target.id, ""); 105 | expect(outputJson, targetJson); 106 | }); 107 | }); 108 | 109 | group('[Verify toUri util method]', () { 110 | // given 111 | final params = GetQueryParameters(); 112 | params.limit = 99; 113 | params.page = 1; 114 | params.fieldSearchable = true; 115 | params.types = ['a', 'b']; 116 | 117 | test('get parameters as object', () { 118 | // when 119 | final target = JsonMapper.toUri(getParams: params); 120 | 121 | // then 122 | expect(target, TypeMatcher()); 123 | expect(target.toString(), 124 | r'?page=1&limit=99&field_searchable.0=true&types=a%2Cb'); 125 | }); 126 | 127 | test('get parameters as object + baseUrl', () { 128 | // when 129 | final target = 130 | JsonMapper.toUri(getParams: params, baseUrl: 'http://go.com'); 131 | 132 | // then 133 | expect(target.toString(), 134 | r'http://go.com?page=1&limit=99&field_searchable.0=true&types=a%2Cb'); 135 | }); 136 | 137 | test('baseUrl', () { 138 | // when 139 | final target = JsonMapper.toUri(baseUrl: 'http://go.com'); 140 | 141 | // then 142 | expect(target.toString(), r'http://go.com'); 143 | }); 144 | }); 145 | } 146 | -------------------------------------------------------------------------------- /perf-test/test/unit/test.inheritance.dart: -------------------------------------------------------------------------------- 1 | import 'package:dart_json_mapper/dart_json_mapper.dart'; 2 | import 'package:test/test.dart'; 3 | import 'package:unit_testing/unit_testing.dart' 4 | show 5 | TypedStringChild, 6 | TypedStringParent, 7 | TypedChild, 8 | TypedParent, 9 | AbstractUser, 10 | UserImpl, 11 | BusinessType, 12 | MySuperclass, 13 | Stakeholder, 14 | Stakeholder2, 15 | Hotel, 16 | Hotel2, 17 | Startup, 18 | Startup2; 19 | 20 | void testInheritance() { 21 | group('[Verify inheritance cases]', () { 22 | test( 23 | 'Should distinguish inherited classes by readonly discriminator property value', 24 | () { 25 | // given 26 | final jack = Stakeholder('Jack', [Startup(10), Hotel(4)]); 27 | 28 | // when 29 | final json = JsonMapper.serialize(jack); 30 | final target = JsonMapper.deserialize(json)!; 31 | 32 | // then 33 | expect(target.businesses[0], TypeMatcher()); 34 | expect(target.businesses[0].type, BusinessType.public); 35 | expect(target.businesses[1], TypeMatcher()); 36 | expect(target.businesses[1].type, BusinessType.private); 37 | }); 38 | 39 | test( 40 | 'Should distinguish inherited classes by writable discriminator property value', 41 | () { 42 | // given 43 | final jack = Stakeholder2('Jack', [Startup2(10), Hotel2(4)]); 44 | 45 | // when 46 | final json = JsonMapper.serialize(jack); 47 | final target = JsonMapper.deserialize(json)!; 48 | 49 | // then 50 | expect(target.businesses[0], TypeMatcher()); 51 | expect(target.businesses[0].type, BusinessType.public2); 52 | expect(target.businesses[1], TypeMatcher()); 53 | expect(target.businesses[1].type, BusinessType.private2); 54 | }); 55 | 56 | test('should inherit annotations from abstract class', () { 57 | // given 58 | final instance = MySuperclass(); 59 | final json = 60 | '{"myCustomFieldName":"myFieldValue","myCustomGetterName":"myGetterValue"}'; 61 | 62 | // when 63 | final targetJson = JsonMapper.serialize(instance); 64 | final target = JsonMapper.deserialize(targetJson)!; 65 | 66 | // then 67 | expect(targetJson, json); 68 | expect(target.myField, instance.myField); 69 | expect(target.myGetter, instance.myGetter); 70 | }); 71 | 72 | test('implements AbstractUser', () { 73 | // given 74 | final user = UserImpl(id: 'xxx', email: 'x@x.com'); 75 | 76 | // when 77 | final map = JsonMapper.toMap(user)!; 78 | final newUser = JsonMapper.fromMap(map)!; 79 | 80 | // then 81 | expect(map.containsKey('@type'), true); 82 | expect(map['@type'], 'UserImpl'); 83 | 84 | expect(newUser.id, 'xxx'); 85 | expect(newUser.email, 'x@x.com'); 86 | }); 87 | 88 | test('Discriminator as of Type type', () { 89 | // given 90 | final childInstance = TypedChild(); 91 | 92 | // when 93 | final firstJson = JsonMapper.serialize(childInstance); 94 | final targetInstance = JsonMapper.deserialize(firstJson); 95 | final secondJson = JsonMapper.serialize(targetInstance); 96 | 97 | // then 98 | expect(targetInstance, TypeMatcher()); 99 | expect(firstJson, secondJson); 100 | }); 101 | 102 | test('Discriminator as of type String', () { 103 | // given 104 | final childInstance = TypedStringChild(); 105 | 106 | // when 107 | final firstJson = JsonMapper.serialize(childInstance); 108 | final targetInstance = 109 | JsonMapper.deserialize(firstJson); 110 | final secondJson = JsonMapper.serialize(targetInstance); 111 | 112 | // then 113 | expect(targetInstance, TypeMatcher()); 114 | expect(firstJson, secondJson); 115 | }); 116 | }); 117 | } 118 | -------------------------------------------------------------------------------- /models/unit_testing/lib/inheritance.dart: -------------------------------------------------------------------------------- 1 | import 'package:dart_json_mapper/dart_json_mapper.dart'; 2 | 3 | @jsonSerializable 4 | enum BusinessType { private, public, private2, public2 } 5 | 6 | /// Case 1: Using getter only as [discriminatorProperty] /////////////////////// 7 | @jsonSerializable 8 | @Json(discriminatorProperty: 'type') 9 | abstract class Business { 10 | BusinessType get type; 11 | } 12 | 13 | @jsonSerializable 14 | @Json(discriminatorValue: BusinessType.private) 15 | class Hotel extends Business { 16 | int stars; 17 | 18 | @override 19 | BusinessType get type => BusinessType.private; 20 | 21 | Hotel(this.stars); 22 | } 23 | 24 | @jsonSerializable 25 | @Json(discriminatorValue: BusinessType.public) 26 | class Startup extends Business { 27 | int userCount; 28 | 29 | @override 30 | BusinessType get type => BusinessType.public; 31 | 32 | Startup(this.userCount); 33 | } 34 | 35 | @jsonSerializable 36 | class Stakeholder { 37 | String fullName; 38 | List businesses; 39 | 40 | Stakeholder(this.fullName, this.businesses); 41 | } 42 | 43 | /// Case 2: Using writable property as [discriminatorProperty] ///////////////// 44 | @jsonSerializable 45 | @Json(discriminatorProperty: 'type') 46 | abstract class Business2 { 47 | BusinessType? type; 48 | } 49 | 50 | @jsonSerializable 51 | @Json(discriminatorValue: BusinessType.private2) 52 | class Hotel2 extends Business2 { 53 | int stars; 54 | 55 | Hotel2(this.stars); 56 | } 57 | 58 | @jsonSerializable 59 | @Json(discriminatorValue: BusinessType.public2) 60 | class Startup2 extends Business2 { 61 | int userCount; 62 | 63 | Startup2(this.userCount); 64 | } 65 | 66 | @jsonSerializable 67 | class Stakeholder2 { 68 | String fullName; 69 | List businesses; 70 | 71 | Stakeholder2(this.fullName, this.businesses); 72 | } 73 | 74 | /// Case 3: No [discriminatorProperty] exists on the class ///////////////////// 75 | class DataModel { 76 | String? id; 77 | DataModel({this.id}); 78 | } 79 | 80 | @jsonSerializable 81 | @Json(discriminatorProperty: '@type') 82 | abstract class AbstractUser extends DataModel { 83 | late final String? email; 84 | 85 | AbstractUser copyWith({ 86 | String? id, 87 | String? email, 88 | }); 89 | 90 | factory AbstractUser(String id) = UserImpl.newUser; 91 | } 92 | 93 | @jsonSerializable 94 | class UserImpl extends DataModel implements AbstractUser { 95 | @override 96 | late final String? email; 97 | 98 | UserImpl({String? id, this.email}) : super(id: id); 99 | 100 | factory UserImpl.newUser(String id) { 101 | return UserImpl( 102 | id: id, 103 | ); 104 | } 105 | 106 | @override 107 | AbstractUser copyWith({String? email, String? id}) { 108 | return UserImpl(id: id ?? this.id, email: email ?? this.email); 109 | } 110 | } 111 | 112 | @jsonSerializable 113 | abstract class MyBaseClass { 114 | @JsonProperty(name: 'myCustomGetterName') 115 | String get myGetter; 116 | 117 | @JsonProperty(name: 'myCustomFieldName') 118 | final String myField = ''; 119 | } 120 | 121 | @jsonSerializable 122 | class MySuperclass implements MyBaseClass { 123 | @override 124 | String get myGetter => 'myGetterValue'; 125 | 126 | @override 127 | final String myField = 'myFieldValue'; 128 | } 129 | 130 | /// Case 4: Discriminator as of Type type ///////////////////// 131 | @JsonSerializable() 132 | @Json(discriminatorProperty: 'type') 133 | abstract class TypedParent { 134 | @JsonProperty(ignore: true) 135 | Type get type => runtimeType; 136 | 137 | var a = 1; 138 | } 139 | 140 | @JsonSerializable() 141 | class TypedChild extends TypedParent { 142 | var b = "test"; 143 | } 144 | 145 | /// Case 5: Discriminator as of type String ///////////////////// 146 | @JsonSerializable() 147 | @Json(discriminatorProperty: 'type', discriminatorValue: 'p') 148 | abstract class TypedStringParent { 149 | String get type => 'p'; 150 | 151 | var a = 1; 152 | } 153 | 154 | @JsonSerializable() 155 | @Json(discriminatorValue: 'ch') 156 | class TypedStringChild extends TypedStringParent { 157 | @override 158 | String get type => 'ch'; 159 | 160 | var b = "test"; 161 | } 162 | -------------------------------------------------------------------------------- /mapper/lib/src/logic/converter_handler.dart: -------------------------------------------------------------------------------- 1 | import 'package:collection/collection.dart'; 2 | import 'package:dart_json_mapper/src/model/index.dart'; 3 | 4 | import '../mapper.dart'; 5 | 6 | class ConverterHandler { 7 | final JsonMapper _mapper; 8 | 9 | Map converters = {}; 10 | final Map< 11 | ICustomConverter?, 12 | Map>>> 14 | convertedValuesCache = {}; 15 | 16 | ConverterHandler(this._mapper); 17 | 18 | void clearCache() { 19 | convertedValuesCache.clear(); 20 | } 21 | 22 | ICustomConverter? getConverter( 23 | JsonProperty? jsonProperty, TypeInfo typeInfo) { 24 | final result = jsonProperty?.converter ?? 25 | converters[typeInfo.type!] ?? 26 | converters[typeInfo.genericType] ?? 27 | (_mapper.enumValues[typeInfo.type!] != null 28 | ? converters[Enum] 29 | : null) ?? 30 | converters[converters.keys.firstWhereOrNull( 31 | (Type type) => type.toString() == typeInfo.typeName)]; 32 | 33 | if (result is ICustomEnumConverter) { 34 | (result as ICustomEnumConverter) 35 | .setEnumDescriptor(getEnumDescriptor(_mapper.enumValues[typeInfo.type!])); 36 | } 37 | return result; 38 | } 39 | 40 | IEnumDescriptor? getEnumDescriptor(dynamic descriptor) { 41 | if (descriptor is Iterable) { 42 | return EnumDescriptor(values: descriptor); 43 | } 44 | if (descriptor is IEnumDescriptor) { 45 | return descriptor; 46 | } 47 | return null; 48 | } 49 | 50 | dynamic getConvertedValue( 51 | ICustomConverter converter, dynamic value, DeserializationContext context) { 52 | final direction = context.direction; 53 | if (convertedValuesCache.containsKey(converter) && 54 | convertedValuesCache[converter]!.containsKey(direction) && 55 | convertedValuesCache[converter]![direction]!.containsKey(context) && 56 | convertedValuesCache[converter]![direction]![context]! 57 | .containsKey(value)) { 58 | return convertedValuesCache[converter]![direction]![context]![value]; 59 | } 60 | 61 | final computedValue = direction == ConversionDirection.fromJson 62 | ? converter.fromJSON(value, context) 63 | : converter.toJSON(value, context as SerializationContext); 64 | convertedValuesCache.putIfAbsent( 65 | converter, 66 | () => { 67 | direction: { 68 | context: {value: computedValue} 69 | } 70 | }); 71 | convertedValuesCache[converter]!.putIfAbsent( 72 | direction, 73 | () => { 74 | context: {value: computedValue} 75 | }); 76 | convertedValuesCache[converter]![direction]! 77 | .putIfAbsent(context, () => {value: computedValue}); 78 | convertedValuesCache[converter]![direction]![context]! 79 | .putIfAbsent(value, () => computedValue); 80 | return computedValue; 81 | } 82 | 83 | void configureConverter( 84 | ICustomConverter converter, DeserializationContext context, 85 | {dynamic value}) { 86 | if (converter is ICompositeConverter) { 87 | (converter as ICompositeConverter).setGetConverterFunction(getConverter); 88 | (converter as ICompositeConverter) 89 | .setGetConvertedValueFunction(getConvertedValue); 90 | } 91 | if (converter is ICustomIterableConverter) { 92 | (converter as ICustomIterableConverter).setIterableInstance(value); 93 | } 94 | if (converter is ICustomMapConverter) { 95 | final instance = value ?? (context.options.template); 96 | (converter as ICustomMapConverter).setMapInstance(instance); 97 | } 98 | if (converter is IRecursiveConverter) { 99 | (converter as IRecursiveConverter).setSerializeObjectFunction( 100 | (o, context) => _mapper.serializationHandler.serializeObject(o, context)); 101 | (converter as IRecursiveConverter).setDeserializeObjectFunction((o, 102 | context, type) => 103 | _mapper.deserializationHandler.deserializeObject(o, context.reBuild(typeInfo: _mapper.typeInfoHandler.getTypeInfo(type)))); 104 | } 105 | } 106 | } -------------------------------------------------------------------------------- /perf-test/test/unit/test.integration.dart: -------------------------------------------------------------------------------- 1 | import 'package:dart_json_mapper/dart_json_mapper.dart'; 2 | import 'package:test/test.dart'; 3 | import 'package:unit_testing/unit_testing.dart' 4 | show 5 | Car, 6 | Color, 7 | Person, 8 | personJson, 9 | defaultOptions, 10 | ComposableCar, 11 | Wheel, 12 | Tire; 13 | 14 | void testIntegration() { 15 | group('[Verify end to end serialization <=> deserialization]', () { 16 | test('toMap/fromMap', () { 17 | // given 18 | final car = Car('Tesla S3', Color.black); 19 | // when 20 | final targetMap = JsonMapper.toMap(car)!; 21 | final targetCar = JsonMapper.fromMap(targetMap)!; 22 | 23 | // then 24 | expect(targetMap, TypeMatcher>()); 25 | expect(targetMap['modelName'], 'Tesla S3'); 26 | expect(targetMap['color'], 'black'); 27 | 28 | expect(targetCar, TypeMatcher()); 29 | expect(targetCar.model, 'Tesla S3'); 30 | expect(targetCar.color, Color.black); 31 | }); 32 | 33 | test('Object clone', () { 34 | // given 35 | final car = Car('Tesla S3', Color.black); 36 | // when 37 | final clone = JsonMapper.clone(car)!; 38 | 39 | // then 40 | expect(clone == car, false); 41 | expect(clone.color == car.color, true); 42 | expect(clone.model == car.model, true); 43 | }); 44 | 45 | test('Object copyWith', () { 46 | // given 47 | final car = Car('Tesla S3', Color.black); 48 | 49 | // when 50 | final instance = JsonMapper.copyWith(car, {'color': 'blue'})!; 51 | 52 | // then 53 | expect(instance == car, false); 54 | expect(instance.color, Color.blue); 55 | expect(instance.model, car.model); 56 | }); 57 | 58 | test('Object copyWith full depth', () { 59 | // given 60 | final car = ComposableCar( 61 | Wheel(Tire(0.2, Color.black)), Wheel(Tire(0.2, Color.black))); 62 | 63 | // when 64 | final instance = JsonMapper.copyWith(car, { 65 | 'leftWheel': { 66 | 'tire': {'thickness': 32} 67 | } 68 | })!; 69 | 70 | // then 71 | expect(instance == car, false); 72 | expect(instance.rightWheel.tire.thickness, 0.2); 73 | expect(instance.rightWheel.tire.color, Color.black); 74 | expect(instance.leftWheel.tire.thickness, 32); 75 | expect(instance.leftWheel.tire.color, Color.black); 76 | }); 77 | 78 | test('Serialize to target template map', () { 79 | // given 80 | final template = {'a': 'a', 'b': true}; 81 | // when 82 | final json = JsonMapper.serialize(Car('Tesla S3', Color.black), 83 | SerializationOptions(indent: '', template: template)); 84 | 85 | // then 86 | expect(json, 87 | '''{"a":"a","b":true,"modelName":"Tesla S3","color":"black"}'''); 88 | }); 89 | 90 | test('Serialization', () { 91 | // given 92 | // when 93 | final json = JsonMapper.serialize(Person(), defaultOptions); 94 | // then 95 | expect(json, personJson); 96 | }); 97 | 98 | test('Serialization <=> Deserialization', () { 99 | // given 100 | // when 101 | final stopwatch = Stopwatch()..start(); 102 | final person = JsonMapper.deserialize(personJson); 103 | final deserializationMs = stopwatch.elapsedMilliseconds; 104 | final json = JsonMapper.serialize(person, defaultOptions); 105 | print('Deserialization executed in $deserializationMs ms'); 106 | print( 107 | 'Serialization executed in ${stopwatch.elapsedMilliseconds - deserializationMs} ms'); 108 | // then 109 | expect(json, personJson); 110 | }); 111 | 112 | test('Deserialize with type property', () { 113 | // given 114 | final carJson = '{"modelName": "Tesla S3", "color": "black"}'; 115 | final type = Car; 116 | 117 | // when 118 | final instance = 119 | JsonMapper.deserialize(carJson, DeserializationOptions(type: type)); 120 | 121 | // then 122 | expect(instance.runtimeType, Car); 123 | expect(instance.color, Color.black); 124 | expect(instance.model, 'Tesla S3'); 125 | }); 126 | }); 127 | } 128 | -------------------------------------------------------------------------------- /perf-test/test/starlink/json_serializable/model.dart: -------------------------------------------------------------------------------- 1 | part of 'json_serializable_test.dart'; 2 | 3 | @JsonSerializable() 4 | class SpaceTrack { 5 | @JsonKey(name: 'CCSDS_OMM_VERS') 6 | String? ccsdsOmmVers; 7 | 8 | @JsonKey(name: 'COMMENT') 9 | String? comment; 10 | 11 | @JsonKey(name: 'ORIGINATOR') 12 | String? originator; 13 | 14 | @JsonKey(name: 'OBJECT_NAME') 15 | String? objectName; 16 | 17 | @JsonKey(name: 'OBJECT_ID') 18 | String? objectId; 19 | 20 | @JsonKey(name: 'OBJECT_TYPE') 21 | String? objectType; 22 | 23 | @JsonKey(name: 'CENTER_NAME') 24 | String? centerName; 25 | 26 | @JsonKey(name: 'REF_FRAME') 27 | String? refFrame; 28 | 29 | @JsonKey(name: 'TIME_SYSTEM') 30 | String? timeSystem; 31 | 32 | @JsonKey(name: 'MEAN_ELEMENT_THEORY') 33 | String? meanElementTheory; 34 | 35 | @JsonKey(name: 'CLASSIFICATION_TYPE') 36 | String? classificationType; 37 | 38 | @JsonKey(name: 'RCS_SIZE') 39 | String? rcsSize; 40 | 41 | @JsonKey(name: 'COUNTRY_CODE') 42 | String? countryCode; 43 | 44 | @JsonKey(name: 'SITE') 45 | String? site; 46 | 47 | @JsonKey(name: 'TLE_LINE0') 48 | String? tleLine0; 49 | 50 | @JsonKey(name: 'TLE_LINE1') 51 | String? tleLine1; 52 | 53 | @JsonKey(name: 'TLE_LINE2') 54 | String? tleLine2; 55 | 56 | @JsonKey(name: 'MEAN_MOTION') 57 | num? meanMotion; 58 | 59 | @JsonKey(name: 'ECCENTRICITY') 60 | num? eccentricity; 61 | 62 | @JsonKey(name: 'RA_OF_ASC_NODE') 63 | num? raOfAscNode; 64 | 65 | @JsonKey(name: 'ARG_OF_PERICENTER') 66 | num? argOfPericenter; 67 | 68 | @JsonKey(name: 'MEAN_ANOMALY') 69 | num? meanAnomaly; 70 | 71 | @JsonKey(name: 'EPHEMERIS_TYPE') 72 | num? ephemerisType; 73 | 74 | @JsonKey(name: 'NORAD_CAT_ID') 75 | num? noradCatId; 76 | 77 | @JsonKey(name: 'ELEMENT_SET_NO') 78 | num? elementSetNo; 79 | 80 | @JsonKey(name: 'REV_AT_EPOCH') 81 | num? revAtEpoch; 82 | 83 | @JsonKey(name: 'BSTAR') 84 | num? bstar; 85 | 86 | @JsonKey(name: 'MEAN_MOTION_DOT') 87 | num? meanMotionDot; 88 | 89 | @JsonKey(name: 'MEAN_MOTION_DDOT') 90 | num? meanMotionDdot; 91 | 92 | @JsonKey(name: 'SEMIMAJOR_AXIS') 93 | num? semimajorAxis; 94 | 95 | @JsonKey(name: 'PERIOD') 96 | num? period; 97 | 98 | @JsonKey(name: 'APOAPSIS') 99 | num? apoapsis; 100 | 101 | @JsonKey(name: 'PERIAPSIS') 102 | num? periapsis; 103 | 104 | @JsonKey(name: 'DECAYED') 105 | num? decayed; 106 | 107 | @JsonKey(name: 'FILE') 108 | num? file; 109 | 110 | @JsonKey(name: 'GP_ID') 111 | num? gpId; 112 | 113 | @JsonKey( 114 | name: 'DECAY_DATE', 115 | fromJson: _dateTimeFromStringDefault, 116 | toJson: _dateTimeToStringDefault) 117 | DateTime? decayDate; 118 | 119 | @JsonKey( 120 | name: 'CREATION_DATE', 121 | fromJson: _dateTimeFromStringDefault, 122 | toJson: _dateTimeToStringDefault) 123 | DateTime? creationDate; 124 | 125 | @JsonKey( 126 | name: 'EPOCH', 127 | fromJson: _dateTimeFromStringDefault, 128 | toJson: _dateTimeToStringDefault) 129 | DateTime? epoch; 130 | 131 | @JsonKey( 132 | name: 'LAUNCH_DATE', 133 | fromJson: _dateTimeFromString, 134 | toJson: _dateTimeToString) 135 | DateTime? launchDate; 136 | 137 | SpaceTrack(); 138 | 139 | static DateTime? _dateTimeFromString(String value) => 140 | DateFormat('yyyy-MM-dd').parse(value); 141 | 142 | static String? _dateTimeToString(DateTime? dateTime) => 143 | DateFormat('yyyy-MM-dd').format(dateTime!); 144 | 145 | static DateTime? _dateTimeFromStringDefault(dynamic value) => 146 | value is String ? DateTime.tryParse(value) : value; 147 | 148 | static String _dateTimeToStringDefault(DateTime? dateTime) => 149 | dateTime.toString(); 150 | 151 | factory SpaceTrack.fromJson(Map json) => 152 | _$SpaceTrackFromJson(json); 153 | 154 | Map toJson() => _$SpaceTrackToJson(this); 155 | } 156 | 157 | @JsonSerializable(explicitToJson: true) 158 | class Record { 159 | SpaceTrack? spaceTrack; 160 | String? version; 161 | String? id; 162 | String? launch; 163 | 164 | Record(); 165 | 166 | factory Record.fromJson(Map json) => _$RecordFromJson(json); 167 | 168 | Map toJson() => _$RecordToJson(this); 169 | } 170 | -------------------------------------------------------------------------------- /adapters/built/lib/dart_json_mapper_built.dart: -------------------------------------------------------------------------------- 1 | library json_mapper_built; 2 | 3 | import 'package:built_collection/built_collection.dart'; 4 | import 'package:dart_json_mapper/dart_json_mapper.dart' 5 | show 6 | DefaultTypeInfoDecorator, 7 | defaultIterableConverter, 8 | ICustomConverter, 9 | IRecursiveConverter, 10 | SerializeObjectFunction, 11 | DeserializeObjectFunction, 12 | TypeInfo, 13 | DeserializationContext, 14 | SerializationContext, 15 | JsonMapperAdapter; 16 | 17 | /// Shorthand for ready made decorator instance 18 | final builtTypeInfoDecorator = BuiltTypeInfoDecorator(); 19 | 20 | /// Type info decorator provides support for Built types like 21 | /// BuiltList, BuiltMap, BuiltSet 22 | class BuiltTypeInfoDecorator extends DefaultTypeInfoDecorator { 23 | final Map _collectionTypePredicates = { 24 | BuiltList: (TypeInfo typeInfo) => 25 | typeInfo.typeName!.startsWith('_BuiltList<') || 26 | typeInfo.typeName!.startsWith('BuiltList<'), 27 | BuiltMap: (TypeInfo typeInfo) => 28 | typeInfo.typeName!.startsWith('_BuiltMap<') || 29 | typeInfo.typeName!.startsWith('BuiltMap<'), 30 | BuiltSet: (TypeInfo typeInfo) => 31 | typeInfo.typeName!.startsWith('_BuiltSet<') || 32 | typeInfo.typeName!.startsWith('BuiltSet<'), 33 | }; 34 | 35 | @override 36 | TypeInfo decorate(TypeInfo typeInfo) { 37 | typeInfo = super.decorate(typeInfo); 38 | typeInfo.isList = 39 | typeInfo.isList || _collectionTypePredicates[BuiltList]!(typeInfo); 40 | typeInfo.isSet = 41 | typeInfo.isSet || _collectionTypePredicates[BuiltSet]!(typeInfo); 42 | typeInfo.isMap = 43 | typeInfo.isMap || _collectionTypePredicates[BuiltMap]!(typeInfo); 44 | typeInfo.isIterable = 45 | typeInfo.isIterable || typeInfo.isList || typeInfo.isSet; 46 | typeInfo.genericType = detectGenericType(typeInfo); 47 | return typeInfo; 48 | } 49 | 50 | @override 51 | Type? detectGenericType(TypeInfo typeInfo) { 52 | for (var entry in _collectionTypePredicates.entries) { 53 | if (entry.value(typeInfo)) { 54 | return entry.key; 55 | } 56 | } 57 | return super.detectGenericType(typeInfo); 58 | } 59 | } 60 | 61 | /// Shorthand for ready made converter instance 62 | final builtMapConverter = BuiltMapConverter(); 63 | 64 | /// [BuiltMap] converter 65 | class BuiltMapConverter implements ICustomConverter, IRecursiveConverter { 66 | BuiltMapConverter() : super(); 67 | 68 | late SerializeObjectFunction _serializeObject; 69 | late DeserializeObjectFunction _deserializeObject; 70 | 71 | @override 72 | dynamic fromJSON(dynamic jsonValue, DeserializationContext context) { 73 | if (context.typeInfo != null && jsonValue is Map) { 74 | return jsonValue.map((key, value) => MapEntry( 75 | _deserializeObject(key, context, context.typeInfo!.parameters.first), 76 | _deserializeObject( 77 | value, context, context.typeInfo!.parameters.last))); 78 | } 79 | return jsonValue; 80 | } 81 | 82 | @override 83 | dynamic toJSON(dynamic object, SerializationContext context) => 84 | (object as BuiltMap).toMap().map((key, value) => MapEntry( 85 | _serializeObject(key, context).toString(), 86 | _serializeObject(value, context))); 87 | 88 | @override 89 | void setSerializeObjectFunction(SerializeObjectFunction serializeObject) { 90 | _serializeObject = serializeObject; 91 | } 92 | 93 | @override 94 | void setDeserializeObjectFunction( 95 | DeserializeObjectFunction deserializeObject) { 96 | _deserializeObject = deserializeObject; 97 | } 98 | } 99 | 100 | /// Adapter definition, should be passed to the Json Mapper initialization method: 101 | /// initializeJsonMapper(adapters: [builtAdapter]); 102 | final builtAdapter = JsonMapperAdapter( 103 | title: 'Built Collection Adapter', 104 | refUrl: 'https://pub.dev/packages/built_collection', 105 | url: 106 | 'https://github.com/k-paxian/dart-json-mapper/tree/master/adapters/built', 107 | typeInfoDecorators: { 108 | 0: builtTypeInfoDecorator 109 | }, 110 | converters: { 111 | BuiltList: defaultIterableConverter, 112 | BuiltSet: defaultIterableConverter, 113 | BuiltMap: builtMapConverter, 114 | }); -------------------------------------------------------------------------------- /models/unit_testing/lib/generic.dart: -------------------------------------------------------------------------------- 1 | import 'package:dart_json_mapper/dart_json_mapper.dart'; 2 | 3 | import 'model.dart'; 4 | 5 | @jsonSerializable 6 | class Foo {} 7 | 8 | @jsonSerializable 9 | class BarBase { 10 | T? foo; 11 | 12 | BarBase({this.foo}); 13 | 14 | BarBase? fromJson(dynamic json) => 15 | JsonMapper.deserialize>(json); 16 | 17 | dynamic toJson() => 18 | JsonMapper.serialize(this, SerializationOptions(indent: '')); 19 | } 20 | 21 | @jsonSerializable 22 | @Json(valueDecorators: Bar.valueDecorators) 23 | class Bar extends BarBase { 24 | static Map valueDecorators() => 25 | {typeOf>(): (value) => Bar.of(value)}; 26 | 27 | Bar(); 28 | 29 | factory Bar.of(BarBase other) => Bar()..foo = other.foo; 30 | } 31 | 32 | @jsonSerializable 33 | @Json(discriminatorProperty: 'technicalName', ignoreNullMembers: true) 34 | class EntityModel { 35 | final String? parentUuid; 36 | final String? uuid; 37 | 38 | @JsonProperty(ignore: true) 39 | final T? entity; 40 | 41 | static Map entityProperties = {}; 42 | 43 | const EntityModel({this.parentUuid, this.uuid, this.entity}); 44 | 45 | factory EntityModel.of(EntityModel other) => EntityModel( 46 | parentUuid: other.parentUuid, uuid: other.uuid, entity: other.entity); 47 | 48 | @jsonProperty 49 | Map? entityToJson() => JsonMapper.toMap(entity); 50 | 51 | @jsonProperty 52 | void setEntityPropertyFromJson(String name, dynamic value) { 53 | entityProperties[name] = value; 54 | } 55 | 56 | T? newEntityFromModelJson(Map? entityModelJson) { 57 | fromJson(entityModelJson); 58 | return JsonMapper.fromMap(entityProperties); 59 | } 60 | 61 | T? newEntityFromJson(Map entityJson) => 62 | JsonMapper.fromMap(entityJson); 63 | 64 | EntityModel? fromJson(Map? modelJson) => 65 | JsonMapper.fromMap>(modelJson); 66 | 67 | Map? toJson() => JsonMapper.toMap(this); 68 | } 69 | 70 | @jsonSerializable 71 | @Json(discriminatorProperty: 'technicalName', ignoreNullMembers: true) 72 | abstract class AbstractEntityModel { 73 | final String? parentUuid; 74 | final String? uuid; 75 | 76 | const AbstractEntityModel({this.parentUuid, this.uuid}); 77 | 78 | T copyWith(); 79 | 80 | T merge(T other); 81 | 82 | T? fromJson(Map jsonData) { 83 | return JsonMapper.fromMap(jsonData); 84 | } 85 | 86 | Map? toJson() { 87 | return JsonMapper.toMap(this); 88 | } 89 | } 90 | 91 | @jsonSerializable 92 | class MyCarModel extends AbstractEntityModel { 93 | final String? model; 94 | final Color? color; 95 | 96 | const MyCarModel({String? parentUuid, String? uuid, this.model, this.color}) 97 | : super(parentUuid: parentUuid, uuid: uuid); 98 | 99 | @override 100 | Car copyWith() { 101 | return Car(model, color); 102 | } 103 | 104 | @override 105 | Car merge(Car other) { 106 | return Car(model ?? other.model, color ?? other.color); 107 | } 108 | } 109 | 110 | @jsonSerializable 111 | class ApiResult { 112 | bool? success; 113 | T? result; 114 | 115 | ApiResult({ 116 | this.success, 117 | this.result, 118 | }); 119 | 120 | ApiResult? fromJson(dynamic json) => 121 | JsonMapper.deserialize>(json); 122 | 123 | dynamic toJson() => JsonMapper.serialize(this, compactOptions); 124 | } 125 | 126 | @jsonSerializable 127 | class UserModel { 128 | int? id; 129 | String? name; 130 | 131 | UserModel({ 132 | this.id, 133 | this.name, 134 | }); 135 | } 136 | 137 | @jsonSerializable 138 | @Json(valueDecorators: ApiResultUserModel.valueDecorators) 139 | class ApiResultUserModel extends ApiResult { 140 | static Map valueDecorators() => 141 | {typeOf>(): (value) => ApiResultUserModel.of(value)}; 142 | 143 | ApiResultUserModel({ 144 | bool? success, 145 | UserModel? result, 146 | }) : super( 147 | success: success, 148 | result: result, 149 | ); 150 | 151 | factory ApiResultUserModel.of(ApiResult other) => ApiResultUserModel( 152 | success: other.success, 153 | result: JsonMapper.deserialize(other.result), 154 | ); 155 | } 156 | -------------------------------------------------------------------------------- /adapters/built/example/example.mapper.g.dart: -------------------------------------------------------------------------------- 1 | // This file has been generated by the dart_json_mapper package. 2 | // https://github.com/k-paxian/dart-json-mapper 3 | // @dart = 2.12 4 | import 'example.dart' as x0 show ImmutableClass; 5 | import 'package:dart_json_mapper/dart_json_mapper.dart' show JsonMapper, JsonMapperAdapter, typeOf; 6 | // This file has been generated by the reflectable package. 7 | // https://github.com/dart-lang/reflectable. 8 | 9 | 10 | import 'dart:core'; 11 | import 'example.dart' as prefix1; 12 | import 'package:built_collection/src/list.dart' as prefix2; 13 | import 'package:dart_json_mapper/src/model/annotations.dart' as prefix0; 14 | 15 | // ignore_for_file: prefer_adjacent_string_concatenation 16 | // ignore_for_file: prefer_collection_literals 17 | // ignore_for_file: unnecessary_const 18 | // ignore_for_file: implementation_imports 19 | 20 | // ignore:unused_import 21 | import 'package:reflectable/mirrors.dart' as m; 22 | // ignore:unused_import 23 | import 'package:reflectable/src/reflectable_builder_based.dart' as r; 24 | // ignore:unused_import 25 | import 'package:reflectable/reflectable.dart' as r show Reflectable; 26 | 27 | final _data = {const prefix0.JsonSerializable(): r.ReflectorData([r.NonGenericClassMirrorImpl(r'ImmutableClass', r'json_mapper_fixnum.example.ImmutableClass', 7, 0, const prefix0.JsonSerializable(), const [0, 2], const [3, 4, 5, 6, 7, 1], const [], -1, {}, {}, {r'': (bool b) => (list) => b ? prefix1.ImmutableClass(list) : null}, -1, 0, const [], const [prefix0.jsonSerializable], null)], [r.VariableMirrorImpl(r'list', 2130949, 0, const prefix0.JsonSerializable(), -1, 1, 2, const [3], const []), r.ImplicitGetterMirrorImpl(const prefix0.JsonSerializable(), 0, 1), r.MethodMirrorImpl(r'', 128, 0, -1, 0, 0, const [], const [0], const prefix0.JsonSerializable(), const []), r.MethodMirrorImpl(r'==', 131074, -1, -1, 4, 4, const [], const [1], const prefix0.JsonSerializable(), const []), r.MethodMirrorImpl(r'toString', 131074, -1, -1, 5, 5, const [], const [], const prefix0.JsonSerializable(), const []), r.MethodMirrorImpl(r'noSuchMethod', 65538, -1, -1, -1, -1, const [], const [2], const prefix0.JsonSerializable(), const []), r.MethodMirrorImpl(r'hashCode', 131075, -1, -1, 3, 3, const [], const [], const prefix0.JsonSerializable(), const []), r.MethodMirrorImpl(r'runtimeType', 131075, -1, -1, 6, 6, const [], const [], const prefix0.JsonSerializable(), const [])], [r.ParameterMirrorImpl(r'list', 2130950, 2, const prefix0.JsonSerializable(), -1, 1, 2, const [3], const [], null, null), r.ParameterMirrorImpl(r'other', 32774, 3, const prefix0.JsonSerializable(), -1, 7, 7, const [], const [], null, null), r.ParameterMirrorImpl(r'invocation', 32774, 5, const prefix0.JsonSerializable(), -1, 8, 8, const [], const [], null, null)], [prefix1.ImmutableClass, const m.TypeValue>().type, prefix2.BuiltList, int, bool, String, Type, Object, Invocation], 1, {r'==': (dynamic instance) => (x) => instance == x, r'toString': (dynamic instance) => instance.toString, r'noSuchMethod': (dynamic instance) => instance.noSuchMethod, r'hashCode': (dynamic instance) => instance.hashCode, r'runtimeType': (dynamic instance) => instance.runtimeType, r'list': (dynamic instance) => instance.list}, {}, null, [])}; 28 | 29 | 30 | final _memberSymbolMap = null; 31 | 32 | void _initializeReflectable(JsonMapperAdapter adapter) { 33 | if (!adapter.isGenerated) { 34 | return; 35 | } 36 | r.data = adapter.reflectableData!; 37 | r.memberSymbolMap = adapter.memberSymbolMap; 38 | } 39 | 40 | final exampleGeneratedAdapter = JsonMapperAdapter( 41 | title: 'Example Generated Adapter', 42 | url: 'asset:dart_json_mapper_built/example/example.dart', 43 | reflectableData: _data, 44 | memberSymbolMap: _memberSymbolMap, 45 | valueDecorators: { 46 | typeOf>(): (value) => value.cast(), 47 | typeOf>(): (value) => value.cast() 48 | }, 49 | enumValues: { 50 | 51 | }); 52 | 53 | Future initializeJsonMapperAsync({Iterable adapters = const []}) => Future(() => initializeJsonMapper(adapters: adapters)); 54 | 55 | JsonMapper initializeJsonMapper({Iterable adapters = const []}) { 56 | JsonMapper.enumerateAdapters([...adapters, exampleGeneratedAdapter], (JsonMapperAdapter adapter) { 57 | _initializeReflectable(adapter); 58 | JsonMapper().useAdapter(adapter); 59 | }); 60 | return JsonMapper(); 61 | } -------------------------------------------------------------------------------- /adapters/fixnum/example/example.mapper.g.dart: -------------------------------------------------------------------------------- 1 | // This file has been generated by the dart_json_mapper package. 2 | // https://github.com/k-paxian/dart-json-mapper 3 | // @dart = 2.12 4 | import 'example.dart' as x0 show Int32IntData; 5 | import 'package:dart_json_mapper/dart_json_mapper.dart' show JsonMapper, JsonMapperAdapter, typeOf; 6 | // This file has been generated by the reflectable package. 7 | // https://github.com/dart-lang/reflectable. 8 | 9 | 10 | import 'dart:core'; 11 | import 'example.dart' as prefix1; 12 | import 'package:dart_json_mapper/src/model/annotations.dart' as prefix0; 13 | import 'package:fixnum/fixnum.dart' as prefix2; 14 | 15 | // ignore_for_file: prefer_adjacent_string_concatenation 16 | // ignore_for_file: prefer_collection_literals 17 | // ignore_for_file: unnecessary_const 18 | // ignore_for_file: implementation_imports 19 | 20 | // ignore:unused_import 21 | import 'package:reflectable/mirrors.dart' as m; 22 | // ignore:unused_import 23 | import 'package:reflectable/src/reflectable_builder_based.dart' as r; 24 | // ignore:unused_import 25 | import 'package:reflectable/reflectable.dart' as r show Reflectable; 26 | 27 | final _data = {const prefix0.JsonSerializable(): r.ReflectorData([r.NonGenericClassMirrorImpl(r'Int32IntData', r'json_mapper_fixnum.example.Int32IntData', 7, 0, const prefix0.JsonSerializable(), const [0, 3], const [4, 5, 6, 7, 8, 1, 2], const [], -1, {}, {}, {r'': (bool b) => (int32) => b ? prefix1.Int32IntData(int32) : null}, -1, 0, const [], const [prefix0.jsonSerializable], null)], [r.VariableMirrorImpl(r'int32', 32773, 0, const prefix0.JsonSerializable(), -1, 1, 1, const [], const []), r.ImplicitGetterMirrorImpl(const prefix0.JsonSerializable(), 0, 1), r.ImplicitSetterMirrorImpl(const prefix0.JsonSerializable(), 0, 2), r.MethodMirrorImpl(r'', 0, 0, -1, 0, 0, const [], const [0], const prefix0.JsonSerializable(), const []), r.MethodMirrorImpl(r'==', 131074, -1, -1, 2, 2, const [], const [2], const prefix0.JsonSerializable(), const []), r.MethodMirrorImpl(r'toString', 131074, -1, -1, 3, 3, const [], const [], const prefix0.JsonSerializable(), const []), r.MethodMirrorImpl(r'noSuchMethod', 65538, -1, -1, -1, -1, const [], const [3], const prefix0.JsonSerializable(), const []), r.MethodMirrorImpl(r'hashCode', 131075, -1, -1, 4, 4, const [], const [], const prefix0.JsonSerializable(), const []), r.MethodMirrorImpl(r'runtimeType', 131075, -1, -1, 5, 5, const [], const [], const prefix0.JsonSerializable(), const [])], [r.ParameterMirrorImpl(r'int32', 33798, 3, const prefix0.JsonSerializable(), -1, 1, 1, const [], const [], null, null), r.ParameterMirrorImpl(r'_int32', 32870, 2, const prefix0.JsonSerializable(), -1, 1, 1, const [], const [], null, null), r.ParameterMirrorImpl(r'other', 32774, 4, const prefix0.JsonSerializable(), -1, 6, 6, const [], const [], null, null), r.ParameterMirrorImpl(r'invocation', 32774, 6, const prefix0.JsonSerializable(), -1, 7, 7, const [], const [], null, null)], [prefix1.Int32IntData, prefix2.Int32, bool, String, int, Type, Object, Invocation], 1, {r'==': (dynamic instance) => (x) => instance == x, r'toString': (dynamic instance) => instance.toString, r'noSuchMethod': (dynamic instance) => instance.noSuchMethod, r'hashCode': (dynamic instance) => instance.hashCode, r'runtimeType': (dynamic instance) => instance.runtimeType, r'int32': (dynamic instance) => instance.int32}, {r'int32=': (dynamic instance, value) => instance.int32 = value}, null, [])}; 28 | 29 | 30 | final _memberSymbolMap = null; 31 | 32 | void _initializeReflectable(JsonMapperAdapter adapter) { 33 | if (!adapter.isGenerated) { 34 | return; 35 | } 36 | r.data = adapter.reflectableData!; 37 | r.memberSymbolMap = adapter.memberSymbolMap; 38 | } 39 | 40 | final exampleGeneratedAdapter = JsonMapperAdapter( 41 | title: 'Example Generated Adapter', 42 | url: 'asset:dart_json_mapper_fixnum/example/example.dart', 43 | reflectableData: _data, 44 | memberSymbolMap: _memberSymbolMap, 45 | valueDecorators: { 46 | typeOf>(): (value) => value.cast(), 47 | typeOf>(): (value) => value.cast() 48 | }, 49 | enumValues: { 50 | 51 | }); 52 | 53 | Future initializeJsonMapperAsync({Iterable adapters = const []}) => Future(() => initializeJsonMapper(adapters: adapters)); 54 | 55 | JsonMapper initializeJsonMapper({Iterable adapters = const []}) { 56 | JsonMapper.enumerateAdapters([...adapters, exampleGeneratedAdapter], (JsonMapperAdapter adapter) { 57 | _initializeReflectable(adapter); 58 | JsonMapper().useAdapter(adapter); 59 | }); 60 | return JsonMapper(); 61 | } -------------------------------------------------------------------------------- /perf-test/test/unit/test.scheme.dart: -------------------------------------------------------------------------------- 1 | import 'package:dart_json_mapper/dart_json_mapper.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | enum Scheme { A, B } 5 | 6 | @jsonSerializable 7 | @Json(name: 'default') 8 | @Json(name: '_', scheme: Scheme.B) 9 | @Json(name: 'root', scheme: Scheme.A) 10 | class Object { 11 | @JsonProperty(name: 'title_test', scheme: Scheme.B) 12 | String title; 13 | 14 | Object(this.title); 15 | } 16 | 17 | @jsonSerializable 18 | @Json(name: 'Address') 19 | class Address { 20 | @JsonProperty(name: 'first_name', scheme: Scheme.B) 21 | @JsonProperty(name: 'firstname', scheme: Scheme.A) 22 | String? firstName; 23 | 24 | @JsonProperty(name: 'last_name', scheme: Scheme.B) 25 | @JsonProperty(name: 'lastname', scheme: Scheme.A) 26 | String? lastName; 27 | 28 | @JsonProperty(name: 'email', scheme: Scheme.B) 29 | @JsonProperty(name: 'email', scheme: Scheme.A) 30 | String? email; 31 | 32 | @JsonProperty(name: 'phone', scheme: Scheme.B) 33 | @JsonProperty(name: 'telephone', scheme: Scheme.A) 34 | String? phoneNumber; 35 | 36 | @JsonProperty(name: 'country', scheme: Scheme.B) 37 | @JsonProperty(name: 'country_id', scheme: Scheme.A) 38 | String? country; 39 | 40 | @JsonProperty(name: 'city', scheme: Scheme.B) 41 | @JsonProperty(name: 'city', scheme: Scheme.A) 42 | String? city; 43 | 44 | @JsonProperty(name: 'postcode', scheme: Scheme.B) 45 | @JsonProperty(name: 'postcode', scheme: Scheme.A) 46 | String? zipCode; 47 | 48 | @JsonProperty(name: 'address_1', scheme: Scheme.B) 49 | String? street; 50 | 51 | @JsonProperty(name: 'street', scheme: Scheme.A) 52 | List? streetList; 53 | 54 | String? id; 55 | String? district; 56 | 57 | static Address? fromJson(dynamic jsonValue, {Scheme scheme = Scheme.A}) => 58 | JsonMapper.fromJson
( 59 | jsonValue, 60 | DeserializationOptions( 61 | scheme: scheme, processAnnotatedMembersOnly: true)); 62 | 63 | @JsonConstructor(scheme: Scheme.B) 64 | Address.jsonTwo(); 65 | 66 | @JsonConstructor(scheme: Scheme.A) 67 | Address.jsonOne(@JsonProperty(name: 'id', scheme: Scheme.A) int id, 68 | this.streetList, this.city) 69 | : id = id.toString(), 70 | street = streetList?.elementAt(0), 71 | district = city; 72 | } 73 | 74 | void testScheme() { 75 | group('[Verify scheme processing]', () { 76 | test('Verify scheme A serialize', () { 77 | // given 78 | final instance = Object('Scheme A'); 79 | // when 80 | final json = JsonMapper.serialize( 81 | instance, SerializationOptions(indent: '', scheme: Scheme.A)); 82 | // then 83 | expect(json, '''{"root":{"title":"Scheme A"}}'''); 84 | }); 85 | 86 | test('Verify scheme A deserialize', () { 87 | // given 88 | final json = '''{"root":{"title":"Scheme A"}}'''; 89 | // when 90 | final instance = JsonMapper.deserialize( 91 | json, DeserializationOptions(scheme: Scheme.A))!; 92 | // then 93 | expect(instance, TypeMatcher()); 94 | expect(instance.title, 'Scheme A'); 95 | }); 96 | 97 | test('Verify scheme B serialize', () { 98 | // given 99 | final instance = Object('Scheme B'); 100 | // when 101 | final json = JsonMapper.serialize( 102 | instance, SerializationOptions(indent: '', scheme: Scheme.B)); 103 | // then 104 | expect(json, '''{"_":{"title_test":"Scheme B"}}'''); 105 | }); 106 | 107 | test('Verify scheme B deserialize', () { 108 | // given 109 | final json = '''{"_":{"title_test":"Scheme B"}}'''; 110 | // when 111 | final instance = JsonMapper.deserialize( 112 | json, DeserializationOptions(scheme: Scheme.B))!; 113 | // then 114 | expect(instance, TypeMatcher()); 115 | expect(instance.title, 'Scheme B'); 116 | }); 117 | 118 | test('Verify NO scheme serialize', () { 119 | // given 120 | final instance = Object('No Scheme'); 121 | // when 122 | final json = JsonMapper.serialize(instance); 123 | // then 124 | expect(json, '''{"default":{"title":"No Scheme"}}'''); 125 | }); 126 | 127 | test('Verify NO scheme deserialize', () { 128 | // given 129 | final json = '''{"default":{"title":"No Scheme"}}'''; 130 | // when 131 | final instance = JsonMapper.deserialize(json)!; 132 | // then 133 | expect(instance, TypeMatcher()); 134 | expect(instance.title, 'No Scheme'); 135 | }); 136 | 137 | test('Verify two @JsonConstructor', () { 138 | // given 139 | final json = '''{"id":5,"email":"a@a.com"}'''; 140 | 141 | // when 142 | final instance = Address.fromJson(json); 143 | 144 | // then 145 | expect(instance, TypeMatcher
()); 146 | }); 147 | }); 148 | } 149 | -------------------------------------------------------------------------------- /mapper/lib/src/model/index/context.dart: -------------------------------------------------------------------------------- 1 | import 'package:collection/collection.dart'; 2 | 3 | import '../../identifier_casing.dart'; 4 | import '../../json_map.dart'; 5 | import '../annotations.dart'; 6 | import '../type_info.dart'; 7 | import 'options.dart'; 8 | import 'conversion_direction.dart'; 9 | 10 | /// Describes a set of data / state to be re-used down the road of recursive 11 | /// process of Deserialization / Serialization 12 | class DeserializationContext { 13 | final DeserializationOptions options; 14 | final JsonProperty? jsonPropertyMeta; 15 | final Json? classMeta; 16 | final TypeInfo? typeInfo; 17 | final Iterable? parentJsonMaps; 18 | final Iterable? parentObjectInstances; 19 | 20 | const DeserializationContext(this.options, 21 | {this.jsonPropertyMeta, 22 | this.parentObjectInstances, 23 | this.classMeta, 24 | this.typeInfo, 25 | this.parentJsonMaps}); 26 | 27 | CaseStyle? getParentCaseStyle() { 28 | if (parentJsonMaps != null && parentJsonMaps!.isNotEmpty) { 29 | final parentJsonMap = parentJsonMaps! 30 | .firstWhereOrNull((element) => element.jsonMeta != null); 31 | return parentJsonMap != null && parentJsonMap.jsonMeta != null 32 | ? parentJsonMap.jsonMeta!.caseStyle 33 | : null; 34 | } 35 | return null; 36 | } 37 | 38 | CaseStyle? get caseStyle => (classMeta != null && classMeta!.caseStyle != null 39 | ? classMeta!.caseStyle 40 | : getParentCaseStyle() ?? options.caseStyle ?? defaultCaseStyle); 41 | 42 | CaseStyle? get targetCaseStyle => 43 | direction == ConversionDirection.fromJson ? defaultCaseStyle : caseStyle; 44 | 45 | CaseStyle? get sourceCaseStyle => 46 | direction == ConversionDirection.fromJson ? caseStyle : defaultCaseStyle; 47 | 48 | String transformIdentifier(String name) => direction == 49 | ConversionDirection.fromJson 50 | ? transformIdentifierCaseStyle(name, sourceCaseStyle, targetCaseStyle) 51 | : transformIdentifierCaseStyle(name, targetCaseStyle, sourceCaseStyle); 52 | 53 | ConversionDirection get direction => ConversionDirection.fromJson; 54 | 55 | DeserializationContext reBuild( 56 | {JsonProperty? jsonPropertyMeta, 57 | Json? classMeta, 58 | TypeInfo? typeInfo, 59 | Iterable? parentJsonMaps, 60 | Iterable? parentObjectInstances}) => 61 | DeserializationContext(options, 62 | jsonPropertyMeta: jsonPropertyMeta ?? this.jsonPropertyMeta, 63 | classMeta: classMeta ?? this.classMeta, 64 | typeInfo: typeInfo ?? this.typeInfo, 65 | parentJsonMaps: parentJsonMaps ?? this.parentJsonMaps, 66 | parentObjectInstances: 67 | parentObjectInstances ?? this.parentObjectInstances); 68 | 69 | @override 70 | int get hashCode => 71 | options.hashCode ^ jsonPropertyMeta.hashCode ^ classMeta.hashCode; 72 | 73 | @override 74 | bool operator ==(Object other) { 75 | final otherContext = (other as DeserializationContext); 76 | 77 | return otherContext.options == options && 78 | otherContext.jsonPropertyMeta == jsonPropertyMeta && 79 | otherContext.typeInfo == typeInfo && 80 | otherContext.classMeta == classMeta; 81 | } 82 | } 83 | 84 | /// Describes a set of data / state to be re-used down the road of recursive 85 | /// process of Serialization 86 | class SerializationContext extends DeserializationContext { 87 | /// Recursion nesting level, 0 = top object, 1 = object's property, and so on 88 | final int level; 89 | 90 | const SerializationContext(SerializationOptions super.options, 91 | {this.level = 0, 92 | super.jsonPropertyMeta, 93 | super.classMeta, 94 | super.typeInfo, 95 | super.parentJsonMaps, 96 | parentObjectInstance}) 97 | : super( 98 | parentObjectInstances: parentObjectInstance); 99 | 100 | SerializationOptions get serializationOptions => 101 | options as SerializationOptions; 102 | 103 | @override 104 | DeserializationContext reBuild( 105 | {int? level, 106 | JsonProperty? jsonPropertyMeta, 107 | Json? classMeta, 108 | TypeInfo? typeInfo, 109 | Iterable? parentJsonMaps, 110 | Iterable? parentObjectInstances}) => 111 | SerializationContext(serializationOptions, 112 | level: level ?? this.level, 113 | jsonPropertyMeta: jsonPropertyMeta ?? this.jsonPropertyMeta, 114 | classMeta: classMeta ?? this.classMeta, 115 | typeInfo: typeInfo ?? this.typeInfo, 116 | parentJsonMaps: parentJsonMaps ?? this.parentJsonMaps, 117 | parentObjectInstance: 118 | parentObjectInstances ?? this.parentObjectInstances); 119 | 120 | @override 121 | ConversionDirection get direction => ConversionDirection.toJson; 122 | } 123 | -------------------------------------------------------------------------------- /adapters/mobx/example/example.mapper.g.dart: -------------------------------------------------------------------------------- 1 | // This file has been generated by the dart_json_mapper v2.2.6 2 | // https://github.com/k-paxian/dart-json-mapper 3 | // @dart = 2.12 4 | import 'example.dart' as x0 show MobX; 5 | import 'package:dart_json_mapper/dart_json_mapper.dart' show JsonMapper, JsonMapperAdapter, typeOf; 6 | // This file has been generated by the reflectable package. 7 | // https://github.com/dart-lang/reflectable. 8 | 9 | 10 | import 'dart:core'; 11 | import 'example.dart' as prefix1; 12 | import 'package:dart_json_mapper/src/model/annotations.dart' as prefix0; 13 | import 'package:mobx/src/api/observable_collections.dart' as prefix2; 14 | 15 | // ignore_for_file: camel_case_types 16 | // ignore_for_file: implementation_imports 17 | // ignore_for_file: prefer_adjacent_string_concatenation 18 | // ignore_for_file: prefer_collection_literals 19 | // ignore_for_file: unnecessary_const 20 | 21 | // ignore:unused_import 22 | import 'package:reflectable/mirrors.dart' as m; 23 | // ignore:unused_import 24 | import 'package:reflectable/src/reflectable_builder_based.dart' as r; 25 | // ignore:unused_import 26 | import 'package:reflectable/reflectable.dart' as r show Reflectable; 27 | 28 | final _data = {const prefix0.JsonSerializable(): r.ReflectorData([r.NonGenericClassMirrorImpl(r'MobX', r'json_mapper_mobx.example.MobX', 134217735, 0, const prefix0.JsonSerializable(), const [0, 3], const [4, 5, 6, 7, 8, 1, 2], const [], -1, {}, {}, {r'': (bool b) => (mailingList) => b ? prefix1.MobX(mailingList) : null}, -1, 0, const [], const [prefix0.jsonSerializable], null)], [r.VariableMirrorImpl(r'mailingList', 151126021, 0, const prefix0.JsonSerializable(), -1, 1, 2, const [3], const []), r.ImplicitGetterMirrorImpl(const prefix0.JsonSerializable(), 0, 1), r.ImplicitSetterMirrorImpl(const prefix0.JsonSerializable(), 0, 2), r.MethodMirrorImpl(r'', 0, 0, -1, 0, 0, const [], const [0], const prefix0.JsonSerializable(), const []), r.MethodMirrorImpl(r'==', 2097154, -1, -1, 4, 4, const [], const [2], const prefix0.JsonSerializable(), const []), r.MethodMirrorImpl(r'toString', 2097154, -1, -1, 3, 3, const [], const [], const prefix0.JsonSerializable(), const []), r.MethodMirrorImpl(r'noSuchMethod', 524290, -1, -1, -1, -1, const [], const [3], const prefix0.JsonSerializable(), const []), r.MethodMirrorImpl(r'hashCode', 2097155, -1, -1, 5, 5, const [], const [], const prefix0.JsonSerializable(), const []), r.MethodMirrorImpl(r'runtimeType', 2097155, -1, -1, 6, 6, const [], const [], const prefix0.JsonSerializable(), const [])], [r.ParameterMirrorImpl(r'mailingList', 151127046, 3, const prefix0.JsonSerializable(), -1, 1, 2, const [3], const [], null, null), r.ParameterMirrorImpl(r'_mailingList', 151126118, 2, const prefix0.JsonSerializable(), -1, 1, 2, const [3], const [], null, null), r.ParameterMirrorImpl(r'other', 134348806, 4, const prefix0.JsonSerializable(), -1, 7, 7, const [], const [], null, null), r.ParameterMirrorImpl(r'invocation', 134348806, 6, const prefix0.JsonSerializable(), -1, 8, 8, const [], const [], null, null)], [prefix1.MobX, const m.TypeValue>().type, prefix2.ObservableList, String, bool, int, Type, Object, Invocation], 1, {r'==': (dynamic instance) => (x) => instance == x, r'toString': (dynamic instance) => instance.toString, r'noSuchMethod': (dynamic instance) => instance.noSuchMethod, r'hashCode': (dynamic instance) => instance.hashCode, r'runtimeType': (dynamic instance) => instance.runtimeType, r'mailingList': (dynamic instance) => instance.mailingList}, {r'mailingList=': (dynamic instance, value) => instance.mailingList = value}, null, [])}; 29 | 30 | 31 | final _memberSymbolMap = null; 32 | 33 | void _initializeReflectable(JsonMapperAdapter adapter) { 34 | if (!adapter.isGenerated) { 35 | return; 36 | } 37 | r.data = adapter.reflectableData!; 38 | r.memberSymbolMap = adapter.memberSymbolMap; 39 | } 40 | 41 | final exampleGeneratedAdapter = JsonMapperAdapter( 42 | title: 'dart_json_mapper_mobx', 43 | url: 'asset:dart_json_mapper_mobx/example/example.dart', 44 | refUrl: 'https://github.com/k-paxian/dart-json-mapper/tree/master/adapters/mobx', 45 | reflectableData: _data, 46 | memberSymbolMap: _memberSymbolMap, 47 | valueDecorators: { 48 | typeOf>(): (value) => value.cast(), 49 | typeOf>(): (value) => value.cast() 50 | }, 51 | enumValues: { 52 | 53 | }); 54 | 55 | Future initializeJsonMapperAsync({Iterable adapters = const []}) => Future(() => initializeJsonMapper(adapters: adapters)); 56 | 57 | JsonMapper initializeJsonMapper({Iterable adapters = const []}) { 58 | JsonMapper.enumerateAdapters([...adapters, exampleGeneratedAdapter], (JsonMapperAdapter adapter) { 59 | _initializeReflectable(adapter); 60 | JsonMapper().useAdapter(adapter); 61 | }); 62 | return JsonMapper(); 63 | } -------------------------------------------------------------------------------- /perf-test/test/starlink/built_value/model.dart: -------------------------------------------------------------------------------- 1 | part of 'built_value_test.dart'; 2 | 3 | abstract class SpaceTrack implements Built { 4 | SpaceTrack._(); 5 | 6 | // ignore: use_function_type_syntax_for_parameters 7 | factory SpaceTrack([updates(SpaceTrackBuilder b)]) = _$SpaceTrack; 8 | 9 | @BuiltValueField(wireName: 'CCSDS_OMM_VERS') 10 | String get cCSDSOMMVERS; 11 | 12 | @BuiltValueField(wireName: 'COMMENT') 13 | String get cOMMENT; 14 | 15 | @BuiltValueField(wireName: 'CREATION_DATE') 16 | String get cREATIONDATE; 17 | 18 | @BuiltValueField(wireName: 'ORIGINATOR') 19 | String get oRIGINATOR; 20 | 21 | @BuiltValueField(wireName: 'OBJECT_NAME') 22 | String get oBJECTNAME; 23 | 24 | @BuiltValueField(wireName: 'OBJECT_ID') 25 | String get oBJECTID; 26 | 27 | @BuiltValueField(wireName: 'CENTER_NAME') 28 | String get cENTERNAME; 29 | 30 | @BuiltValueField(wireName: 'REF_FRAME') 31 | String get rEFFRAME; 32 | 33 | @BuiltValueField(wireName: 'TIME_SYSTEM') 34 | String get tIMESYSTEM; 35 | 36 | @BuiltValueField(wireName: 'MEAN_ELEMENT_THEORY') 37 | String get mEANELEMENTTHEORY; 38 | 39 | @BuiltValueField(wireName: 'EPOCH') 40 | String get ePOCH; 41 | 42 | @BuiltValueField(wireName: 'MEAN_MOTION') 43 | num get mEANMOTION; 44 | 45 | @BuiltValueField(wireName: 'ECCENTRICITY') 46 | num get eCCENTRICITY; 47 | 48 | @BuiltValueField(wireName: 'INCLINATION') 49 | num get iNCLINATION; 50 | 51 | @BuiltValueField(wireName: 'RA_OF_ASC_NODE') 52 | num get rAOFASCNODE; 53 | 54 | @BuiltValueField(wireName: 'ARG_OF_PERICENTER') 55 | num get aRGOFPERICENTER; 56 | 57 | @BuiltValueField(wireName: 'MEAN_ANOMALY') 58 | num get mEANANOMALY; 59 | 60 | @BuiltValueField(wireName: 'EPHEMERIS_TYPE') 61 | num get ePHEMERISTYPE; 62 | 63 | @BuiltValueField(wireName: 'CLASSIFICATION_TYPE') 64 | String get cLASSIFICATIONTYPE; 65 | 66 | @BuiltValueField(wireName: 'NORAD_CAT_ID') 67 | num get nORADCATID; 68 | 69 | @BuiltValueField(wireName: 'ELEMENT_SET_NO') 70 | num get eLEMENTSETNO; 71 | 72 | @BuiltValueField(wireName: 'REV_AT_EPOCH') 73 | num get rEVATEPOCH; 74 | 75 | @BuiltValueField(wireName: 'BSTAR') 76 | num get bSTAR; 77 | 78 | @BuiltValueField(wireName: 'MEAN_MOTION_DOT') 79 | num get mEANMOTIONDOT; 80 | 81 | @BuiltValueField(wireName: 'MEAN_MOTION_DDOT') 82 | num get mEANMOTIONDDOT; 83 | 84 | @BuiltValueField(wireName: 'SEMIMAJOR_AXIS') 85 | num get sEMIMAJORAXIS; 86 | 87 | @BuiltValueField(wireName: 'PERIOD') 88 | num get pERIOD; 89 | 90 | @BuiltValueField(wireName: 'APOAPSIS') 91 | num get aPOAPSIS; 92 | 93 | @BuiltValueField(wireName: 'PERIAPSIS') 94 | num get pERIAPSIS; 95 | 96 | @BuiltValueField(wireName: 'OBJECT_TYPE') 97 | String get oBJECTTYPE; 98 | 99 | @BuiltValueField(wireName: 'RCS_SIZE') 100 | String get rCSSIZE; 101 | 102 | @BuiltValueField(wireName: 'COUNTRY_CODE') 103 | String get cOUNTRYCODE; 104 | 105 | @BuiltValueField(wireName: 'LAUNCH_DATE') 106 | String get lAUNCHDATE; 107 | 108 | @BuiltValueField(wireName: 'SITE') 109 | String get sITE; 110 | 111 | @BuiltValueField(wireName: 'DECAY_DATE') 112 | String? get dECAYDATE; 113 | 114 | @BuiltValueField(wireName: 'DECAYED') 115 | num get dECAYED; 116 | 117 | @BuiltValueField(wireName: 'FILE') 118 | num get fILE; 119 | 120 | @BuiltValueField(wireName: 'GP_ID') 121 | num get gPID; 122 | 123 | @BuiltValueField(wireName: 'TLE_LINE0') 124 | String get tLELINE0; 125 | 126 | @BuiltValueField(wireName: 'TLE_LINE1') 127 | String get tLELINE1; 128 | 129 | @BuiltValueField(wireName: 'TLE_LINE2') 130 | String get tLELINE2; 131 | 132 | String toJson() { 133 | return json.encode(serializers.serializeWith(SpaceTrack.serializer, this)); 134 | } 135 | 136 | static SpaceTrack? fromJson(String jsonString) { 137 | return serializers.deserializeWith( 138 | SpaceTrack.serializer, json.decode(jsonString)); 139 | } 140 | 141 | static Serializer get serializer => _$spaceTrackSerializer; 142 | } 143 | 144 | abstract class Record implements Built { 145 | Record._(); 146 | 147 | // ignore: use_function_type_syntax_for_parameters 148 | factory Record([updates(RecordBuilder b)]) = _$Record; 149 | 150 | @BuiltValueField(wireName: 'spaceTrack') 151 | SpaceTrack get spaceTrack; 152 | 153 | @BuiltValueField(wireName: 'version') 154 | String get version; 155 | 156 | @BuiltValueField(wireName: 'launch') 157 | String get launch; 158 | 159 | @BuiltValueField(wireName: 'id') 160 | String get id; 161 | 162 | String toJson() { 163 | return json.encode(serializers.serializeWith(Record.serializer, this)); 164 | } 165 | 166 | static Record? fromJson(String jsonString) { 167 | return serializers.deserializeWith( 168 | Record.serializer, json.decode(jsonString)); 169 | } 170 | 171 | static Serializer get serializer => _$recordSerializer; 172 | } 173 | -------------------------------------------------------------------------------- /perf-test/test/unit/test.collections.dart: -------------------------------------------------------------------------------- 1 | import 'dart:collection'; 2 | 3 | import 'package:dart_json_mapper/dart_json_mapper.dart'; 4 | import 'package:test/test.dart'; 5 | 6 | void testCollections() { 7 | group('[Verify Dart Collection cases]', () { 8 | test('UnmodifiableMapView', () { 9 | // given 10 | final instance = UnmodifiableMapView({'a': 1, 'b': 2, 'c': 3}); 11 | final adapter = JsonMapperAdapter(valueDecorators: { 12 | typeOf>(): (value) => 13 | UnmodifiableMapView(value.cast()) 14 | }); 15 | JsonMapper().useAdapter(adapter); 16 | 17 | // when 18 | final json = JsonMapper.serialize(instance); 19 | final target = 20 | JsonMapper.deserialize>(json)!; 21 | 22 | // then 23 | expect(json, '{"a":1,"b":2,"c":3}'); 24 | 25 | expect(target, TypeMatcher>()); 26 | expect(target.containsKey('a'), true); 27 | expect(target['a'], 1); 28 | expect(target.containsKey('b'), true); 29 | expect(target['b'], 2); 30 | expect(target.containsKey('c'), true); 31 | expect(target['c'], 3); 32 | 33 | JsonMapper().removeAdapter(adapter); 34 | }); 35 | 36 | test('UnmodifiableListView', () { 37 | // given 38 | final instance = UnmodifiableListView([1, 2, 3]); 39 | final adapter = JsonMapperAdapter(valueDecorators: { 40 | typeOf>(): (value) => 41 | UnmodifiableListView(value.cast()) 42 | }); 43 | JsonMapper().useAdapter(adapter); 44 | 45 | // when 46 | final json = JsonMapper.serialize(instance); 47 | final target = JsonMapper.deserialize>(json)!; 48 | 49 | // then 50 | expect(json, '[1,2,3]'); 51 | 52 | expect(target, TypeMatcher>()); 53 | expect(target.first, 1); 54 | expect(target.last, 3); 55 | 56 | JsonMapper().removeAdapter(adapter); 57 | }); 58 | 59 | test('HashSet', () { 60 | // given 61 | final instance = HashSet.of([1, 2, 3]); 62 | final adapter = JsonMapperAdapter(valueDecorators: { 63 | typeOf>(): (value) => 64 | HashSet.of(value.cast().toList()) 65 | }); 66 | JsonMapper().useAdapter(adapter); 67 | 68 | // when 69 | final json = JsonMapper.serialize(instance); 70 | final target = JsonMapper.deserialize>(json)!; 71 | 72 | // then 73 | expect(json, '[1,2,3]'); 74 | 75 | expect(target, TypeMatcher>()); 76 | expect(target.first, 1); 77 | expect(target.last, 3); 78 | 79 | JsonMapper().removeAdapter(adapter); 80 | }); 81 | 82 | test('HashMap', () { 83 | // given 84 | final instance = HashMap.of({'a': 1, 'b': 2, 'c': 3}); 85 | final adapter = JsonMapperAdapter(valueDecorators: { 86 | typeOf>(): (value) => 87 | HashMap.of(value.cast()) 88 | }); 89 | JsonMapper().useAdapter(adapter); 90 | 91 | // when 92 | final json = JsonMapper.serialize(instance); 93 | final target = JsonMapper.deserialize>(json)!; 94 | 95 | // then 96 | expect(json, kIsWeb ? '{"a":1,"b":2,"c":3}' : '{"c":3,"a":1,"b":2}'); 97 | 98 | expect(target, TypeMatcher>()); 99 | expect(target.containsKey('a'), true); 100 | expect(target['a'], 1); 101 | expect(target.containsKey('b'), true); 102 | expect(target['b'], 2); 103 | expect(target.containsKey('c'), true); 104 | expect(target['c'], 3); 105 | 106 | JsonMapper().removeAdapter(adapter); 107 | }); 108 | 109 | test('HashMap', () { 110 | // given 111 | final instance = HashMap.of({1: 'a', 2: 'b', 3: 'c'}); 112 | final adapter = JsonMapperAdapter(valueDecorators: { 113 | typeOf>(): (value) => HashMap.of( 114 | value.map((key, value) => MapEntry(key, value)).cast()) 115 | }); 116 | JsonMapper().useAdapter(adapter); 117 | 118 | // when 119 | final json = JsonMapper.serialize(instance); 120 | final target = JsonMapper.deserialize>(json)!; 121 | 122 | // then 123 | // https://stackoverflow.com/questions/9304528/why-json-allows-only-string-to-be-a-key 124 | expect(json, '{"1":"a","2":"b","3":"c"}'); 125 | 126 | expect(target, TypeMatcher>()); 127 | expect(target.containsKey(1), true); 128 | expect(target[1], 'a'); 129 | expect(target.containsKey(2), true); 130 | expect(target[2], 'b'); 131 | expect(target.containsKey(3), true); 132 | expect(target[3], 'c'); 133 | 134 | JsonMapper().removeAdapter(adapter); 135 | }); 136 | }); 137 | } 138 | -------------------------------------------------------------------------------- /perf-test/test/unit/test.default.value.dart: -------------------------------------------------------------------------------- 1 | import 'package:dart_json_mapper/dart_json_mapper.dart'; 2 | import 'package:test/test.dart'; 3 | import 'package:unit_testing/unit_testing.dart' show defaultOptions, Car, Color; 4 | 5 | @jsonSerializable 6 | class CropArea { 7 | num? top; 8 | num? left; 9 | num? right; 10 | num? bottom; 11 | } 12 | 13 | @jsonSerializable 14 | class ImmutableDefault { 15 | @JsonProperty( 16 | defaultValue: {'top': 0.0, 'left': 1.0, 'right': 1.0, 'bottom': 0.0}) 17 | final CropArea? cropArea; 18 | 19 | @JsonProperty(defaultValue: 1) 20 | final int? id; 21 | final String? name; 22 | final Car? car; 23 | 24 | const ImmutableDefault({this.cropArea, this.id, this.name, this.car}); 25 | } 26 | 27 | @jsonSerializable 28 | class DefaultFields { 29 | @JsonProperty( 30 | defaultValue: {'top': 0.0, 'left': 1.0, 'right': 1.0, 'bottom': 0.0}, 31 | ignoreIfDefault: true) 32 | CropArea? cropArea; 33 | 34 | @JsonProperty(defaultValue: 1) 35 | int? id; 36 | } 37 | 38 | @jsonSerializable 39 | @Json(ignoreDefaultMembers: true) 40 | class ManyDefaultFields { 41 | @JsonProperty( 42 | defaultValue: {'top': 0.0, 'left': 1.0, 'right': 1.0, 'bottom': 0.0}) 43 | CropArea? cropArea; 44 | 45 | @JsonProperty(defaultValue: 1) 46 | int? id; 47 | } 48 | 49 | @jsonSerializable 50 | class GlobalDefaultFields { 51 | @JsonProperty( 52 | defaultValue: {'top': 0.0, 'left': 1.0, 'right': 1.0, 'bottom': 0.0}) 53 | CropArea? cropArea; 54 | 55 | @JsonProperty(defaultValue: 1) 56 | int? id; 57 | } 58 | 59 | @jsonSerializable 60 | class DefaultValueOverrideTest { 61 | @JsonProperty(defaultValue: 4) 62 | int value; 63 | DefaultValueOverrideTest(this.value); 64 | } 65 | 66 | void testDefaultValue() { 67 | group('[Verify default value cases]', () { 68 | test('Override default value by the json value', () { 69 | // given 70 | final json1 = '''{"value":12}'''; 71 | final json2 = '''{}'''; 72 | // when 73 | final target1 = JsonMapper.deserialize(json1); 74 | final target2 = JsonMapper.deserialize(json2); 75 | // then 76 | expect(target1!.value, 12); 77 | expect(target2!.value, 4); 78 | }); 79 | 80 | test('Ignore default field via field annotation', () { 81 | // given 82 | final instance = DefaultFields(); 83 | // when 84 | final target = JsonMapper.serialize(instance); 85 | // then 86 | expect(target, '{"id":1}'); 87 | }); 88 | 89 | test('Ignore default fields via class annotation', () { 90 | // given 91 | final instance = ManyDefaultFields(); 92 | // when 93 | final target = JsonMapper.serialize(instance); 94 | // then 95 | expect(target, '{}'); 96 | }); 97 | 98 | test('Ignore default fields via serialization options', () { 99 | // given 100 | final instance = GlobalDefaultFields(); 101 | // when 102 | final target = JsonMapper.serialize(instance, 103 | SerializationOptions(indent: '', ignoreDefaultMembers: true)); 104 | // then 105 | expect(target, '{}'); 106 | }); 107 | 108 | test('processAnnotatedMembersOnly global option', () { 109 | // given 110 | final instance = ImmutableDefault(); 111 | // when 112 | final target = JsonMapper.serialize(instance, 113 | SerializationOptions(indent: '', processAnnotatedMembersOnly: true)); 114 | // then 115 | expect( 116 | target, 117 | kIsWeb 118 | ? '{"cropArea":{"top":0,"left":1,"right":1,"bottom":0},"id":1}' 119 | : '{"cropArea":{"top":0.0,"left":1.0,"right":1.0,"bottom":0.0},"id":1}'); 120 | }); 121 | 122 | test('Serialize Immutable class with DefaultValue provided', () { 123 | // given 124 | final immutableJsonWeb = '''{ 125 | "cropArea": { 126 | "top": 0, 127 | "left": 1, 128 | "right": 1, 129 | "bottom": 0 130 | }, 131 | "id": 1, 132 | "name": "Bob", 133 | "car": { 134 | "modelName": "Audi", 135 | "color": "green" 136 | } 137 | }'''; 138 | final immutableJson = '''{ 139 | "cropArea": { 140 | "top": 0.0, 141 | "left": 1.0, 142 | "right": 1.0, 143 | "bottom": 0.0 144 | }, 145 | "id": 1, 146 | "name": "Bob", 147 | "car": { 148 | "modelName": "Audi", 149 | "color": "green" 150 | } 151 | }'''; 152 | 153 | final json = '''{ 154 | "name": "Bob", 155 | "car": { 156 | "modelName": "Audi", 157 | "color": "Green" 158 | } 159 | }'''; 160 | final i = ImmutableDefault(name: 'Bob', car: Car('Audi', Color.green)); 161 | 162 | // when 163 | final targetJson = JsonMapper.serialize(i, defaultOptions); 164 | final target = JsonMapper.deserialize(json)!; 165 | 166 | // then 167 | expect(targetJson, kIsWeb ? immutableJsonWeb : immutableJson); 168 | 169 | expect(target.id, 1); 170 | expect(target.cropArea, TypeMatcher()); 171 | expect(target.cropArea!.left, 1); 172 | expect(target.cropArea!.right, 1); 173 | expect(target.cropArea!.bottom, 0); 174 | }); 175 | }); 176 | } 177 | -------------------------------------------------------------------------------- /perf-test/test/unit/test.raw_json.dart: -------------------------------------------------------------------------------- 1 | import 'package:test/test.dart'; 2 | import 'package:dart_json_mapper/dart_json_mapper.dart'; 3 | // Import for initializeJsonMapper removed as per subtask 4 | 5 | @jsonSerializable 6 | class RawJsonTestModel { 7 | @JsonProperty(name: 'rawField', rawJson: true) 8 | String? rawField; 9 | 10 | @JsonProperty(name: 'normalField') 11 | String? normalField; 12 | 13 | String? noAnnotationField; 14 | 15 | RawJsonTestModel({this.rawField, this.normalField, this.noAnnotationField}); 16 | } 17 | 18 | void main() { 19 | // setUpAll block removed as per subtask 20 | 21 | group('RawJson Serialization Tests', () { 22 | test('Serialization - rawJson with valid JSON object string', () { 23 | final model = RawJsonTestModel(rawField: '{"key": "value"}'); 24 | final json = JsonMapper.serialize(model); 25 | expect(json, contains('"rawField":{"key":"value"}')); 26 | expect(json, isNot(contains('"rawField":"{\\"key\\":\\"value\\"}"'))); 27 | }); 28 | 29 | test('Serialization - rawJson with valid JSON array string', () { 30 | final model = RawJsonTestModel(rawField: '[1, 2, 3]'); 31 | final json = JsonMapper.serialize(model); 32 | expect(json, contains('"rawField":[1,2,3]')); 33 | expect(json, isNot(contains('"rawField":"[1,2,3]"'))); 34 | }); 35 | 36 | test('Serialization - rawJson with invalid JSON string', () { 37 | final model = RawJsonTestModel(rawField: 'not actually json'); 38 | final json = JsonMapper.serialize(model); 39 | expect(json, contains('"rawField":"not actually json"')); 40 | }); 41 | 42 | test('Serialization - rawJson with null rawField', () { 43 | final model = RawJsonTestModel(rawField: null); 44 | final json = JsonMapper.serialize(model); 45 | expect(json, contains('"rawField":null')); 46 | }); 47 | 48 | test('Serialization - normalField with string value', () { 49 | final model = RawJsonTestModel(normalField: 'a normal string'); 50 | final json = JsonMapper.serialize(model); 51 | expect(json, contains('"normalField":"a normal string"')); 52 | }); 53 | 54 | test('Serialization - noAnnotationField with string value', () { 55 | final model = RawJsonTestModel(noAnnotationField: 'no annotation'); 56 | final json = JsonMapper.serialize(model); 57 | expect(json, contains('"noAnnotationField":"no annotation"')); 58 | }); 59 | }); 60 | 61 | group('RawJson Deserialization Tests', () { 62 | test('Deserialization - rawJson with JSON object', () { 63 | final json = '{"rawField": {"id": 2, "data": "content"}}'; 64 | final model = JsonMapper.deserialize(json)!; 65 | expect(model.rawField, '{"id":2,"data":"content"}'); 66 | }); 67 | 68 | test('Deserialization - rawJson with JSON array', () { 69 | final json = '{"rawField": [1, 2, 3, "test"]}'; 70 | final model = JsonMapper.deserialize(json)!; 71 | expect(model.rawField, '[1,2,3,"test"]'); 72 | }); 73 | 74 | test('Deserialization - rawJson with JSON string', () { 75 | final json = '{"rawField": "a string value"}'; 76 | final model = JsonMapper.deserialize(json)!; 77 | expect(model.rawField, 'a string value'); 78 | }); 79 | 80 | test('Deserialization - rawJson with null', () { 81 | final json = '{"rawField": null}'; 82 | final model = JsonMapper.deserialize(json)!; 83 | expect(model.rawField, isNull); 84 | }); 85 | 86 | test('Deserialization - normalField with string value', () { 87 | final json = '{"normalField": "a normal string value"}'; 88 | final model = JsonMapper.deserialize(json)!; 89 | expect(model.normalField, 'a normal string value'); 90 | }); 91 | 92 | test('Deserialization - noAnnotationField with string value', () { 93 | final json = '{"noAnnotationField": "no annotation value"}'; 94 | final model = JsonMapper.deserialize(json)!; 95 | expect(model.noAnnotationField, 'no annotation value'); 96 | }); 97 | 98 | test('Deserialization - all fields', () { 99 | final json = ''' 100 | { 101 | "rawField": {"complex": [1, {"nested": "object"}]}, 102 | "normalField": "normal text", 103 | "noAnnotationField": "unannotated text" 104 | } 105 | '''; 106 | final model = JsonMapper.deserialize(json)!; 107 | expect(model.rawField, '{"complex":[1,{"nested":"object"}]}'); 108 | expect(model.normalField, 'normal text'); 109 | expect(model.noAnnotationField, 'unannotated text'); 110 | }); 111 | 112 | test('Deserialization - rawJson with number', () { 113 | final json = '{"rawField": 123}'; 114 | final model = JsonMapper.deserialize(json)!; 115 | expect(model.rawField, '123'); 116 | }); 117 | 118 | test('Deserialization - rawJson with boolean', () { 119 | final json = '{"rawField": true}'; 120 | final model = JsonMapper.deserialize(json)!; 121 | expect(model.rawField, 'true'); 122 | }); 123 | }); 124 | } 125 | -------------------------------------------------------------------------------- /adapters/flutter/example/example.mapper.g.dart: -------------------------------------------------------------------------------- 1 | // This file has been generated by the dart_json_mapper v2.2.9 2 | // https://github.com/k-paxian/dart-json-mapper 3 | // @dart = 2.12 4 | import 'example.dart' as x0 show FlutterClass; 5 | import 'package:dart_json_mapper/dart_json_mapper.dart' show JsonMapper, JsonMapperAdapter, SerializationOptions, DeserializationOptions, typeOf; 6 | // This file has been generated by the reflectable package. 7 | // https://github.com/dart-lang/reflectable. 8 | 9 | import 'dart:core'; 10 | import 'dart:ui' as prefix2; 11 | import 'example.dart' as prefix1; 12 | import 'package:dart_json_mapper/src/model/annotations.dart' as prefix0; 13 | 14 | // ignore_for_file: camel_case_types 15 | // ignore_for_file: implementation_imports 16 | // ignore_for_file: prefer_adjacent_string_concatenation 17 | // ignore_for_file: prefer_collection_literals 18 | // ignore_for_file: unnecessary_const 19 | 20 | // ignore:unused_import 21 | import 'package:reflectable/mirrors.dart' as m; 22 | // ignore:unused_import 23 | import 'package:reflectable/src/reflectable_builder_based.dart' as r; 24 | // ignore:unused_import 25 | import 'package:reflectable/reflectable.dart' as r show Reflectable; 26 | 27 | final _data = {const prefix0.JsonSerializable(): r.ReflectorData([r.NonGenericClassMirrorImpl(r'FlutterClass', r'json_mapper_flutter.example.FlutterClass', 134217735, 0, const prefix0.JsonSerializable(), const [0, 3], const [4, 5, 6, 7, 8, 1, 2], const [], -1, {}, {}, {r'': (bool b) => (color) => b ? prefix1.FlutterClass(color) : null}, -1, 0, const [], const [prefix0.jsonSerializable], null)], [r.VariableMirrorImpl(r'color', 134348805, 0, const prefix0.JsonSerializable(), -1, 1, 1, const [], const []), r.ImplicitGetterMirrorImpl(const prefix0.JsonSerializable(), 0, 1), r.ImplicitSetterMirrorImpl(const prefix0.JsonSerializable(), 0, 2), r.MethodMirrorImpl(r'', 0, 0, -1, 0, 0, const [], const [0], const prefix0.JsonSerializable(), const []), r.MethodMirrorImpl(r'==', 2097154, -1, -1, 2, 2, const [], const [2], const prefix0.JsonSerializable(), const []), r.MethodMirrorImpl(r'toString', 2097154, -1, -1, 3, 3, const [], const [], const prefix0.JsonSerializable(), const []), r.MethodMirrorImpl(r'noSuchMethod', 524290, -1, -1, -1, -1, const [], const [3], const prefix0.JsonSerializable(), const []), r.MethodMirrorImpl(r'hashCode', 2097155, -1, -1, 4, 4, const [], const [], const prefix0.JsonSerializable(), const []), r.MethodMirrorImpl(r'runtimeType', 2097155, -1, -1, 5, 5, const [], const [], const prefix0.JsonSerializable(), const [])], [r.ParameterMirrorImpl(r'color', 134349830, 3, const prefix0.JsonSerializable(), -1, 1, 1, const [], const [], null, null), r.ParameterMirrorImpl(r'_color', 134348902, 2, const prefix0.JsonSerializable(), -1, 1, 1, const [], const [], null, null), r.ParameterMirrorImpl(r'other', 134348806, 4, const prefix0.JsonSerializable(), -1, 6, 6, const [], const [], null, null), r.ParameterMirrorImpl(r'invocation', 134348806, 6, const prefix0.JsonSerializable(), -1, 7, 7, const [], const [], null, null)], [prefix1.FlutterClass, prefix2.Color, bool, String, int, Type, Object, Invocation], 1, {r'==': (dynamic instance) => (x) => instance == x, r'toString': (dynamic instance) => instance.toString, r'noSuchMethod': (dynamic instance) => instance.noSuchMethod, r'hashCode': (dynamic instance) => instance.hashCode, r'runtimeType': (dynamic instance) => instance.runtimeType, r'color': (dynamic instance) => instance.color}, {r'color=': (dynamic instance, value) => instance.color = value}, null, [])}; 28 | 29 | 30 | final _memberSymbolMap = null; 31 | 32 | void _initializeReflectable(JsonMapperAdapter adapter) { 33 | if (!adapter.isGenerated) { 34 | return; 35 | } 36 | r.data = adapter.reflectableData!; 37 | r.memberSymbolMap = adapter.memberSymbolMap; 38 | } 39 | 40 | final exampleGeneratedAdapter = JsonMapperAdapter( 41 | title: 'dart_json_mapper_flutter', 42 | url: 'asset:dart_json_mapper_flutter/example/example.dart', 43 | refUrl: 'https://github.com/k-paxian/dart-json-mapper/tree/master/adapters/flutter', 44 | reflectableData: _data, 45 | memberSymbolMap: _memberSymbolMap, 46 | valueDecorators: { 47 | typeOf>(): (value) => value.cast(), 48 | typeOf>(): (value) => value.cast() 49 | }, 50 | enumValues: { 51 | 52 | }); 53 | 54 | Future initializeJsonMapperAsync({Iterable adapters = const [], SerializationOptions? serializationOptions, DeserializationOptions? deserializationOptions}) => Future(() => initializeJsonMapper(adapters: adapters, serializationOptions: serializationOptions, deserializationOptions: deserializationOptions)); 55 | 56 | JsonMapper initializeJsonMapper({Iterable adapters = const [], SerializationOptions? serializationOptions, DeserializationOptions? deserializationOptions}) { 57 | JsonMapper.globalSerializationOptions = serializationOptions ?? JsonMapper.globalSerializationOptions; 58 | JsonMapper.globalDeserializationOptions = deserializationOptions ?? JsonMapper.globalDeserializationOptions; 59 | JsonMapper.enumerateAdapters([...adapters, exampleGeneratedAdapter], (JsonMapperAdapter adapter) { 60 | _initializeReflectable(adapter); 61 | JsonMapper().useAdapter(adapter); 62 | }); 63 | return JsonMapper(); 64 | } --------------------------------------------------------------------------------