Skip to content

Commit 1379a70

Browse files
committed
[go_router_builder] add initial json support #110781
1 parent 387b8b1 commit 1379a70

17 files changed

+909
-36
lines changed

packages/go_router_builder/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 3.0.1
2+
3+
- Adds support for classes that support fromJson/toJson. [#117261](https://github.com/flutter/flutter/issues/117261)
4+
- Adds annotation that enable custom string encoder/decoder [#110781](https://github.com/flutter/flutter/issues/110781)
5+
16
## 3.0.0
27

38
- Route classes now required to use a mixin `with _$RouteName`.
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
// ignore_for_file: public_member_api_docs, unreachable_from_main
6+
7+
import 'dart:convert';
8+
9+
import 'package:flutter/material.dart';
10+
import 'package:go_router/go_router.dart';
11+
12+
import 'shared/data.dart';
13+
14+
part 'json_example.g.dart';
15+
16+
void main() => runApp(App());
17+
18+
class App extends StatelessWidget {
19+
App({super.key});
20+
21+
@override
22+
Widget build(BuildContext context) => MaterialApp.router(
23+
routerConfig: _router,
24+
title: _appTitle,
25+
);
26+
27+
final GoRouter _router = GoRouter(routes: $appRoutes);
28+
}
29+
30+
@TypedGoRoute<HomeRoute>(
31+
path: '/',
32+
name: 'Home',
33+
routes: <TypedGoRoute<GoRouteData>>[
34+
TypedGoRoute<JsonRoute>(path: 'json'),
35+
],
36+
)
37+
class HomeRoute extends GoRouteData with _$HomeRoute {
38+
const HomeRoute();
39+
40+
@override
41+
Widget build(BuildContext context, GoRouterState state) => const HomeScreen();
42+
}
43+
44+
class JsonRoute extends GoRouteData with _$JsonRoute {
45+
const JsonRoute(this.json);
46+
47+
final JsonExample json;
48+
49+
@override
50+
Widget build(BuildContext context, GoRouterState state) =>
51+
JsonScreen(json: json);
52+
}
53+
54+
class HomeScreen extends StatelessWidget {
55+
const HomeScreen({super.key});
56+
57+
@override
58+
Widget build(BuildContext context) => Scaffold(
59+
appBar: AppBar(title: const Text(_appTitle)),
60+
body: ListView(
61+
children: <Widget>[
62+
for (final JsonExample json in jsonData)
63+
ListTile(
64+
title: Text(json.name),
65+
onTap: () => JsonRoute(json).go(context),
66+
)
67+
],
68+
),
69+
);
70+
}
71+
72+
class JsonScreen extends StatelessWidget {
73+
const JsonScreen({required this.json, super.key});
74+
final JsonExample json;
75+
76+
@override
77+
Widget build(BuildContext context) => Scaffold(
78+
appBar: AppBar(title: Text(json.name)),
79+
body: ListView(
80+
key: ValueKey<String>(json.id),
81+
children: <Widget>[
82+
Text(json.id),
83+
Text(json.name),
84+
],
85+
),
86+
);
87+
}
88+
89+
const String _appTitle = 'GoRouter Example: builder';

packages/go_router_builder/example/lib/json_example.g.dart

Lines changed: 79 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/go_router_builder/example/lib/shared/data.dart

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,3 +191,46 @@ class Repository {
191191
return FamilyPerson(family: family, person: family.person(pid));
192192
}
193193
}
194+
195+
class JsonExample {
196+
const JsonExample({required this.id, required this.name});
197+
198+
factory JsonExample.fromJson(Map<String, dynamic> json) {
199+
return JsonExample(
200+
id: json['id'] as String,
201+
name: json['name'] as String,
202+
);
203+
}
204+
205+
Map<String, dynamic> toJson() {
206+
return <String, dynamic>{
207+
'id': id,
208+
'name': name,
209+
};
210+
}
211+
212+
final String id;
213+
final String name;
214+
}
215+
216+
const List<JsonExample> jsonData = <JsonExample>[
217+
JsonExample(id: '1', name: 'people'),
218+
JsonExample(id: '2', name: 'animals'),
219+
];
220+
221+
class JsonExampleNested<T> {
222+
const JsonExampleNested({required this.child});
223+
224+
factory JsonExampleNested.fromJson(
225+
Map<String, dynamic> json,
226+
T Function(Object? json) fromJsonT,
227+
) {
228+
return JsonExampleNested<T>(child: fromJsonT(json['child']));
229+
}
230+
231+
Map<String, dynamic> toJson() {
232+
return <String, dynamic>{'child': child};
233+
}
234+
235+
final T child;
236+
}

packages/go_router_builder/lib/src/route_config.dart

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,12 @@ class GoRouteConfig extends RouteBaseConfig {
303303
);
304304
}
305305
}
306-
final String fromStateExpression = decodeParameter(element, _pathParams);
306+
final List<ElementAnnotation>? metadata = _fieldMetadata(element.name);
307+
final String fromStateExpression = decodeParameter(
308+
element,
309+
_pathParams,
310+
metadata,
311+
);
307312

308313
if (element.isPositional) {
309314
return '$fromStateExpression,';
@@ -328,7 +333,8 @@ class GoRouteConfig extends RouteBaseConfig {
328333
);
329334
}
330335

331-
return encodeField(field);
336+
final List<ElementAnnotation>? metadata = _fieldMetadata(fieldName);
337+
return encodeField(field, metadata);
332338
}
333339

334340
String get _locationQueryParams {
@@ -752,6 +758,10 @@ $routeDataClassName.$dataConvertionFunctionName(
752758
PropertyAccessorElement? _field(String name) =>
753759
routeDataClass.getGetter(name);
754760

761+
List<ElementAnnotation>? _fieldMetadata(String name) => routeDataClass.fields
762+
.firstWhereOrNull((FieldElement element) => element.displayName == name)
763+
?.metadata;
764+
755765
/// The name of `RouteData` subclass this configuration represents.
756766
@protected
757767
String get routeDataClassName;

0 commit comments

Comments
 (0)