DEV Community

codebangkok
codebangkok

Posted on

Flutter & Dart: Call RESTful API and Authen with JWT

Agenda

  • Call REST API with GET Method
  • Call REST API with POST Method
  • JSON Serialization (jsonEncode)
  • JSON Deserializaton (jsonDecode)
  • Call Authorized REST API with JWT

Prerequisite

1. สร้างโปรเจ็ค แล้ว migrate ให้ dart ซัพพอร์ท null safety

dart create rest_api cd rest_api dart migrate --apply-changes 
Enter fullscreen mode Exit fullscreen mode

2. ติดตั้ง http package

dart pub add http 
Enter fullscreen mode Exit fullscreen mode

เข้าไปดูได้ที่ https://pub.dev/packages/http
Alt Text

3. เตรียม API

ผมทำเอาไว้เพื่อทดสอบแล้วที่ https://techcoach.azurewebsites.net
Alt Text

4. ตัวอย่างที่ 1 การเรียก API แบบ GET กับการดึงค่า Gender

URL: https://techcoach.azurewebsites.net/registration/genders
Alt Text

4.1 import http,io,convert package แล้วสร้างฟังชั่น getGender แบบ async
import 'package:http/http.dart' as http; import 'dart:io'; import 'dart:convert'; void main(List<String> arguments) { } Future getGenders() async { } 
Enter fullscreen mode Exit fullscreen mode
4.2 เขียนโปรแกรมที่ฟังชั่น getGenders เรียกฟังชั่น http.get แล้วส่ง URL เข้าไปดังนี้
final response = await http.get( Uri.parse('https://techcoach.azurewebsites.net/registration/genders'), ); 
Enter fullscreen mode Exit fullscreen mode
4.2 ตรวจสอบว่าถ้าสถานะไม่ใช่ ok (200) ก็จะหยุดการทำงาน
if (response.statusCode != HttpStatus.ok) { print('Response: ${response.statusCode}'); return; } 
Enter fullscreen mode Exit fullscreen mode
4.3 พิมพ์ผลที่ได้ออกมาดูก่อน
print(response.body); 
Enter fullscreen mode Exit fullscreen mode
4.3 เปลี่ยนที่ฟังชั่น main เป็นแบบ async แล้วเรียกฟังชั่น getGenders
void main(List<String> arguments) async { await getGenders(); } 
Enter fullscreen mode Exit fullscreen mode

ผลลัพธ์ที่ได้หลังจากการรันคำสั่ง

dart run [{"id":1,"name":"ชาย"},{"id":2,"name":"หญิง"}] 
Enter fullscreen mode Exit fullscreen mode

Alt Text

4.4 สร้างคลาส Gender โดยมี id กับ name เป็น arribute พร้อมกับสร้าง constructor เพื่อรับค่าด้วย
class Gender { final int id; final String name; Gender({ required this.id, required this.name, }); } 
Enter fullscreen mode Exit fullscreen mode
4.4 เพิ่ม factory constructor ให้กับ Gender เพื่อความสะดวกในการแปลงจาก Map เป็น Object
class Gender { final int id; final String name; Gender({ required this.id, required this.name, }); factory Gender.fromJson(Map<String, dynamic> json) => Gender( id: json['id'], name: json['name'], ); } 
Enter fullscreen mode Exit fullscreen mode
4.5 แก้ไขฟังชั่น getGenders ลบบรรทัด print ออกแล้วเพิ่มคำสั่ง jsonDecode เพื่อแปลงจาก JSON String ให้เป็น List ของ Map
final json = jsonDecode(response.body) as List; 
Enter fullscreen mode Exit fullscreen mode
4.6 ใช้ map เพื่อแปลงจาก Map ให้กลายเป็น List ของ Gender
final genders = json.map((e) => Gender.fromJson(e)).toList(); 
Enter fullscreen mode Exit fullscreen mode
4.6 แสดงผลที่ได้จาก List ของ Gender
for (var gender in genders) { print('id: ${gender.id}, name: ${gender.name}'); } 
Enter fullscreen mode Exit fullscreen mode

ผลลัพธ์ที่ได้หลังจากการรันคำสั่ง

dart run id: 1, name: ชาย id: 2, name: หญิง 
Enter fullscreen mode Exit fullscreen mode

Alt Text
โค้ดทั้งหมด

import 'package:http/http.dart' as http; import 'dart:io'; import 'dart:convert'; void main(List<String> arguments) async { await getGenders(); } Future getGenders() async { final response = await http.get( Uri.parse('https://techcoach.azurewebsites.net/registration/genders'), ); if (response.statusCode != HttpStatus.ok) { print('Response: ${response.statusCode}'); return; } final json = jsonDecode(response.body) as List; final genders = json.map((e) => Gender.fromJson(e)).toList(); for (final gender in genders) { print('id: ${gender.id}, name: ${gender.name}'); } } class Gender { int id; String name; Gender({ required this.id, required this.name, }); factory Gender.fromJson(Map<String, dynamic> json) => Gender( id: json['id'], name: json['name'], ); } 
Enter fullscreen mode Exit fullscreen mode

5. ตัวอย่างที่ 2 การเรียก API แบบ POST กับการลงทะเบียน User โดยจะต้องส่ง payload ในรูปแบบ JSON ที่ body ด้วย

URL: https://techcoach.azurewebsites.net/registration/users
Alt Text

5.1 สร้างฟังชั่น signup แบบ async รับพารามิเตอร์ที่ต้องการ แล้วเรียกฟังชั่น http.post แล้วส่ง URL เข้าไปดังนี้
Future signup({ required final String firstName, required final String lastName, required final String email, required final String password, required final int genderId, }) async { final response = await http.post( Uri.parse('https://techcoach.azurewebsites.net/registration/users'), ); } 
Enter fullscreen mode Exit fullscreen mode
5.2 เพิ่ม content-type: application/json เข้าไปที่ headers
final response = await http.post( Uri.parse('https://techcoach.azurewebsites.net/registration/users'), headers: {'content-type': 'application/json'}, ); 
Enter fullscreen mode Exit fullscreen mode
5.3 ที่ body สร้าง Map ของคีย์ต่างๆที่ payload ต้องการ แล้วใช้ jsonEncode เพื่อแปลงจาก Map ให้เป็น JSON String
final response = await http.post( Uri.parse('https://techcoach.azurewebsites.net/registration/users'), headers: {'content-type': 'application/json'}, body: jsonEncode({ 'firstName': firstName, 'lastName': lastName, 'email': email, 'password': password, 'genderId': genderId, }), ); 
Enter fullscreen mode Exit fullscreen mode
5.4 ตรวจสอบว่าถ้าสถานะ ok (200) แสดงผลคำว่า signup success
if (response.statusCode != HttpStatus.ok) { print('Response: ${response.statusCode}'); return; } print('signup success'); 
Enter fullscreen mode Exit fullscreen mode
5.5 ที่ฟังชั่น main ให้เรียกฟังชั่น signup ตัวอย่างดังนี้
void main(List<String> arguments) async { await signup( firstName: 'Code', lastName: 'Bangkok', email: 'codebangkok@gmail.com', password: 'iloveyou', genderId: 1, ); } 
Enter fullscreen mode Exit fullscreen mode

ผลลัพธ์ที่ได้หลังจากการรันคำสั่ง

dart run signup success 
Enter fullscreen mode Exit fullscreen mode

Alt Text

โค้ดที่เกี่ยวข้องทั้งหมด

import 'package:http/http.dart' as http; import 'dart:io'; import 'dart:convert'; void main(List<String> arguments) async { await signup( firstName: 'Code', lastName: 'Bangkok', email: 'codebangkok@gmail.com', password: 'iloveyou', genderId: 1, ); } Future signup({ required final String firstName, required final String lastName, required final String email, required final String password, required final int genderId, }) async { final response = await http.post( Uri.parse('https://techcoach.azurewebsites.net/registration/users'), headers: {'content-type': 'application/json'}, body: jsonEncode({ 'firstName': firstName, 'lastName': lastName, 'email': email, 'password': password, 'genderId': genderId, }), ); if (response.statusCode != HttpStatus.ok) { print('Response: ${response.statusCode}'); return; } print('signup success'); } 
Enter fullscreen mode Exit fullscreen mode

6. ตัวอย่างที่ 3 การเรียก API แบบ POST กับการ Login โดยจะต้องส่ง payload ในรูปแบบ JSON ที่ body และรับค่า response กลับมาด้วย

URL: https://techcoach.azurewebsites.net/registration/login
Alt Text

6.1 สร้างฟังชั่น login แบบ async รับพารามิเตอร์ที่ต้องการ แล้วเรียกฟังชั่น http.post แล้วส่ง URL เข้าไปดังนี้
Future login({ required final String email, required final String password, }) async { final response = await http.post( Uri.parse('https://techcoach.azurewebsites.net/registration/login'), ); } 
Enter fullscreen mode Exit fullscreen mode
6.2 เพิ่ม content-type: application/json เข้าไปที่ headers
final response = await http.post( Uri.parse('https://techcoach.azurewebsites.net/registration/login'), headers: {'content-type': 'application/json'}, ); 
Enter fullscreen mode Exit fullscreen mode
6.3 ที่ body สร้าง Map ของคีย์ต่างๆที่ payload ต้องการ แล้วใช้ jsonEncode เพื่อแปลงจาก Map ให้เป็น JSON String
final response = await http.post( Uri.parse('https://techcoach.azurewebsites.net/registration/login'), headers: {'content-type': 'application/json'}, body: jsonEncode({ 'email': email, 'password': password, }), ); 
Enter fullscreen mode Exit fullscreen mode
6.4 ตรวจสอบว่าถ้าสถานะไม่ใช่ ok (200) ก็จะหยุดการทำงาน
if (response.statusCode != HttpStatus.ok) { print('Response: ${response.statusCode}'); return; } 
Enter fullscreen mode Exit fullscreen mode
6.5 สร้างคลาส User โดยมี arribute ต่างๆตาม response พร้อมกับสร้าง constructor เพื่อรับค่าด้วย
class User { final int id; final String firstName; final String lastName; final String email; final Gender gender; final String jwtToken; User({ required this.id, required this.firstName, required this.lastName, required this.email, required this.gender, required this.jwtToken, }); } 
Enter fullscreen mode Exit fullscreen mode
6.6 เพิ่ม factory constructor ให้กับ User เพื่อความสะดวกในการแปลงจาก Map เป็น Object
class User { final int id; final String firstName; final String lastName; final String email; final Gender gender; final String jwtToken; User({ required this.id, required this.firstName, required this.lastName, required this.email, required this.gender, required this.jwtToken, }); factory User.fromJson(Map<String, dynamic> json) => User( id: json['id'], firstName: json['firstName'], lastName: json['lastName'], email: json['email'], gender: Gender.fromJson(json['gender']), jwtToken: json['jwtToken'], ); } 
Enter fullscreen mode Exit fullscreen mode
6.7 แก้ไขฟังชั่น login เพิ่มคำสั่ง jsonDecode เพื่อแปลงจาก JSON String ไปเป็น Map
final json = jsonDecode(response.body); 
Enter fullscreen mode Exit fullscreen mode
6.8 แปลงจาก Map ให้กลายเป็น User object ด้วย fromJson
final user = User.fromJson(json); 
Enter fullscreen mode Exit fullscreen mode
6.9 แสดงผลที่ได้จาก User object
print('First Name: ${user.firstName}'); print('Last Name: ${user.lastName}'); print('Email: ${user.email}'); print('Gender: ${user.gender.name}'); print('JWT Token: ${user.jwtToken}'); 
Enter fullscreen mode Exit fullscreen mode
6.10 ที่ฟังชั่น main ให้เรียกฟังชั่น login ตัวอย่างดังนี้
void main(List<String> arguments) async { await login( email: 'codebangkok@gmail.com', password: 'iloveyou', ); } 
Enter fullscreen mode Exit fullscreen mode

