Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

changelog cleanup, add more examples to readme #1213

Merged
merged 2 commits into from
Sep 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 2 additions & 3 deletions json_annotation/lib/src/json_converter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}
/// ```
Expand Down
3 changes: 2 additions & 1 deletion json_serializable/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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

Expand Down
79 changes: 79 additions & 0 deletions json_serializable/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

```dart
@JsonSerializable()
class Sample1 {
Sample1(this.value);

factory Sample1.fromJson(Map<String, dynamic> 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<String, dynamic> toJson() => _$Sample1ToJson(this);
}

class Sample2 {
Sample2(this.value);

// The convention is for `fromJson` to take a single parameter of type
// `Map<String, dynamic>` 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<String, dynamic>` but any JSON-compatible type is allowed.
int toJson() => value;
}
```

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);

factory Sample3.fromJson(Map<String, dynamic> json) =>
_$Sample3FromJson(json);

@JsonKey(
toJson: _toJson,
fromJson: _fromJson,
)
final DateTime value;

Map<String, dynamic> toJson() => _$Sample3ToJson(this);

static int _toJson(DateTime value) => value.millisecondsSinceEpoch;
static DateTime _fromJson(int value) =>
DateTime.fromMillisecondsSinceEpoch(value);
}
```

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);

factory Sample4.fromJson(Map<String, dynamic> json) =>
_$Sample4FromJson(json);

@EpochDateTimeConverter()
final DateTime value;

Map<String, dynamic> toJson() => _$Sample4ToJson(this);
}

class EpochDateTimeConverter implements JsonConverter<DateTime, int> {
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
Expand Down
1 change: 1 addition & 0 deletions json_serializable/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ targets:
- test/kitchen_sink/*
- test/literal/*
- test/supported_types/*
- tool/readme/*

json_serializable|_test_builder:
generate_for:
Expand Down
25 changes: 0 additions & 25 deletions json_serializable/tool/readme/enum_example.dart

This file was deleted.

101 changes: 101 additions & 0 deletions json_serializable/tool/readme/readme_examples.dart
Original file line number Diff line number Diff line change
@@ -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<String, dynamic> 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<String, dynamic> toJson() => _$Sample1ToJson(this);
}

class Sample2 {
Sample2(this.value);

// The convention is for `fromJson` to take a single parameter of type
// `Map<String, dynamic>` 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<String, dynamic>` but any JSON-compatible type is allowed.
int toJson() => value;
}

// # json_key
@JsonSerializable()
class Sample3 {
Sample3(this.value);

factory Sample3.fromJson(Map<String, dynamic> json) =>
_$Sample3FromJson(json);

@JsonKey(
toJson: _toJson,
fromJson: _fromJson,
)
final DateTime value;

Map<String, dynamic> 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<String, dynamic> json) =>
_$Sample4FromJson(json);

@EpochDateTimeConverter()
final DateTime value;

Map<String, dynamic> toJson() => _$Sample4ToJson(this);
}

class EpochDateTimeConverter implements JsonConverter<DateTime, int> {
const EpochDateTimeConverter();

@override
DateTime fromJson(int json) => DateTime.fromMillisecondsSinceEpoch(json);

@override
int toJson(DateTime object) => object.millisecondsSinceEpoch;
}
33 changes: 33 additions & 0 deletions json_serializable/tool/readme/readme_examples.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 10 additions & 2 deletions json_serializable/tool/readme/readme_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`.

<!-- REPLACE tool/readme/enum_example.dart-simple_example -->
<!-- REPLACE tool/readme/readme_examples.dart-simple_example -->

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.

<!-- REPLACE tool/readme/enum_example.dart-enhanced_example -->
<!-- REPLACE tool/readme/readme_examples.dart-enhanced_example -->

# Supported types

Expand All @@ -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.

<!-- REPLACE tool/readme/readme_examples.dart-to_from -->

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.

<!-- REPLACE tool/readme/readme_examples.dart-json_key -->

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).

<!-- REPLACE tool/readme/readme_examples.dart-json_converter -->

# Build configuration

Aside from setting arguments on the associated annotation classes, you can also
Expand Down
16 changes: 11 additions & 5 deletions json_serializable/tool/readme_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand All @@ -44,11 +44,14 @@ class _ReadmeBuilder extends Builder {
final foundClasses = SplayTreeMap<String, String>(compareAsciiLowerCase);

final theMap = <Pattern, String Function(Match)>{
RegExp(r'<!-- REPLACE ([\/\w\d\._-]+) -->'): (match) {
final replacementKey = match.group(1)!;
RegExp(r'( *)<!-- REPLACE ([\/\w\d\._-]+) -->'): (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)!;
Expand Down Expand Up @@ -278,4 +281,7 @@ ${trim()}
```''';

static const _blockComment = r'// # ';

String indent(String indent) =>
LineSplitter.split(this).map((e) => '$indent$e'.trimRight()).join('\n');
}