SKILL.md
$2a
Task Progress:
- Add the
httppackage topubspec.yaml.
- Configure platform permissions (Internet permission in
AndroidManifest.xmland macOS.entitlements).
- Construct the target
Uri.
- Execute the HTTP method.
- Validate the response and parse the JSON payload.
Conditional Implementation:
- If fetching data (GET): Use
http.get(uri).
- If sending new data (POST): Use
http.post(uri, headers: {...}, body: jsonEncode(data)). EnsureContent-Typeisapplication/json; charset=UTF-8.
- If updating data (PUT): Use
http.put(uri, headers: {...}, body: jsonEncode(data)).
- If deleting data (DELETE): Use
http.delete(uri, headers: {...}).
Feedback Loop: Validation & Error Handling
- Run the HTTP request.
- Check
response.statusCode.
- If
200or201, calljsonDecode(response.body)and map to a Dart object.
- If any other code, throw an
Exception('Failed to load/update/delete resource').
- Review errors -> fix endpoint, headers, or payload structure.
Workflow: Implementing JSON Serialization
Choose the serialization strategy based on project complexity.
Conditional Implementation:
- If building a small prototype or simple models: Use manual serialization with
dart:convert.
- If building a production app with complex/nested models: Use code generation with
json_serializable.
Manual Serialization Setup
Task Progress:
- Import
dart:convert.
- Define the Model class with
finalproperties.
- Implement a
factory Model.fromJson(Map<String, dynamic> json)constructor.
- Implement a
Map<String, dynamic> toJson()method.
Code Generation Setup ( json_serializable )
Task Progress:
- Add dependencies:
flutter pub add json_annotationandflutter pub add -d build_runner json_serializable.
- Import
json_annotation.dartin the model file.
- Add the
part 'model_name.g.dart';directive.
- Annotate the class with
@JsonSerializable(). UseexplicitToJson: trueif the class contains nested models.
- Define the
fromJsonfactory andtoJsonmethod delegating to the generated functions.
- Run the generator:
dart run build_runner build --delete-conflicting-outputs.
Workflow: Parsing Large JSON in the Background
Use this workflow to prevent frame drops when parsing large JSON payloads (e.g., lists of 1000+ items).
Task Progress:
- Create a top-level or static function that takes a
String(the response body) and returns the parsed Dart object (e.g.,List<Model>).
- Inside the function, call
jsonDecodeand map the results to the Model class.
- In the HTTP fetch method, pass the top-level parsing function and the
response.bodyto Flutter'scompute()function.
Examples
Example 1: HTTP GET with Manual Serialization
import 'dart:convert';
import 'package:http/http.dart' as http;
class Album {
final int id;
final String title;
const Album({required this.id, required this.title});
factory Album.fromJson(Map<String, dynamic> json) {
return Album(
id: json['id'] as int,
title: json['title'] as String,
);
}
}
Future<Album> fetchAlbum() async {
final uri = Uri.https('jsonplaceholder.typicode.com', '/albums/1');
final response = await http.get(uri);
if (response.statusCode == 200) {
return Album.fromJson(jsonDecode(response.body) as Map<String, dynamic>);
} else {
throw Exception('Failed to load album');
}
}
Example 2: HTTP POST Request
Future<Album> createAlbum(String title) async {
final uri = Uri.https('jsonplaceholder.typicode.com', '/albums');
final response = await http.post(
uri,
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(<String, String>{'title': title}),
);
if (response.statusCode == 201) {
return Album.fromJson(jsonDecode(response.body) as Map<String, dynamic>);
} else {
throw Exception('Failed to create album.');
}
}
Example 3: Background Parsing with compute
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart' as http;
// 1. Top-level function for parsing
List<Photo> parsePhotos(String responseBody) {
final parsed = (jsonDecode(responseBody) as List<Object?>)
.cast<Map<String, Object?>>();
return parsed.map<Photo>(Photo.fromJson).toList();
}
// 2. Fetch function using compute
Future<List<Photo>> fetchPhotos(http.Client client) async {
final uri = Uri.https('jsonplaceholder.typicode.com', '/photos');
final response = await client.get(uri);
if (response.statusCode == 200) {
// Run parsePhotos in a separate isolate
return compute(parsePhotos, response.body);
} else {
throw Exception('Failed to load photos');
}
}
Example 4: Code Generation ( json_serializable )
import 'package:json_annotation/json_annotation.dart';
part 'user.g.dart';
@JsonSerializable(explicitToJson: true)
class User {
final String name;
@JsonKey(name: 'registration_date_millis')
final int registrationDateMillis;
User(this.name, this.registrationDateMillis);
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
Map<String, dynamic> toJson() => _$UserToJson(this);
}