Experimenting with 6 examples of different types of simple and complex JSON structures in Flutter

Overview

Parsing complex JSON in Flutter

Gives a detailed explanation of working with simple and complex JSON structures using dart:convert library in Flutter along with a sample project with 6+ examples to experiment with.

Tutorial

Read the Medium article here

Types of JSON structures

  • Simple map
  • Simple structure with arrays
  • Simple nested structures
  • Nested structure with Lists
  • List of maps
  • Complex nested structures
  • Simple structure with Nested Maps [parsed using json_serializable library]
  • Demo for Network Calls with examples for GET, POST methods along with FutureBuilder and .then()

How to work with Network Calls?

Not covered in the article

Let's take this API as an example.

Take a look at post_model.dart for the model class and utility methods. I produced it using this converter tool

GET getAllPosts

//services.dart
Future<List<Post>> getAllPosts() async {
  final response = await http.get(url);
  return allPostsFromJson(response.body);
}
// As a part of your UI widget, e.g body of Scaffold widget
FutureBuilder<List<Post>>(
            future: getAllPosts(),
            builder: (context, snapshot) {
              if(snapshot.hasData)
                return Text('Title from Post JSON : ${snapshot.data[0].title}');
              else
                return CircularProgressIndicator();
            }
        )

GET getPost (to get a particular POST by id)

//services.dart
Future<Post> getPost() async{
  final response = await http.get('$url/1'); // the number is the id of the item being accessed
  return postFromJson(response.body);
}
// As a part of your UI widget, e.g body of Scaffold widget
FutureBuilder<Post>(
            future: getPost(),
            builder: (context, snapshot) {
              if(snapshot.hasData)
                return Text('Title from Post JSON : ${snapshot.data.title}');
              else
                return CircularProgressIndicator();
            }
        )

POST createPost

//services.dart
Future<http.Response> createPost(Post post) async{
  final response = await http.post('$url',
      headers: {
        HttpHeaders.contentTypeHeader: 'application/json'
      },
      body: postToJson(post)
  );

  return response;
}
  //call this function when you want to create a new post
 callAPI(){
    Post post = Post(
      body: 'Testing body body body',
      title: 'Flutter jam6'
    ); // creating a new Post object to send it to API
    
    createPost(post).then((response){
        if(response.statusCode > 200)
          print(response.body);
        else
          print(response.statusCode);
    }).catchError((error){
      print('error : $error');
    });
    
  }
