Question #204EasyFlutter Basics

What is the use of jsonPlaceHolder with Flutter ?

#flutter#json

Answer

JSONPlaceholder with Flutter

JSONPlaceholder is a free, fake REST API service that provides placeholder JSON data for testing and prototyping. It's extremely useful for Flutter development when building apps that consume REST APIs.

What is JSONPlaceholder?

JSONPlaceholder (https://jsonplaceholder.typicode.com/) is a mock API service that provides:

  • Fake but realistic JSON data
  • RESTful API endpoints
  • No authentication required
  • Perfect for learning and testing

Available Endpoints

EndpointCountDescription
/posts100Blog posts
/comments500Post comments
/albums100Photo albums
/photos5000Photos
/todos200Todo items
/users10User profiles

Basic Implementation

Model Class:

dart
class Post {
  final int userId;
  final int id;
  final String title;
  final String body;

  Post({
    required this.userId,
    required this.id,
    required this.title,
    required this.body,
  });

  factory Post.fromJson(Map<String, dynamic> json) {
    return Post(
      userId: json['userId'],
      id: json['id'],
      title: json['title'],
      body: json['body'],
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'userId': userId,
      'id': id,
      'title': title,
      'body': body,
    };
  }
}

API Service:

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

class ApiService {
  static const String baseUrl = 'https://jsonplaceholder.typicode.com

  // GET request - Fetch all posts
  Future<List<Post>> getPosts() async {
    final response = await http.get(Uri.parse('$baseUrl/posts'));

    if (response.statusCode == 200) {
      List<dynamic> data = json.decode(response.body);
      return data.map((json) => Post.fromJson(json)).toList();
    } else {
      throw Exception('Failed to load posts');
    }
  }

  // GET request - Fetch single post
  Future<Post> getPost(int id) async {
    final response = await http.get(Uri.parse('$baseUrl/posts/$id'));

    if (response.statusCode == 200) {
      return Post.fromJson(json.decode(response.body));
    } else {
      throw Exception('Failed to load post');
    }
  }

  // POST request - Create new post
  Future<Post> createPost(Post post) async {
    final response = await http.post(
      Uri.parse('$baseUrl/posts'),
      headers: {'Content-Type': 'application/json'},
      body: json.encode(post.toJson()),
    );

    if (response.statusCode == 201) {
      return Post.fromJson(json.decode(response.body));
    } else {
      throw Exception('Failed to create post');
    }
  }

  // PUT request - Update post
  Future<Post> updatePost(int id, Post post) async {
    final response = await http.put(
      Uri.parse('$baseUrl/posts/$id'),
      headers: {'Content-Type': 'application/json'},
      body: json.encode(post.toJson()),
    );

    if (response.statusCode == 200) {
      return Post.fromJson(json.decode(response.body));
    } else {
      throw Exception('Failed to update post');
    }
  }

  // DELETE request - Delete post
  Future<void> deletePost(int id) async {
    final response = await http.delete(Uri.parse('$baseUrl/posts/$id'));

    if (response.statusCode != 200) {
      throw Exception('Failed to delete post');
    }
  }
}

UI Implementation

dart
import 'package:flutter/material.dart';

class PostsScreen extends StatefulWidget {
  
  _PostsScreenState createState() => _PostsScreenState();
}

class _PostsScreenState extends State<PostsScreen> {
  final ApiService _apiService = ApiService();
  late Future<List<Post>> _posts;

  
  void initState() {
    super.initState();
    _posts = _apiService.getPosts();
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('JSONPlaceholder Demo'),
      ),
      body: FutureBuilder<List<Post>>(
        future: _posts,
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return Center(child: CircularProgressIndicator());
          }

          if (snapshot.hasError) {
            return Center(child: Text('Error: ${snapshot.error}'));
          }

          if (!snapshot.hasData || snapshot.data!.isEmpty) {
            return Center(child: Text('No posts found'));
          }

          return ListView.builder(
            itemCount: snapshot.data!.length,
            itemBuilder: (context, index) {
              final post = snapshot.data![index];
              return ListTile(
                title: Text(post.title),
                subtitle: Text(
                  post.body,
                  maxLines: 2,
                  overflow: TextOverflow.ellipsis,
                ),
                onTap: () {
                  // Navigate to post detail
                },
              );
            },
          );
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _createNewPost,
        child: Icon(Icons.add),
      ),
    );
  }

  Future<void> _createNewPost() async {
    final newPost = Post(
      userId: 1,
      id: 0,
      title: 'New Post',
      body: 'This is a new post created from Flutter',
    );

    try {
      final createdPost = await _apiService.createPost(newPost);
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Post created with ID: ${createdPost.id}')),
      );
    } catch (e) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('Failed to create post: $e')),
      );
    }
  }
}

Use Cases in Flutter Development

  • Learning REST APIs: Practice HTTP requests without backend setup
  • Prototyping: Test UI with realistic data
  • Testing: Write unit and widget tests
  • Demo Apps: Build portfolio projects
  • API Integration Practice: Learn pagination, filtering, error handling

Dependencies

Add to

text
pubspec.yaml
:

yaml
dependencies:
  http: ^1.1.0

Best Practices

  • Use proper error handling
  • Implement loading states
  • Cache responses when appropriate
  • Add retry logic for failed requests
  • Use models for type safety

Important: JSONPlaceholder is perfect for development and testing, but remember it's a mock API. Data changes are simulated and don't persist. Use it for learning, then transition to real APIs for production.

Learn more at JSONPlaceholder Guide.