Creating a REST API program

Add the dependencies

pubspec.yaml

dependencies:
  http: ^0.13.5

main.dart

import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart' as http;

Here’s what each import is for:

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:

  1. 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.parse converts the raw URL string to a format that http.get recognizes.
  1. You use http.get to make a GET request to the URL. Change http to pinkElephants if that’s what you called it earlier. GET requests are the same requests browsers make when you type a URL in the address bar.
  1. Because it takes time to contact a server that might exist on another continent, http.get returns 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 the await keyword, 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 type Response, which includes information from the server.
  1. HTTP defines various three-digit status codes. A status code of 200 means OK — the request was successful, and the server did what you asked. On the other hand, the common status code of 404 means the server couldn’t find what you were asking for. If that happens, you’ll throw an HttpException.
  1. The response body from this URL address includes a string in JSON format. You use jsonDecode from the dart:convert library to convert the raw JSON string into a Dart map. The type is dynamic because 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.
  1. Once you have a Dart map, you can pass it into the fromJson factory constructor of your Todo class 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: