Creating a REST API program
Add the dependencies
pubspec.yaml
dependencies:
http: ^0.13.5main.dart
import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart' as http;Here’s what each import is for:
- As you recall from Chapter 10, “Error Handling”, the
dart:convertlibrary gives youjsonDecode, a function for converting a raw JSON string to a Dart map.
- The
dart:iolibrary hasHttpExceptionandSocketException, which you’ll use shortly.
- The final import is the
httplibrary you just added topubspec.yaml. Note theas httpat the end. This isn’t necessary, but theaskeyword lets you prefix any functions from the library with the namehttp. You don’t need to call ithttp— any arbitrary name is fine. Feel free to change the name topinkElephantsif you so desire. Providing a custom name can be useful for avoiding naming conflicts with other libraries or functions.
Lets create todo class to store data
class Todo {
Todo({
required this.userId,
required this.id,
required this.title,
required this.completed,
});
factory Todo.fromJson(Map<String, dynamic> jsonMap) {
return Todo(
userId: jsonMap['userId'] as int,
id: jsonMap['id'] as int,
title: jsonMap['title'] as String,
completed: jsonMap['completed'] as bool,
);
}
final int userId;
final int id;
final String title;
final bool completed;
@override
String toString() {
return 'userId: $userId\n'
'id: $id\n'
'title: $title\n'
'completed: $completed';
}
}GET request
Future<void> main() async {
// 1
final url = 'https://jsonplaceholder.typicode.com/todos/1';
final parsedUrl = Uri.parse(url);
// 2, 3
final response = await http.get(parsedUrl);
// 4
final statusCode = response.statusCode;
if (statusCode != 200) {
throw HttpException('$statusCode');
}
// 5
final jsonString = response.body;
dynamic jsonMap = jsonDecode(jsonString);
// 6
final todo = Todo.fromJson(jsonMap);
print(todo);
}There are a few new things here, so have a look at each of them:
- The URL address is for a server that provides an API that returns sample JSON for developers. It’s much like the type of API you would make as a backend for a client app.
Uri.parseconverts the raw URL string to a format thathttp.getrecognizes.
- You use
http.getto make aGETrequest to the URL. ChangehttptopinkElephantsif that’s what you called it earlier.GETrequests are the same requests browsers make when you type a URL in the address bar.
- Because it takes time to contact a server that might exist on another continent,
http.getreturns a future. Dart passes the work of contacting the remote server to the underlying platform, so you won’t need to worry about it blocking your app while you wait. Because you’re using theawaitkeyword, the rest of the main method will be added to the event queue when the future completes. If the future completes with a value, the value will be an object of typeResponse, which includes information from the server.
- HTTP defines various three-digit status codes. A status code of
200meansOK— the request was successful, and the server did what you asked. On the other hand, the common status code of404means the server couldn’t find what you were asking for. If that happens, you’ll throw anHttpException.
- The response body from this URL address includes a string in JSON format. You use
jsonDecodefrom thedart:convertlibrary to convert the raw JSON string into a Dart map. The type isdynamicbecause JSON strings are untyped by nature. You’re assuming that it’s a map, but theoretically, it might not be. You can do some extra type checking or error checking if you want to be sure.
- Once you have a Dart
map, you can pass it into thefromJsonfactory constructor of yourTodoclass that you wrote earlier.
Lets handle those errors
A few things could go wrong with the code above, so you’ll need to be ready to handle any errors. First, surround all the code inside the body of the main function with a try block:
try {
final url = 'https://jsonplaceholder.typicode.com/todos/1';
// ...
}
Then, below the try block, add the following catch blocks:
on SocketException catch (error) {
print(error);
} on HttpException catch (error) {
print(error);
} on FormatException catch (error) {
print(error);
}
Here’s what each of the exceptions means:
SocketException: You’ll get this exception if there’s no internet connection. Thehttp.getmethod is the one to throw the exception.
HttpException: You’re throwing this exception yourself if the status code isn’t200OK.
FormatException:jsonDecodethrows this exception if the JSON string from the server isn’t in proper JSON format. It would be unwise to blindly trust whatever the server gives you.