ผลลัพธ์ที่ได้หลังจากการรันคำสั่ง (jwt token จะเปลี่ยนทุกครั้งที่รัน)

dart run First Name: Code Last Name: Bangkok Email: codebangkok@gmail.com Gender: ชาย JWT Token: eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjYiLCJzdWIiOiJjb2RlYmFuZ2tva0BnbWFpbC5jb20iLCJlbWFpbCI6ImNvZGViYW5na29rQGdtYWlsLmNvbSIsIm5iZiI6MTYxOTY5MDkwMSwiZXhwIjoxNjE5NzEyNTAxLCJpYXQiOjE2MTk2OTA5MDF9.BBQ6RDSIZodGdn19Af5HrZLHSyGOJJReXAsSXfN2LG1dc4kTK6SlLc6U7e65-9iSBqiM4MA97EMvJvRUYKbUwQ 
Enter fullscreen mode Exit fullscreen mode

Alt Text

โค้ดที่เกี่ยวข้องทั้งหมด

import 'package:http/http.dart' as http; import 'dart:io'; import 'dart:convert'; void main(List<String> arguments) async { await login( email: 'codebangkok@gmail.com', password: 'iloveyou', ); } Future login({ required final String email, required final String password, }) async { final response = await http.post( Uri.parse('https://techcoach.azurewebsites.net/registration/login'), headers: {'content-type': 'application/json'}, body: jsonEncode({ 'email': email, 'password': password, }), ); if (response.statusCode != HttpStatus.ok) { print('Response: ${response.statusCode}'); return; } final json = jsonDecode(response.body); final user = User.fromJson(json); print('First Name: ${user.firstName}'); print('Last Name: ${user.lastName}'); print('Email: ${user.email}'); print('Gender: ${user.gender.name}'); print('JWT Token: ${user.jwtToken}'); } class User { final int id; final String firstName; final String lastName; final String email; final Gender gender; final String jwtToken; User({ required this.id, required this.firstName, required this.lastName, required this.email, required this.gender, required this.jwtToken, }); factory User.fromJson(Map<String, dynamic> json) => User( id: json['id'], firstName: json['firstName'], lastName: json['lastName'], email: json['email'], gender: Gender.fromJson(json['gender']), jwtToken: json['jwtToken'], ); } 
Enter fullscreen mode Exit fullscreen mode

7. ตัวอย่างที่ 4 การเรียก Authorized API แบบ GET ด้วยการใช้ JWT Token

URL: https://techcoach.azurewebsites.net/registration/users
Alt Text

