-
Notifications
You must be signed in to change notification settings - Fork 708
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
Add extension types to JSON page #5605
Comments
I think a section similar to this one would be great, https://docs.flutter.dev/data-and-backend/serialization/json#serializing-json-inside-model-classes. On a related note, these pages really are not flutter specific, they could just as easily be on the dart site? But maybe moving it is hard, or it is there for visibility reasons or something. |
Hmm that's a good point, it's definitely 99% Dart content. I'm sure it's there for visibility and moving it at this point would require a lot of redirecting and maybe be confusing for users... But, it would be a great place to add this extension types content and any future major updates to the json serialization story in Dart. I think it's important to keep all that information together. I think for now I'll just add a similar section to Dart's JSON page, but I'll raise consolidating/moving that page with the Flutter docs team. |
Yeah I definitely understand not wanting to move it - I do think it's a nice page though and I don't think we have an equivalent on the Dart site today? We could even link to it from the Dart site? |
I originally planned to replace our JSON content on dart.dev in #4286 in a similar fashion to the fetch data article, but I guess I never got to that...
I think this makes sense!
That was the plan once I finally worked on that new JSON content, but doing so still makes sense :) Then the Flutter site's version could link to the consolidated dart.dev docs as a linked prerequisite, and then focus on how it can be integrated with or used in a Flutter application. |
Oh ok great! So @jakemac53 sounds like it's safe to move or at least pare down the Flutter page in favor of having that content on Dart's, and we'll continue that work in @parlough's existing issue. I'll keep this issue open just for adding the extension types section on JSON serialization in the mean time. Thanks all! |
About the original consideration (using extension types to handle JSON data safely), here's an example that illustrates the basic idea that I've mentioned on earlier occasions: The starting point would be that we have some information about the expected structure of the JSON data. For instance, we might have a JSON schema. Here's something that resembles a JSON schema (I'm skipping stuff like "$id", "$schema", "description", and just including the elements of interest to us): {
"title": "StreetAddress",
"type": "object",
"properties": {
"number": { "type": "number" },
"street_name": { "type": "string" },
"street_type": { "enum": ["Street", "Avenue", "Boulevard"] }
}
} In general we would have several schemas and they would depend on each other. That's a straightforward generalization, so I'll just go with one schema. Data which is expected to conform to this schema would be received as text, and we'd use something like We then use extension types (plus perhaps some enumerated types) to navigate the weakly typed object graph in a statically typed manner. I'd expect these declarations to be produced by code generation in many cases, but we can of course also write them manually: import 'dart:convert';
enum StreetType {
street,
avenue,
boulevard;
factory StreetType.fromJson(String json) {
return switch (json) {
"Street" => street,
"Avenue" => avenue,
"Boulevard" => boulevard,
_ => throw "Bad JSON, expected StreetType"
};
}
}
extension type StreetAddress.fromJson(Map<String, Object?> it) {
factory StreetAddress.fromSource(String source) {
Object? json = jsonDecode(source);
if (json is! Map<String, Object?>) {
throw "Invalid JSON, expected StreetAddress";
}
return StreetAddress.fromJson(json);
}
int get number => it["number"] as int;
String get streetName => it["street_name"] as String;
StreetType get streetType => StreetType.fromJson(it["street_type"] as String);
} The point is that the weakly typed object graph is "wrapped" by the extension types and enums, and the navigation is now statically typed. If something is wrong in the weakly typed object graph then we'll handle it in one place, which is in this wrapping layer. We can now use the JSON data in a statically type checked manner: void main() {
var source = """
{
"number": 1600,
"street_name": "Pennsylvania",
"street_type": "Avenue"
}""";
var address = StreetAddress.fromSource(source);
var suffix = switch (address.streetType) {
StreetType.street => 'St',
StreetType.avenue => 'Ave',
StreetType.boulevard => 'Blvd'
};
print('Neighbour: ${address.number + 2} ${address.streetName} $suffix.');
}
This approach is useful if the navigation of the weakly typed object graph occurs a limited number of times, or perhaps not at all in some parts because we're only performing some lookups into the data, and then discarding it without looking at the rest. We should note, though, that this approach will use a The main benefit of using extension types is that we would have very performant support for obtaining the weakly typed object graph (so we do want to use something like It could make sense for the code generation to generate the extension types as described above, and also generate regular Dart classes (same thing, essentially, just using |
Extension types are an option for JSON serialization/deserialization
Example from @jakemac53:
We could add "extension types" as a bullet on the JSON page, but we'd need to add another category since it doesn't fit under "Libraries", "Flutter", or "Web app". Maybe "Language"?
One option is to add a section to the extension types page under "Usage" that describes using them for JSON serialization. (Leaning towards this)
Or, we could include the above example or something similar just directly on that JSON page. Wouldn't leave a lot of room for elaboration, but maybe elaboration in this case is not too important.
@eernstg if you have any insights on a good way to do this!
Edit: We could add a "Manual serialization" section to the page and include both this extension types content, plus a link to the Patterns and records codelab that uses json deserialization as its example.
The text was updated successfully, but these errors were encountered: