قراءة JSON
جزء من قسم البيانات والشبكة في رحلة Flutter على Coddy. الدرس 15 من 27.
نادرًا ما تجيب الخوادم بجملة عادية. فهي ترسل JSON: نصًا يحتوي على بيانات، بأسماء بين علامتي اقتباس وقيم بعد نقطتين. وتُرجع واجهة API التجريبية عند طلب /user ما يلي:
{
"name": "Maya Chen",
"email": "maya@example.com",
"age": 28,
"isPro": true
}بالنسبة إلى تطبيقك، هذا عبارة عن String طويل. تحوّل jsonDecode، من مكتبة dart:convert في Dart، هذا النص إلى قيم Dart. وتصبح الأقواس المعقوفة Map: الأسماء هي مفاتيحها.
import 'dart:convert';
final Map<String, dynamic> user = jsonDecode(body);
print(user['name']); // مايا تشينالمفاتيح دائمًا سلاسل نصية. ويمكن أن تكون القيم نصوصًا أو أرقامًا أو true أو false أو قوائم أو خرائط أخرى، لذا يكون نوعها dynamic: «أي نوع، يُحدَّد أثناء تشغيل التطبيق». يجب أن تتطابق المفاتيح تمامًا: user['Name'] ليست user['name']، والمفتاح غير الموجود يعطي null.
فكّ ترميز الإجابة في الموضع الذي تجلبها فيه، داخل دالة مستقلة، لكي تحصل الشاشة على بيانات جاهزة للاستخدام.
التحدي
متوسطتعرض شاشة الملف الشخصي بيانات JSON الخام. اعرض الشخص بدلًا من ذلك:
- تعيد
loadUserقيمة من النوعFuture<Map<String, dynamic>>: تنتظرfetch('/user')وتعيد نتيجةjsonDecodeللمتن (استوردdart:convert) - يستخدم كلٌّ من
_userوFutureBuilderهذا النوع أيضًا - عند وصول البيانات، اعرض
Columnيحتوي علىuser['name'](بحجم 28 وبخط عريض)، وتحتهuser['email']
جرّب بنفسك
import 'package:flutter/material.dart';
import 'api.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: ProfileScreen(),
);
}
}
class ProfileScreen extends StatefulWidget {
const ProfileScreen({super.key});
@override
State<ProfileScreen> createState() => _ProfileScreenState();
}
class _ProfileScreenState extends State<ProfileScreen> {
late Future<String> _user;
@override
void initState() {
super.initState();
_user = loadUser();
}
Future<String> loadUser() async {
return fetch('/user');
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Profile')),
body: Center(
child: FutureBuilder<String>(
future: _user,
builder: (context, snapshot) {
if (snapshot.hasError) {
return Text('Could not load: ${snapshot.error}');
}
if (snapshot.hasData) {
return Text(snapshot.data!);
}
return const CircularProgressIndicator();
},
),
),
);
}
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البيانات والشبكة
تدرّب بنفسك: مترجم Flutter عبر الإنترنت