7.1 สร้างฟังชั่น getUsers แบบ async รับ jwt token เข้ามา แล้วเรียกฟังชั่น http.get แล้วส่ง URL เข้าไปดังนี้
Future getUsers({required String jwtToken}) async { final response = await http.get( Uri.parse('https://techcoach.azurewebsites.net/registration/users'), ); } 
Enter fullscreen mode Exit fullscreen mode
7.2 เพิ่ม Authorization: Bearer เข้าไปที่ headers นำค่า jwt token ที่ได้จากการ login มาใส่
final response = await http.get( Uri.parse('https://techcoach.azurewebsites.net/registration/users'), headers: {'authorization': 'Bearer $jwtToken'}, ); 
Enter fullscreen mode Exit fullscreen mode
7.3 ตรวจสอบว่าถ้าสถานะ ok (200) ก็พิมพ์ผลลัพธ์ที่ได้ออกมาดู
if (response.statusCode != HttpStatus.ok) { print('Response: ${response.statusCode}'); return; } print(response.body); 
Enter fullscreen mode Exit fullscreen mode
7.4 ที่ฟังชั่น main ให้เรียกฟังชั่น getUsers ตัวอย่างดังนี้
void main(List<String> arguments) async { final jwtToken = ''; //นำค่า jwt ที่ได้จากการ login มาใส่ที่นี่ await getUsers(jwtToken: jwtToken); } 
Enter fullscreen mode Exit fullscreen mode

ผลลัพธ์ที่ได้หลังจากการรันคำสั่ง

dart run [{"id":1,"firstName":"Code","lastName":"Bangkok","email":"codebangkok@gmail.com","gender":{"id":1,"name":"ชาย"}}] 
Enter fullscreen mode Exit fullscreen mode

Alt Text

โค้ดทั้งหมด

import 'package:http/http.dart' as http; import 'dart:io'; import 'dart:convert'; void main(List<String> arguments) async { final jwtToken = ''; //นำค่า jwt ที่ได้จากการ login มาใส่ที่นี่ await getUsers(jwtToken: jwtToken); } Future getUsers({required String jwtToken}) async { final response = await http.get( Uri.parse('https://techcoach.azurewebsites.net/registration/users'), headers: {'authorization': 'Bearer $jwtToken'}, ); if (response.statusCode != HttpStatus.ok) { print('Response: ${response.statusCode}'); return; } print(response.body); } Future login({ required final String email, required final String password, }) async { final response = await http.post( Uri.parse('https://techcoach.azurewebsites.net/registration/login'), headers: {'content-type': 'application/json'}, body: jsonEncode({ 'email': email, 'password': password, }), ); if (response.statusCode != HttpStatus.ok) { print('Response: ${response.statusCode}'); return; } final json = jsonDecode(response.body); final user = User.fromJson(json); print('First Name: ${user.firstName}'); print('Last Name: ${user.lastName}'); print('Email: ${user.email}'); print('Gender: ${user.gender.name}'); print('JWT Token: ${user.jwtToken}'); } Future signup({ required final String firstName, required final String lastName, required final String email, required final String password, required final int genderId, }) async { final response = await http.post( Uri.parse('https://techcoach.azurewebsites.net/registration/users'), headers: {'content-type': 'application/json'}, body: jsonEncode({ 'firstName': firstName, 'lastName': lastName, 'email': email, 'password': password, 'genderId': genderId, }), ); if (response.statusCode != HttpStatus.ok) { print('Response: ${response.statusCode}'); return; } print('signup success'); } Future getGenders() async { final response = await http.get( Uri.parse('https://techcoach.azurewebsites.net/registration/genders'), ); if (response.statusCode != HttpStatus.ok) { print('Response: ${response.statusCode}'); return; } final json = jsonDecode(response.body) as List; final genders = json.map((e) => Gender.fromJson(e)).toList(); for (final gender in genders) { print('id: ${gender.id}, name: ${gender.name}'); } } class Gender { final int id; final String name; Gender({ required this.id, required this.name, }); factory Gender.fromJson(Map<String, dynamic> json) => Gender( id: json['id'], name: json['name'], ); } class User { final int id; final String firstName; final String lastName; final String email; final Gender gender; final String jwtToken; User({ required this.id, required this.firstName, required this.lastName, required this.email, required this.gender, required this.jwtToken, }); factory User.fromJson(Map<String, dynamic> json) => User( id: json['id'], firstName: json['firstName'], lastName: json['lastName'], email: json['email'], gender: Gender.fromJson(json['gender']), jwtToken: json['jwtToken'], ); } 
Enter fullscreen mode Exit fullscreen mode

ติดตามผลงานได้ที่

Top comments (0)