flutter-http-and-json by flutter/skills
npx skills add https://github.com/flutter/skills --skill flutter-http-and-json在 Flutter 应用程序中管理 HTTP 网络请求和 JSON 数据处理。使用 http 包实现安全、异步的 REST API 调用(GET、POST、PUT、DELETE)。处理 JSON 序列化、通过 isolate 对大数据集进行后台解析,以及为 AI 模型集成提供结构化的 JSON 模式。假设 pubspec.yaml 中已添加 http 包,并且环境支持 Dart 3 的模式匹配和空安全。
在实现 JSON 解析和序列化时,请评估以下决策树:
compute() 进行后台解析,以避免 UI 卡顿。dart:convert)。
* 如果数据模型高度嵌套或是大型生产应用的一部分,请停止并询问用户: “我们是否应该配置 json_serializable 和 build_runner 以实现自动化代码生成?”广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
在进行网络请求之前,请确保目标平台具有所需的互联网权限。
Android (android/app/src/main/AndroidManifest.xml):
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 从互联网获取数据所必需。 -->
<uses-permission android:name="android.permission.INTERNET" />
<application ...>
</manifest>
macOS (macos/Runner/DebugProfile.entitlements 和 Release.entitlements):
<dict>
<!-- 从互联网获取数据所必需。 -->
<key>com.apple.security.network.client</key>
<true/>
</dict>
创建一个强类型的 Dart 类来表示 JSON 数据。使用工厂构造函数进行反序列化,并使用 toJson 方法进行序列化。
import 'dart:convert';
class ItemModel {
final int id;
final String title;
const ItemModel({required this.id, required this.title});
// 使用 Dart 3 模式匹配进行反序列化
factory ItemModel.fromJson(Map<String, dynamic> json) {
return switch (json) {
{'id': int id, 'title': String title} => ItemModel(id: id, title: title),
_ => throw const FormatException('Failed to parse ItemModel.'),
};
}
// 序列化为 JSON
Map<String, dynamic> toJson() => {
'id': id,
'title': title,
};
}
使用 http 包执行网络请求。始终使用 Uri.https 进行安全的 URL 编码。验证状态码并在失败时抛出异常。
import 'dart:convert';
import 'package:http/http.dart' as http;
class ApiService {
final http.Client client;
ApiService(this.client);
// GET 请求
Future<ItemModel> fetchItem(int id) async {
final uri = Uri.https('api.example.com', '/items/$id');
final response = await client.get(uri);
if (response.statusCode == 200) {
return ItemModel.fromJson(jsonDecode(response.body) as Map<String, dynamic>);
} else {
throw Exception('Failed to load item: ${response.statusCode}');
}
}
// POST 请求
Future<ItemModel> createItem(String title) async {
final uri = Uri.https('api.example.com', '/items');
final response = await client.post(
uri,
headers: <String, String>{'Content-Type': 'application/json; charset=UTF-8'},
body: jsonEncode(<String, String>{'title': title}),
);
if (response.statusCode == 201) {
return ItemModel.fromJson(jsonDecode(response.body) as Map<String, dynamic>);
} else {
throw Exception('Failed to create item: ${response.statusCode}');
}
}
// DELETE 请求
Future<void> deleteItem(int id) async {
final uri = Uri.https('api.example.com', '/items/$id');
final response = await client.delete(
uri,
headers: <String, String>{'Content-Type': 'application/json; charset=UTF-8'},
);
if (response.statusCode != 200) {
throw Exception('Failed to delete item: ${response.statusCode}');
}
}
}
如果获取的是大型对象列表,请使用 compute() 将 JSON 解码和映射操作移至单独的 isolate 中。
import 'package:flutter/foundation.dart';
// compute() 所需的顶级函数
List<ItemModel> parseItems(String responseBody) {
final parsed = (jsonDecode(responseBody) as List<Object?>).cast<Map<String, Object?>>();
return parsed.map<ItemModel>(ItemModel.fromJson).toList();
}
Future<List<ItemModel>> fetchLargeItemList(http.Client client) async {
final uri = Uri.https('api.example.com', '/items');
final response = await client.get(uri);
if (response.statusCode == 200) {
// 在单独的 isolate 中运行 parseItems
return compute(parseItems, response.body);
} else {
throw Exception('Failed to load items');
}
}
在集成 LLM(如 Gemini)时,通过在生成配置和系统指令中传递严格的模式,来强制执行可靠的 JSON 输出。
import 'package:firebase_vertexai/firebase_vertexai.dart';
// 定义预期的 JSON 模式
final _responseSchema = Schema(
SchemaType.object,
properties: {
'width': Schema(SchemaType.integer),
'height': Schema(SchemaType.integer),
'items': Schema(
SchemaType.array,
items: Schema(
SchemaType.object,
properties: {
'id': Schema(SchemaType.integer),
'name': Schema(SchemaType.string),
},
),
),
},
);
// 使用该模式初始化模型
final model = FirebaseAI.googleAI().generativeModel(
model: 'gemini-2.5-pro',
generationConfig: GenerationConfig(
responseMimeType: 'application/json',
responseSchema: _responseSchema,
),
);
Future<Map<String, dynamic>> analyzeData(String prompt) async {
final content = [Content.text(prompt)];
final response = await model.generateContent(content);
// 安全地解码有保证的 JSON 响应
return jsonDecode(response.text!) as Map<String, dynamic>;
}
Uri.https() 或 Uri.parse() 来构建 URL。切勿使用原始字符串拼接来处理带有查询参数的端点。null。始终抛出 Exception 或自定义错误类,以便 UI(例如 FutureBuilder)能够捕获并通过 snapshot.hasError 显示错误状态。response.statusCode。成功的 GET/PUT/DELETE 使用 200,成功的 POST 使用 201。dart:io 的 HttpClient 进行标准的跨平台网络请求。始终使用 http 包以确保 Web 兼容性。compute() 时,确保解析函数是顶级函数或静态方法,并且仅通过 isolate 边界传递基本类型值或简单对象(如 String 响应体)。不要传递 http.Response 对象。每周安装数
971
代码仓库
GitHub 星标数
792
首次出现
2026年3月4日
安全审计
已安装于
codex951
cursor949
github-copilot948
gemini-cli947
opencode947
kimi-cli946
Manages HTTP networking and JSON data handling in Flutter applications. Implements secure, asynchronous REST API calls (GET, POST, PUT, DELETE) using the http package. Handles JSON serialization, background parsing via isolates for large datasets, and structured JSON schemas for AI model integrations. Assumes the http package is added to pubspec.yaml and the environment supports Dart 3 pattern matching and null safety.
When implementing JSON parsing and serialization, evaluate the following decision tree:
compute() to avoid UI jank.dart:convert).json_serializable and build_runner for automated code generation?"Before making network requests, ensure the target platforms have the required internet permissions.
Android (android/app/src/main/AndroidManifest.xml):
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Required to fetch data from the internet. -->
<uses-permission android:name="android.permission.INTERNET" />
<application ...>
</manifest>
macOS (macos/Runner/DebugProfile.entitlements and Release.entitlements):
<dict>
<!-- Required to fetch data from the internet. -->
<key>com.apple.security.network.client</key>
<true/>
</dict>
Create a strongly typed Dart class to represent the JSON data. Use factory constructors for deserialization and a toJson method for serialization.
import 'dart:convert';
class ItemModel {
final int id;
final String title;
const ItemModel({required this.id, required this.title});
// Deserialize using Dart 3 pattern matching
factory ItemModel.fromJson(Map<String, dynamic> json) {
return switch (json) {
{'id': int id, 'title': String title} => ItemModel(id: id, title: title),
_ => throw const FormatException('Failed to parse ItemModel.'),
};
}
// Serialize to JSON
Map<String, dynamic> toJson() => {
'id': id,
'title': title,
};
}
Use the http package to perform network requests. Always use Uri.https for safe URL encoding. Validate the status code and throw exceptions on failure.
import 'dart:convert';
import 'package:http/http.dart' as http;
class ApiService {
final http.Client client;
ApiService(this.client);
// GET Request
Future<ItemModel> fetchItem(int id) async {
final uri = Uri.https('api.example.com', '/items/$id');
final response = await client.get(uri);
if (response.statusCode == 200) {
return ItemModel.fromJson(jsonDecode(response.body) as Map<String, dynamic>);
} else {
throw Exception('Failed to load item: ${response.statusCode}');
}
}
// POST Request
Future<ItemModel> createItem(String title) async {
final uri = Uri.https('api.example.com', '/items');
final response = await client.post(
uri,
headers: <String, String>{'Content-Type': 'application/json; charset=UTF-8'},
body: jsonEncode(<String, String>{'title': title}),
);
if (response.statusCode == 201) {
return ItemModel.fromJson(jsonDecode(response.body) as Map<String, dynamic>);
} else {
throw Exception('Failed to create item: ${response.statusCode}');
}
}
// DELETE Request
Future<void> deleteItem(int id) async {
final uri = Uri.https('api.example.com', '/items/$id');
final response = await client.delete(
uri,
headers: <String, String>{'Content-Type': 'application/json; charset=UTF-8'},
);
if (response.statusCode != 200) {
throw Exception('Failed to delete item: ${response.statusCode}');
}
}
}
If fetching a large list of objects, move the JSON decoding and mapping to a separate isolate using compute().
import 'package:flutter/foundation.dart';
// Top-level function required for compute()
List<ItemModel> parseItems(String responseBody) {
final parsed = (jsonDecode(responseBody) as List<Object?>).cast<Map<String, Object?>>();
return parsed.map<ItemModel>(ItemModel.fromJson).toList();
}
Future<List<ItemModel>> fetchLargeItemList(http.Client client) async {
final uri = Uri.https('api.example.com', '/items');
final response = await client.get(uri);
if (response.statusCode == 200) {
// Run parseItems in a separate isolate
return compute(parseItems, response.body);
} else {
throw Exception('Failed to load items');
}
}
When integrating LLMs (like Gemini), enforce reliable JSON output by passing a strict schema in the generation configuration and system instructions.
import 'package:firebase_vertexai/firebase_vertexai.dart';
// Define the expected JSON schema
final _responseSchema = Schema(
SchemaType.object,
properties: {
'width': Schema(SchemaType.integer),
'height': Schema(SchemaType.integer),
'items': Schema(
SchemaType.array,
items: Schema(
SchemaType.object,
properties: {
'id': Schema(SchemaType.integer),
'name': Schema(SchemaType.string),
},
),
),
},
);
// Initialize the model with the schema
final model = FirebaseAI.googleAI().generativeModel(
model: 'gemini-2.5-pro',
generationConfig: GenerationConfig(
responseMimeType: 'application/json',
responseSchema: _responseSchema,
),
);
Future<Map<String, dynamic>> analyzeData(String prompt) async {
final content = [Content.text(prompt)];
final response = await model.generateContent(content);
// Safely decode the guaranteed JSON response
return jsonDecode(response.text!) as Map<String, dynamic>;
}
Uri.https() or Uri.parse() to build URLs. Never use raw string concatenation for endpoints with query parameters.null on a failed network request. Always throw an Exception or a custom error class so the UI (e.g., FutureBuilder) can catch and display the error state via snapshot.hasError.response.statusCode. Use 200 for successful GET/PUT/DELETE and 201 for successful POST.Weekly Installs
971
Repository
GitHub Stars
792
First Seen
Mar 4, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykWarn
Installed on
codex951
cursor949
github-copilot948
gemini-cli947
opencode947
kimi-cli946
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
102,200 周安装
Gemini Interactions API 指南:统一接口、智能体交互与服务器端状态管理
833 周安装
Apollo MCP 服务器:让AI代理通过GraphQL API交互的完整指南
834 周安装
智能体记忆系统构建指南:分块策略、向量存储与检索优化
835 周安装
Scrapling官方网络爬虫框架 - 自适应解析、绕过Cloudflare、Python爬虫库
836 周安装
抽奖赢家选取器 - 随机选择工具,支持CSV、Excel、Google Sheets,公平透明
838 周安装
Medusa 前端开发指南:使用 SDK、React Query 构建电商商店
839 周安装
dart:io HttpClient directly for standard cross-platform networking. Always use the http package to ensure web compatibility.compute(), ensure the parsing function is a top-level function or a static method, and only pass primitive values or simple objects (like String response bodies) across the isolate boundary. Do not pass http.Response objects.