From bcda359772114306207f3a8fa21e6ac07b8e91ad Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 28 Sep 2022 15:32:29 -0700 Subject: [PATCH 1/2] changelog cleanup, add more examples to readme --- json_annotation/lib/src/json_converter.dart | 5 +- json_serializable/CHANGELOG.md | 3 +- json_serializable/README.md | 83 +++++++++++++- json_serializable/build.yaml | 1 + .../tool/readme/enum_example.dart | 25 ----- .../tool/readme/readme_examples.dart | 101 ++++++++++++++++++ .../tool/readme/readme_examples.g.dart | 33 ++++++ .../tool/readme/readme_template.md | 16 ++- json_serializable/tool/readme_builder.dart | 2 +- 9 files changed, 233 insertions(+), 36 deletions(-) delete mode 100644 json_serializable/tool/readme/enum_example.dart create mode 100644 json_serializable/tool/readme/readme_examples.dart create mode 100644 json_serializable/tool/readme/readme_examples.g.dart diff --git a/json_annotation/lib/src/json_converter.dart b/json_annotation/lib/src/json_converter.dart index 8736d2c42..fefe88ece 100644 --- a/json_annotation/lib/src/json_converter.dart +++ b/json_annotation/lib/src/json_converter.dart @@ -26,16 +26,15 @@ /// /// ```dart /// @JsonSerializable() -/// @MyJsonConverter() /// class Example { /// @MyJsonConverter() /// final Value property; /// } /// ``` /// -/// Or finally, passed to the annotation: +/// Or finally, passed to the `@JsonSerializable` annotation: /// -///```dart +/// ```dart /// @JsonSerializable(converters: [MyJsonConverter()]) /// class Example {} /// ``` diff --git a/json_serializable/CHANGELOG.md b/json_serializable/CHANGELOG.md index d6366ae68..7270ca696 100644 --- a/json_serializable/CHANGELOG.md +++ b/json_serializable/CHANGELOG.md @@ -1,6 +1,7 @@ ## 6.4.2-dev -- Support `ConstructorElement` which allows using tear-off constructors. +- Allow constructors to be passed to `JsonKey` parameters that support + `Function` types. ## 6.4.1 diff --git a/json_serializable/README.md b/json_serializable/README.md index 2d7b4c66d..b1b7939af 100644 --- a/json_serializable/README.md +++ b/json_serializable/README.md @@ -171,15 +171,94 @@ customize the encoding/decoding of any type, you have a few options. `toJson()` function to the type. Note: while you can use `json_serializable` for these types, you don't have to! The generator code only looks for these methods. It doesn't care how they were created. -1. Use the [`JsonKey.toJson`] and [`JsonKey.fromJson`] properties to specify + +```dart +@JsonSerializable() +class Sample1 { + Sample1(this.value); + + factory Sample1.fromJson(Map json) => + _$Sample1FromJson(json); + + // Sample2 is NOT annotated with @JsonSerializable(), but that's okay + // The class has a `fromJson` constructor and a `toJson` method, which is + // all that is required. + final Sample2 value; + + Map toJson() => _$Sample1ToJson(this); +} + +class Sample2 { + Sample2(this.value); + + // The convention is for `fromJson` to take a single parameter of type + // `Map` but any JSON-compatible type is allowed. + factory Sample2.fromJson(int value) => Sample2(value); + final int value; + + // The convention is for `toJson` to take return a type of + // `Map` but any JSON-compatible type is allowed. + int toJson() => value; +} +``` + +2. Use the [`JsonKey.toJson`] and [`JsonKey.fromJson`] properties to specify custom conversions on the annotated field. The functions specified must be top-level or static. See the documentation of these properties for details. -1. Create an implementation of [`JsonConverter`] and annotate either the + +```dart +@JsonSerializable() +class Sample3 { + Sample3(this.value); + + factory Sample3.fromJson(Map json) => + _$Sample3FromJson(json); + + @JsonKey( + toJson: _toJson, + fromJson: _fromJson, + ) + final DateTime value; + + Map toJson() => _$Sample3ToJson(this); + + static int _toJson(DateTime value) => value.millisecondsSinceEpoch; + static DateTime _fromJson(int value) => + DateTime.fromMillisecondsSinceEpoch(value); +} +``` + +3. Create an implementation of [`JsonConverter`] and annotate either the corresponding field or the containing class. [`JsonConverter`] is convenient if you want to use the same conversion logic on many fields. It also allows you to support a type within collections. Check out [these examples](https://github.com/google/json_serializable.dart/blob/master/example/lib/json_converter_example.dart). +```dart +@JsonSerializable() +class Sample4 { + Sample4(this.value); + + factory Sample4.fromJson(Map json) => + _$Sample4FromJson(json); + + @EpochDateTimeConverter() + final DateTime value; + + Map toJson() => _$Sample4ToJson(this); +} + +class EpochDateTimeConverter implements JsonConverter { + const EpochDateTimeConverter(); + + @override + DateTime fromJson(int json) => DateTime.fromMillisecondsSinceEpoch(json); + + @override + int toJson(DateTime object) => object.millisecondsSinceEpoch; +} +``` + # Build configuration Aside from setting arguments on the associated annotation classes, you can also diff --git a/json_serializable/build.yaml b/json_serializable/build.yaml index 03933fb6e..1b5d731c9 100644 --- a/json_serializable/build.yaml +++ b/json_serializable/build.yaml @@ -18,6 +18,7 @@ targets: - test/kitchen_sink/* - test/literal/* - test/supported_types/* + - tool/readme/* json_serializable|_test_builder: generate_for: diff --git a/json_serializable/tool/readme/enum_example.dart b/json_serializable/tool/readme/enum_example.dart deleted file mode 100644 index f3f48b017..000000000 --- a/json_serializable/tool/readme/enum_example.dart +++ /dev/null @@ -1,25 +0,0 @@ -import 'package:json_annotation/json_annotation.dart'; - -// # simple_example -enum StatusCode { - @JsonValue(200) - success, - @JsonValue(301) - movedPermanently, - @JsonValue(302) - found, - @JsonValue(500) - internalServerError, -} - -// # enhanced_example -@JsonEnum(valueField: 'code') -enum StatusCodeEnhanced { - success(200), - movedPermanently(301), - found(302), - internalServerError(500); - - const StatusCodeEnhanced(this.code); - final int code; -} diff --git a/json_serializable/tool/readme/readme_examples.dart b/json_serializable/tool/readme/readme_examples.dart new file mode 100644 index 000000000..0abc70fc5 --- /dev/null +++ b/json_serializable/tool/readme/readme_examples.dart @@ -0,0 +1,101 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'readme_examples.g.dart'; + +// # simple_example +enum StatusCode { + @JsonValue(200) + success, + @JsonValue(301) + movedPermanently, + @JsonValue(302) + found, + @JsonValue(500) + internalServerError, +} + +// # enhanced_example +@JsonEnum(valueField: 'code') +enum StatusCodeEnhanced { + success(200), + movedPermanently(301), + found(302), + internalServerError(500); + + const StatusCodeEnhanced(this.code); + final int code; +} + +// # to_from +@JsonSerializable() +class Sample1 { + Sample1(this.value); + + factory Sample1.fromJson(Map json) => + _$Sample1FromJson(json); + + // Sample2 is NOT annotated with @JsonSerializable(), but that's okay + // The class has a `fromJson` constructor and a `toJson` method, which is + // all that is required. + final Sample2 value; + + Map toJson() => _$Sample1ToJson(this); +} + +class Sample2 { + Sample2(this.value); + + // The convention is for `fromJson` to take a single parameter of type + // `Map` but any JSON-compatible type is allowed. + factory Sample2.fromJson(int value) => Sample2(value); + final int value; + + // The convention is for `toJson` to take return a type of + // `Map` but any JSON-compatible type is allowed. + int toJson() => value; +} + +// # json_key +@JsonSerializable() +class Sample3 { + Sample3(this.value); + + factory Sample3.fromJson(Map json) => + _$Sample3FromJson(json); + + @JsonKey( + toJson: _toJson, + fromJson: _fromJson, + ) + final DateTime value; + + Map toJson() => _$Sample3ToJson(this); + + static int _toJson(DateTime value) => value.millisecondsSinceEpoch; + static DateTime _fromJson(int value) => + DateTime.fromMillisecondsSinceEpoch(value); +} + +// # json_converter +@JsonSerializable() +class Sample4 { + Sample4(this.value); + + factory Sample4.fromJson(Map json) => + _$Sample4FromJson(json); + + @EpochDateTimeConverter() + final DateTime value; + + Map toJson() => _$Sample4ToJson(this); +} + +class EpochDateTimeConverter implements JsonConverter { + const EpochDateTimeConverter(); + + @override + DateTime fromJson(int json) => DateTime.fromMillisecondsSinceEpoch(json); + + @override + int toJson(DateTime object) => object.millisecondsSinceEpoch; +} diff --git a/json_serializable/tool/readme/readme_examples.g.dart b/json_serializable/tool/readme/readme_examples.g.dart new file mode 100644 index 000000000..be265dd6d --- /dev/null +++ b/json_serializable/tool/readme/readme_examples.g.dart @@ -0,0 +1,33 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +// ignore_for_file: lines_longer_than_80_chars, text_direction_code_point_in_literal + +part of 'readme_examples.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +Sample1 _$Sample1FromJson(Map json) => Sample1( + Sample2.fromJson(json['value'] as int), + ); + +Map _$Sample1ToJson(Sample1 instance) => { + 'value': instance.value, + }; + +Sample3 _$Sample3FromJson(Map json) => Sample3( + Sample3._fromJson(json['value'] as int), + ); + +Map _$Sample3ToJson(Sample3 instance) => { + 'value': Sample3._toJson(instance.value), + }; + +Sample4 _$Sample4FromJson(Map json) => Sample4( + const EpochDateTimeConverter().fromJson(json['value'] as int), + ); + +Map _$Sample4ToJson(Sample4 instance) => { + 'value': const EpochDateTimeConverter().toJson(instance.value), + }; diff --git a/json_serializable/tool/readme/readme_template.md b/json_serializable/tool/readme/readme_template.md index 2f3c39551..a91e5eb37 100644 --- a/json_serializable/tool/readme/readme_template.md +++ b/json_serializable/tool/readme/readme_template.md @@ -75,14 +75,14 @@ Annotate `enum` types with `ja:JsonEnum` (new in `json_annotation` 4.2.0) to: Annotate `enum` values with `ja:JsonValue` to specify the encoded value to map to target `enum` entries. Values can be of type `core:String` or `core:int`. - + If you are annotating an [enhanced enum](https://dart.dev/guides/language/language-tour#declaring-enhanced-enums), you can use `ja:JsonEnum.valueField` to specify the field to use for the serialized value. - + # Supported types @@ -107,15 +107,23 @@ customize the encoding/decoding of any type, you have a few options. `toJson()` function to the type. Note: while you can use `json_serializable` for these types, you don't have to! The generator code only looks for these methods. It doesn't care how they were created. -1. Use the `ja:JsonKey.toJson` and `ja:JsonKey.fromJson` properties to specify + + + +2. Use the `ja:JsonKey.toJson` and `ja:JsonKey.fromJson` properties to specify custom conversions on the annotated field. The functions specified must be top-level or static. See the documentation of these properties for details. -1. Create an implementation of `ja:JsonConverter` and annotate either the + + + +3. Create an implementation of `ja:JsonConverter` and annotate either the corresponding field or the containing class. `ja:JsonConverter` is convenient if you want to use the same conversion logic on many fields. It also allows you to support a type within collections. Check out [these examples](https://github.com/google/json_serializable.dart/blob/master/example/lib/json_converter_example.dart). + + # Build configuration Aside from setting arguments on the associated annotation classes, you can also diff --git a/json_serializable/tool/readme_builder.dart b/json_serializable/tool/readme_builder.dart index be97e7832..400435ef3 100644 --- a/json_serializable/tool/readme_builder.dart +++ b/json_serializable/tool/readme_builder.dart @@ -24,7 +24,7 @@ class _ReadmeBuilder extends Builder { final replacements = { ...await buildStep.getExampleContent('example/example.dart'), ...await buildStep.getExampleContent('example/example.g.dart'), - ...await buildStep.getExampleContent('tool/readme/enum_example.dart'), + ...await buildStep.getExampleContent('tool/readme/readme_examples.dart'), 'supported_types': _classCleanAndSort(supportedTypes()), 'collection_types': _classCleanAndSort(collectionTypes()), 'map_key_types': _classCleanAndSort(mapKeyTypes), From a5c05b6bba75afcee44ad34f25426830ee5a61af Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 29 Sep 2022 11:32:44 -0700 Subject: [PATCH 2/2] oops --- json_serializable/README.md | 120 +++++++++--------- .../tool/readme/readme_template.md | 10 +- json_serializable/tool/readme_builder.dart | 14 +- 3 files changed, 75 insertions(+), 69 deletions(-) diff --git a/json_serializable/README.md b/json_serializable/README.md index b1b7939af..ac0eebdf7 100644 --- a/json_serializable/README.md +++ b/json_serializable/README.md @@ -172,92 +172,92 @@ customize the encoding/decoding of any type, you have a few options. for these types, you don't have to! The generator code only looks for these methods. It doesn't care how they were created. -```dart -@JsonSerializable() -class Sample1 { - Sample1(this.value); + ```dart + @JsonSerializable() + class Sample1 { + Sample1(this.value); - factory Sample1.fromJson(Map json) => - _$Sample1FromJson(json); + factory Sample1.fromJson(Map json) => + _$Sample1FromJson(json); - // Sample2 is NOT annotated with @JsonSerializable(), but that's okay - // The class has a `fromJson` constructor and a `toJson` method, which is - // all that is required. - final Sample2 value; + // Sample2 is NOT annotated with @JsonSerializable(), but that's okay + // The class has a `fromJson` constructor and a `toJson` method, which is + // all that is required. + final Sample2 value; - Map toJson() => _$Sample1ToJson(this); -} + Map toJson() => _$Sample1ToJson(this); + } -class Sample2 { - Sample2(this.value); + class Sample2 { + Sample2(this.value); - // The convention is for `fromJson` to take a single parameter of type - // `Map` but any JSON-compatible type is allowed. - factory Sample2.fromJson(int value) => Sample2(value); - final int value; + // The convention is for `fromJson` to take a single parameter of type + // `Map` but any JSON-compatible type is allowed. + factory Sample2.fromJson(int value) => Sample2(value); + final int value; - // The convention is for `toJson` to take return a type of - // `Map` but any JSON-compatible type is allowed. - int toJson() => value; -} -``` + // The convention is for `toJson` to take return a type of + // `Map` but any JSON-compatible type is allowed. + int toJson() => value; + } + ``` -2. Use the [`JsonKey.toJson`] and [`JsonKey.fromJson`] properties to specify +1. Use the [`JsonKey.toJson`] and [`JsonKey.fromJson`] properties to specify custom conversions on the annotated field. The functions specified must be top-level or static. See the documentation of these properties for details. -```dart -@JsonSerializable() -class Sample3 { - Sample3(this.value); + ```dart + @JsonSerializable() + class Sample3 { + Sample3(this.value); - factory Sample3.fromJson(Map json) => - _$Sample3FromJson(json); + factory Sample3.fromJson(Map json) => + _$Sample3FromJson(json); - @JsonKey( - toJson: _toJson, - fromJson: _fromJson, - ) - final DateTime value; + @JsonKey( + toJson: _toJson, + fromJson: _fromJson, + ) + final DateTime value; - Map toJson() => _$Sample3ToJson(this); + Map toJson() => _$Sample3ToJson(this); - static int _toJson(DateTime value) => value.millisecondsSinceEpoch; - static DateTime _fromJson(int value) => - DateTime.fromMillisecondsSinceEpoch(value); -} -``` + static int _toJson(DateTime value) => value.millisecondsSinceEpoch; + static DateTime _fromJson(int value) => + DateTime.fromMillisecondsSinceEpoch(value); + } + ``` -3. Create an implementation of [`JsonConverter`] and annotate either the +1. Create an implementation of [`JsonConverter`] and annotate either the corresponding field or the containing class. [`JsonConverter`] is convenient if you want to use the same conversion logic on many fields. It also allows you to support a type within collections. Check out [these examples](https://github.com/google/json_serializable.dart/blob/master/example/lib/json_converter_example.dart). -```dart -@JsonSerializable() -class Sample4 { - Sample4(this.value); + ```dart + @JsonSerializable() + class Sample4 { + Sample4(this.value); - factory Sample4.fromJson(Map json) => - _$Sample4FromJson(json); + factory Sample4.fromJson(Map json) => + _$Sample4FromJson(json); - @EpochDateTimeConverter() - final DateTime value; + @EpochDateTimeConverter() + final DateTime value; - Map toJson() => _$Sample4ToJson(this); -} + Map toJson() => _$Sample4ToJson(this); + } -class EpochDateTimeConverter implements JsonConverter { - const EpochDateTimeConverter(); + class EpochDateTimeConverter implements JsonConverter { + const EpochDateTimeConverter(); - @override - DateTime fromJson(int json) => DateTime.fromMillisecondsSinceEpoch(json); + @override + DateTime fromJson(int json) => DateTime.fromMillisecondsSinceEpoch(json); - @override - int toJson(DateTime object) => object.millisecondsSinceEpoch; -} -``` + @override + int toJson(DateTime object) => object.millisecondsSinceEpoch; + } + ``` # Build configuration diff --git a/json_serializable/tool/readme/readme_template.md b/json_serializable/tool/readme/readme_template.md index a91e5eb37..8af2bac78 100644 --- a/json_serializable/tool/readme/readme_template.md +++ b/json_serializable/tool/readme/readme_template.md @@ -108,21 +108,21 @@ customize the encoding/decoding of any type, you have a few options. for these types, you don't have to! The generator code only looks for these methods. It doesn't care how they were created. - + -2. Use the `ja:JsonKey.toJson` and `ja:JsonKey.fromJson` properties to specify +1. Use the `ja:JsonKey.toJson` and `ja:JsonKey.fromJson` properties to specify custom conversions on the annotated field. The functions specified must be top-level or static. See the documentation of these properties for details. - + -3. Create an implementation of `ja:JsonConverter` and annotate either the +1. Create an implementation of `ja:JsonConverter` and annotate either the corresponding field or the containing class. `ja:JsonConverter` is convenient if you want to use the same conversion logic on many fields. It also allows you to support a type within collections. Check out [these examples](https://github.com/google/json_serializable.dart/blob/master/example/lib/json_converter_example.dart). - + # Build configuration diff --git a/json_serializable/tool/readme_builder.dart b/json_serializable/tool/readme_builder.dart index 400435ef3..76156a219 100644 --- a/json_serializable/tool/readme_builder.dart +++ b/json_serializable/tool/readme_builder.dart @@ -44,11 +44,14 @@ class _ReadmeBuilder extends Builder { final foundClasses = SplayTreeMap(compareAsciiLowerCase); final theMap = { - RegExp(r''): (match) { - final replacementKey = match.group(1)!; + RegExp(r'( *)'): (match) { + final replacementKey = match.group(2)!; availableKeys.remove(replacementKey); - return (replacements[replacementKey] ?? '*MISSING! `$replacementKey`*') - .trim(); + final replacement = + (replacements[replacementKey] ?? '*MISSING! `$replacementKey`*') + .trim(); + + return replacement.indent(match.group(1)!); }, RegExp(r'`(\w+):(\w+)(\.\w+)?`'): (match) { final context = match.group(1)!; @@ -278,4 +281,7 @@ ${trim()} ```'''; static const _blockComment = r'// # '; + + String indent(String indent) => + LineSplitter.split(this).map((e) => '$indent$e'.trimRight()).join('\n'); }