Comments
  • hello can you help?

    hello can you help?

    i have create this class from the same modal you provided with diffrent data, but having issues

    import 'dart:io'; import 'package:flutter/material.dart'; import 'product/products.dart'; import 'package:provider/provider.dart'; import 'utils/auth.dart'; import 'navigation.dart'; import 'package:mosquegiving/utils/api_util.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; import 'product/productdetail.dart'; import 'subscription/plan.dart'; import 'searchresult.dart'; import 'package:flutter_rating_bar/flutter_rating_bar.dart';

    void main() { runApp(ChangeNotifierProvider( create: (BuildContext context) => AuthProvider(), child: MyApp(), )); }

    class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'MY Finance', debugShowCheckedModeBanner: false, home: MyHomePage(), ); } }

    class MyHomePage extends StatefulWidget { @override _MyHomePageState createState() => _MyHomePageState(); }

    class _MyHomePageState extends State { var _url = Uri.parse(ApiUtility.Main_Url + '/products'); var nexturl; double average = 2; ScrollController _scrollController = new ScrollController(); //determine if all data has been recieved var loadCompleted = false; List tempList = [];

    var mycontroler = TextEditingController(); @override void initState() { super.initState(); readToken(); data = getData(_url); scrollindecator(); }

    late Future<List> data;

    void scrollindecator() { _scrollController.addListener( () { if (_scrollController.offset >= _scrollController.position.maxScrollExtent && !_scrollController.position.outOfRange) { print('reach to bottom botton'); if (!loadCompleted) { setState(() { data = getData(Uri.parse(nexturl)); }); } } }, ); }

    Future<List> getData(_url) async { final response = await http.get(_url, headers: {}); if (response.statusCode == 200) { // ignore: unused_local_variable var data3 = json.decode(response.body)['links']; if (data3['next'] != null) { nexturl = data3['next']; } else { loadCompleted = true; } var data = List<Map<String, dynamic>>.from(json.decode(response.body)['data']); for (int i = 0; i < data.length; i++) { tempList.add(Product.fromJson(data[i])); } return tempList; } else { throw SocketException('Make sure you have an internet connection'); } }

    void dispose() { super.dispose(); _scrollController.dispose(); mycontroler.dispose(); }

    void readToken() async { await Provider.of(context, listen: false).tryToken(); }

    Widget build(BuildContext context) { double height = MediaQuery.of(context).size.height; double width = MediaQuery.of(context).size.width; double text = MediaQuery.textScaleFactorOf(context); return Scaffold( appBar: AppBar( title: Text( 'Mosque Giving', style: TextStyle(color: Color(0XFF1A1A1A)), ), centerTitle: true, elevation: 0, backgroundColor: Color(0xFF50BC90), ), body: ListView( controller: _scrollController, children: [ Padding( padding: EdgeInsets.all(8.0), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, mainAxisSize: MainAxisSize.max, children: [ Text( 'Giving to your local mosque made easy!', style: TextStyle( fontWeight: FontWeight.bold, fontSize: text * 16, ), ), SizedBox( height: height * 0.03, ), Row( mainAxisSize: MainAxisSize.max, children: [ Expanded( child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(0.0), color: Colors.grey[200], boxShadow: [ BoxShadow( color: Colors.grey, offset: Offset(0.0, 1.0), blurRadius: 1.0, ), ], ), child: TextField( controller: mycontroler, decoration: InputDecoration( icon: Padding( padding: EdgeInsets.only(left: 12.0), child: Icon( Icons.search, color: Colors.grey, ), ), border: InputBorder.none, focusedBorder: InputBorder.none, enabledBorder: InputBorder.none, errorBorder: InputBorder.none, disabledBorder: InputBorder.none, ), ), ), ), SizedBox(width: width * 0.00), Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(0.0), color: Colors.grey[200], boxShadow: [ BoxShadow( color: Colors.grey, offset: Offset(0.0, 1.0), blurRadius: 1.0, ), ], ), child: SizedBox( height: height * 0.06, child: ElevatedButton( style: ElevatedButton.styleFrom( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(0.0), ), primary: Color(0xFF50BC90)), onPressed: () { if (mycontroler.text == '') { final snackBar = SnackBar( content: Text('Please enter a keyword!')); ScaffoldMessenger.of(context) .showSnackBar(snackBar); } else { Navigator.push( context, MaterialPageRoute( builder: (context) => Search(mycontroler.text)), ); } }, child: Text('search')), ), ), ], ), SizedBox( height: 10.0, ), Row( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'All Mosque', style: TextStyle( fontWeight: FontWeight.bold, ), ), ], ), SizedBox( height: 10.0, ), ], ), ], ), ), FutureBuilder<List>( future: data, builder: (context, snapshot) { if (snapshot.hasData) { return ListView.builder( physics: ScrollPhysics(), shrinkWrap: true, padding: const EdgeInsets.all(8), itemCount: snapshot.data!.length, itemBuilder: (context, index) { Product product = snapshot.data![index]; if (index == snapshot.data!.length - 1 && !loadCompleted) { return Center( child: new Opacity( opacity: 1.0, child: new CircularProgressIndicator(), ), ); } else { return Padding( padding: const EdgeInsets.only(bottom: 15), child: InkWell( child: Card( elevation: 0, child: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(8.0), color: Colors.grey[200], boxShadow: [ BoxShadow( color: Colors.grey, offset: Offset(0.0, 1.0), blurRadius: 1.0, ), ], ), // color: Colors.black12, padding: EdgeInsets.all(2), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Container( width: double.infinity, child: Stack( children: [ Container( padding: EdgeInsets.only(top: 1), width: double.infinity, // child: Image( // image: NetworkImage( // ApiUtility.Assest_Url + // product.dealimage), // height: 180, // fit: BoxFit.fitWidth), ), ], ), ), Container( width: double.infinity, child: Stack( alignment: Alignment.bottomLeft, children: [ Container( // color: Colors.black.withOpacity(0.5), padding: const EdgeInsets.all(8.0), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Padding( padding: const EdgeInsets.all( 1.0), child: Text( product.images[0].title, style: TextStyle( fontSize: 15, fontWeight: FontWeight.bold, ), )), Padding( padding: const EdgeInsets.fromLTRB( 0, 8, 0, 8), child: RichText( text: TextSpan( children: [ WidgetSpan( child: Icon( Icons.location_on, size: 18, color: Color( 0xFF50BC90)), ), TextSpan( text: product.address, style: TextStyle( color: Colors .black)), ], ), ), ), Row( children: [ RatingBar.builder( initialRating: average, minRating: 0, direction: Axis.horizontal, allowHalfRating: false, itemCount: 5, itemPadding: EdgeInsets.symmetric( horizontal: 4.0), itemBuilder: (context, _) => Icon( Icons.star, color: Color(0xFF50BC90), ), onRatingUpdate: (rating) { print(rating); }, ), ], ), Row( children: [ Container( height: 40, child: ElevatedButton( style: ElevatedButton .styleFrom( primary: Color( 0xFF50BC90)), onPressed: () { Navigator.of(context) .push( _createRoute( product .id)); }, child: Text('Donate Now'), ), ), SizedBox(width: 3), Container( height: 40, child: ElevatedButton( style: ElevatedButton .styleFrom( primary: Color( 0xFF50BC90)), onPressed: () { Navigator.push( context, new MaterialPageRoute( builder: (context) => new Productdetails( prd: new Product( id: product .id, address: product.address, title: product .title, category: product.category, dealimage: product.dealimage, description: product.description, slug: product .slug, )))); }, child: Text( 'View Details'), ), ), ], ) ], ), ), ], ), ), ], ), ), ), ), ); } }, ); } else if (snapshot.hasError) { return Center( child: Text( "Make sure you have an active internet connection")); } return Center(child: CircularProgressIndicator()); }), ], // This trailing comma makes auto-formatting nicer for build methods. ), drawer: Navigation(), ); }

    Route _createRoute(id) { return PageRouteBuilder( pageBuilder: (context, animation, secondaryAnimation) => Plan(id), transitionsBuilder: (context, animation, secondaryAnimation, child) { return child; }, ); } }

    opened by atta1234 0
  • When a Json calls an another Json

    When a Json calls an another Json

    Hey! Thanks a lot, your article help me so much. But I have a question, not a issue (sorry if I doing this wrong). I'm making an app who based in a WordPress site and the API parse a Json who calls an another Json. So, how I can parsing this? If you wanna to see my code, follow here, have some errors so far, but as long I go coding I will fixing it, or this is the API. Can you help me?

    This App will help a lot deaf people in my country!

    Thank you again!

    opened by adrianofreires 0
  • can you please help with parsing this json ?

    can you please help with parsing this json ?

    hi, may i ask you to help me please to parse this json in this url ,

    http://opml.radiotime.com/Browse.ashx?render=json&c=podcast

    my code is here, so what i did wrong please ?

    import 'dart:convert';
    import 'package:flutter/foundation.dart';
    import 'package:flutter/material.dart';
    import 'package:http/http.dart' as http;
    Future<List<Children>> fetchsprodcasts(http.Client client) async {
      final response =
      await client.get("http://opml.radiotime.com/Browse.ashx?render=json&c=podcast", headers: {'Content-Type': 'application/json; charset=utf-8'});
      return compute(parseProdcasts,utf8.decode(response.bodyBytes));
    }
    List<Children> parseProdcasts(String responseBody) {
      final parsed = jsonDecode(responseBody)['body'].map((item)=> item['children']).toList().expand((x) => x).toList();
      return parsed.map((m) => new Children.fromJson(m)).toList();
    }
    class Prodcasts {
      Head head;
      List<Body> body;
    
      Prodcasts({this.head, this.body});
    
      Prodcasts.fromJson(Map<String, dynamic> json) {
        head = json['head'] != null ? new Head.fromJson(json['head']) : null;
        if (json['body'] != null) {
          body = new List<Body>();
          json['body'].forEach((v) {
            body.add(new Body.fromJson(v));
          });
        }
      }
    
      Map<String, dynamic> toJson() {
        final Map<String, dynamic> data = new Map<String, dynamic>();
        if (this.head != null) {
          data['head'] = this.head.toJson();
        }
        if (this.body != null) {
          data['body'] = this.body.map((v) => v.toJson()).toList();
        }
        return data;
      }
    }
    class Head {
      String title;
      String status;
    
      Head({this.title, this.status});
    
      Head.fromJson(Map<String, dynamic> json) {
        title = json['title'];
        status = json['status'];
      }
    
      Map<String, dynamic> toJson() {
        final Map<String, dynamic> data = new Map<String, dynamic>();
        data['title'] = this.title;
        data['status'] = this.status;
        return data;
      }
    }
    class Body {
      String element;
      String text;
      List<Children> children;
    
      Body({this.element, this.text, this.children});
    
      Body.fromJson(Map<String, dynamic> json) {
        element = json['element'];
        text = json['text'];
        if (json['children'] != null) {
          children = new List<Children>();
          json['children'].forEach((v) {
            children.add(new Children.fromJson(v));
          });
        }
      }
    
      Map<String, dynamic> toJson() {
        final Map<String, dynamic> data = new Map<String, dynamic>();
        data['element'] = this.element;
        data['text'] = this.text;
        if (this.children != null) {
          data['children'] = this.children.map((v) => v.toJson()).toList();
        }
        return data;
      }
    }
    class Children {
      String element;
      String type;
      String text;
      String uRL;
      String guideId;
    
      Children({this.element, this.type, this.text, this.uRL, this.guideId});
    
      Children.fromJson(Map<String, dynamic> json) {
        element = json['element'];
        type = json['type'];
        text = json['text'];
        uRL = json['URL'];
        guideId = json['guide_id'];
      }
    
      Map<String, dynamic> toJson() {
        final Map<String, dynamic> data = new Map<String, dynamic>();
        data['element'] = this.element;
        data['type'] = this.type;
        data['text'] = this.text;
        data['URL'] = this.uRL;
        data['guide_id'] = this.guideId;
        return data;
      }
    }
    void main() {
      runApp(ParseProdcastss());
    }
    class ParseProdcastss extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return  ParseProdcasts();
      }
    }
    class ParseProdcasts extends StatelessWidget {
      ParseProdcasts({Key key}) : super(key: key);
      @override
      Widget build(BuildContext context) {
        return  FutureBuilder<List<Children>>(
          future: fetchsprodcasts(http.Client()),
          builder: (context, snapshot) {
            if (snapshot.hasError) print(snapshot.error);
            return snapshot.hasData
                ? ProdcastsList(childrenList: snapshot.data) :Container(
              color: Colors.white,
                  child: Center(child: new CircularProgressIndicator(
              backgroundColor: Color(0xff193451),
              valueColor: AlwaysStoppedAnimation<Color>(Colors.blueGrey),
            )),
                );
          },
        );
      }
    }
    class ProdcastsList extends StatefulWidget {
      List<Children> childrenList = []; // We assume that you filled this list with children.
      ProdcastsList({Key key, this.childrenList}) : super(key: key);
      @override
      _ProdcastsListState createState() => _ProdcastsListState();
    }
    class _ProdcastsListState extends State<ProdcastsList> {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            backgroundColor: Colors.blueGrey,
            body: Container(
              color: Colors.blueGrey,
              child: Column(
                children: [
                  Expanded(
                    child: ListView.builder(
                      physics: ClampingScrollPhysics(),
                      shrinkWrap: true,
                      itemCount: widget.childrenList.length,
                      itemBuilder: (context, index) {
                        return ExpansionTile(
                          backgroundColor: Colors.grey.shade200,
                          children: <Widget>[
                          ],
                          title: Text('${widget.childrenList[index].text}',style: TextStyle(fontSize: 12, color: Colors.blueGrey),),
                          subtitle: Text(''),
                        );
                      },
                    ),
                  ),
                ],
              ),
            ),
          ),
        );
      }
    }
    
    opened by basharbachir 0
  • about translation your article

    about translation your article

    hi there, I recently had a trouble to convert JSON in flutter and your article was so helpful for me. so, i want to share your article in Korean so that flutter-starters can get the idea without language barrier. would you mind if I translate your article 'parsing-complex-json in flutter'?

    I definately leave your source and original link of the article.

    thanks,

    opened by oowgnoj 1
  • API calls should not be in build() method

    API calls should not be in build() method

    opened by jirihradil 0
Owner
Pooja Bhaumik
Creator | Mentor | Developer | Google Developer Expert @Flutter
Pooja Bhaumik
Examples of all types of widgets used for animation in Flutter.

Anny Flutter application for learning animations concept. Checkout the live demo here. License Copyright 2020 Ashutosh Singh Licensed under the A

Ashutosh Singh 23 Nov 22, 2022
John Pfister 2 Feb 25, 2022
Application to practice creating different types of screen in flutter

Diseño de paginas en flutter. Getting Started This project is a starting point for a Flutter application. A few resources to get you started if this i

Diego Martinez 2 Nov 29, 2021
A Flutter app to showcase different types of Splash Screens

Flutter Splash Demo A Flutter applicaiton to showcase how to make different types of Splash Screens. In this demo we have used Video Player plugin, th

FlutterDevs 173 Dec 29, 2022
A showcase app for the Flutter SDK. Wonderous will educate and entertain as you uncover information about some of the most famous structures in the world.

Wonderous Navigate the intersection of history, art, and culture. Wonderous will educate and entertain as you uncover information about some of the mo

gskinner team 2.3k Dec 29, 2022
Implementation of data structures and algorithms in Dart programming language.

Algorithms in Dart Implementation of several algorithms with Dart programming language. Use dartdoc to generate documentation. Lists List data structu

Mafinar Khan 197 Dec 24, 2022
Prepare for Data Structures & Algorithms questions for your upcoming interviews with this Flutter App made by Parker Shamblin.

flutter_data_structures_and_algorithms Prepare for Data Structures & Algorithms questions for your upcoming interviews with this Flutter App made by P

Parker Shamblin 3 Jun 12, 2022
A JSON serialize class to convert 'to' and 'from' JSON format Enums, DateTime and any of your own classes.

A JSON serialize class to convert 'to' and 'from' JSON format Enums, DateTime and any of your own classes. Introduction Jsonize solves the problem of

null 2 Nov 17, 2022
Given a JSON string, this library will generate all the necessary Dart classes to parse and generate JSON.

JSON to Dart Given a JSON string, this library will generate all the necessary Dart classes to parse and generate JSON. This library is designed to ge

Javier Lecuona 1.2k Dec 25, 2022
Flutter package: Json Table Widget to create table from json array

Json Table Widget ?? Proudly Sponsored by FieldAssist Request a Demo This Flutter package provides a Json Table Widget for directly showing table from

Ayush P Gupta 193 Jan 7, 2023
Fluter-json - App Demonstrating JSON Data Parsing with various flutter widgets

users_list Flutter App to Demonstrate JSON Parsing Getting Started This project is a starting point for a Flutter application. A few resources to get

Khurram Rizvi 5 Jul 10, 2021
Json editor - A json editor on flutter

Features Support add comment; Support show errors for invalid json text; Pretty

Chan Young 12 Nov 18, 2022
State Persistence - Persist state across app launches. By default this library store state as a local JSON file called `data.json` in the applications data directory. Maintainer: @slightfoot

State Persistence Persist state across app launches. By default this library store state as a local JSON file called data.json in the applications dat

Flutter Community 70 Sep 28, 2022
A super powerful widget to help developers build complex views quickly and comfortably.

FSuper FSuper can help developers build complex views quickly and comfortably. It supports rich text, rounded corners, borders, pictures, small red do

Fliggy Mobile 481 Dec 29, 2022
A super powerful widget to help developers build complex views quickly and comfortably.

FSuper FSuper can help developers build complex views quickly and comfortably. It supports rich text, rounded corners, borders, pictures, small red do

Fliggy Mobile 481 Dec 29, 2022
A CustomPaint example where we can draw with different colors and different stroke sizes

CustomPaint A CustomPaint example where we can draw with different colors and different stroke sizes. A Flutter application which runs on iOS, Android

Behruz Hurramov 0 Dec 27, 2021
Flutter Navigation - all types of navigation in flutter run main.tabBar.dart to see tabBar, and run main.dart to see the otheres

pop_up_bar A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you started if th

Michael Odumosu 0 Jan 1, 2022
Immutable value types, enum classes, and serialization.

Built Values for Dart Introduction Built Value provides: Immutable value types; EnumClass, classes that behave like enums; JSON serialization. Immutab

Google 816 Dec 23, 2022
Ruqe brings the convenient types and methods found in Rust into Dart, such as the Result, Option, pattern-matching, etc.

ruqe Ruqe brings the convenient types and methods found in Rust into Dart, such as the Result, Option, pattern-matching, etc. Additionally, the librar

Alexander Nitiola 12 Dec 28, 2022