Complex JSON Parsing in Flutter / Dart

By | February 19, 2019

Hi

This article helps you to do complex Json Parsing in Flutter or dart.

Watch Video Tutorial

Simple JSON

I have the following json in a file named “person.json” in a folder named “json” in root of my project.

{
  "id": "1001",
  "name": "Vipin",
  "age": 25
}

To parse this json, we will create a model class named “Person”.

class Person {
  final String id;
  final String name;
  final int age;

  Person(
      {this.id, this.name, this.age, this.places, this.images, this.address});

  factory Person.fromJson(Map<String, dynamic> json) {
    return Person(
      id: json['id'],
      name: json['name'],
      age: json['age']
    );
  }
}

The “fromJson” method creates a “Person” object and parses the incoming Json object.

Load the JSON file from assets

Future<String> loadPersonFromAssets() async {
        return await rootBundle.loadString('json/person.json');
}

Load the Person

Future loadPerson() async {
    String jsonString = await loadPersonFromAssets();
    final jsonResponse = json.decode(jsonString);
    Person person = new Person.fromJson(jsonResponse);
    print('Name: ${person.name}');
}

Parsing List of Strings

Let’s add some more data to the json file.

"places": [
    "India",
    "US"
  ],

Now we have a list of json strings.

Add the below line to Person class

final List<String> places;

Update the constructor

  Person(
      {this.id, this.name, this.age, this.places, this.images, this.address});

  factory Person.fromJson(Map<String, dynamic> json) {
    return Person(
      id: json['id'],
      name: json['name'],
      age: json['age'],
      places: parsePlaces(json['places']), 
    );
  }

  static List<String> parsePlaces(placesJson) {
    List<String> placesList = new List<String>.from(placesJson);
    return placesList;
  }

The ‘parsePlaces’ will parse the json with places and returns the List of Strings.

Another simple way is just specify

final List places; // in this case it will be List<dynamic>

and the fromJson method will change to just

 places: json['places']);

Parse List of Objects

Now we will add a list of objects to our json.

...
 "images": [
    {
      "id": 10,
      "name": "img1"
    },
    {
      "id": 11,
      "name": "img2"
    }
  ],

Now let’s create the class for Images

class Images {
  final int id;
  final String name;

  Images({this.id, this.name});

  factory Images.fromJson(Map<String, dynamic> parsedJson) {
    return Images(id: parsedJson['id'], name: parsedJson['name']);
  }
}

Now add the images variable to the Person class…

class Person {
  final String id;
  final String name;
  final int age;
  final List<String> places;
  final List<Images> images;

  Person(
      {this.id, this.name, this.age, this.places, this.images, this.address});

  factory Person.fromJson(Map<String, dynamic> json) {
    return Person(
      id: json['id'],
      name: json['name'],
      age: json['age'],
      places: parsePlaces(json['places']), // json['places']);
      images: parseImages(json)
    );
  }

  static List<String> parsePlaces(placesJson) {
    List<String> placesList = new List<String>.from(placesJson);
    return placesList;
  }

  static List<Images> parseImages(imagesJson) {
    var list = imagesJson['images'] as List;
    List<Images> imagesList =
        list.map((data) => Images.fromJson(data)).toList();
    return imagesList;
  }
}

Parse Nested Json Arrays

We are going to add some object to our existing json now.

...
 "address": {
    "street_no": "1212",
    "details": {
      "house_no": 3355,
      "town": "Test Town"
    }
  }

Here we have the details object nested inside “address”.
So we have to create model class for Details first.

class Details {
  final int houseNo;
  final String town;

  Details({this.houseNo, this.town});

  factory Details.fromJson(Map<String, dynamic> json) {
    return Details(
      houseNo: json['house_no'] as int,
      town: json['town'],
    );
  }
}

then the Address class

class Address {
  final String streetNo;
  final Details details;

  Address({this.streetNo, this.details});

  factory Address.fromJson(Map<String, dynamic> json) {
    return Address(
        streetNo: json['street_no'] as String,
        details: Details.fromJson(
          json['details'],
        ));
  }
}

Our Person Class will change like this

class Person {
  final String id;
  final String name;
  final int age;
  final List<String> places;
  final List<Images> images;
  final Address address;

  Person(
      {this.id, this.name, this.age, this.places, this.images, this.address});

  factory Person.fromJson(Map<String, dynamic> json) {
    return Person(
      id: json['id'],
      name: json['name'],
      age: json['age'],
      places: parsePlaces(json['places']), // json['places']);
      images: parseImages(json),
      address: Address.fromJson(
        json['address'],
      ),
    );
  }

  static List<String> parsePlaces(placesJson) {
    List<String> placesList = new List<String>.from(placesJson);
    return placesList;
  }

  static List<Images> parseImages(imagesJson) {
    var list = imagesJson['images'] as List;
    List<Images> imagesList =
        list.map((data) => Images.fromJson(data)).toList();
    return imagesList;
  }
}

JSON Parsing from a webservice

We are going to parse the json data coming from the below url now.
https://jsonplaceholder.typicode.com/photos

We will create a new class ‘Services’ to call this webservice and get the data first and then parse it.

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

class Services {
  static const String url = "https://jsonplaceholder.typicode.com/photos";

  static Future<List<Album>> getPhotos() async {
    try {
      final response = await http.get(url);
      if (response.statusCode == 200) {
        List<Album> list = parsePhotos(response.body);
        return list;
      } else {
        throw Exception("Error");
      }
    } catch (e) {
      throw Exception(e.toString());
    }
  }

  static List<Album> parsePhotos(String responseBody) {
    final parsed = json.decode(responseBody).cast<Map<String, dynamic>>();
    return parsed.map<Album>((json) => Album.fromJson(json)).toList();
  }
}

getPhotos will get the data and we will parse the json received with the help of ‘parsePhotos‘ method and return the List.

Usage

All the above can be used like this

 Future<String> loadPersonFromAssets() async {
    return await rootBundle.loadString('json/person.json');
  }

  Future loadPerson() async {
    String jsonString = await loadPersonFromAssets();
    final jsonResponse = json.decode(jsonString);
    Person person = new Person.fromJson(jsonResponse);
    print('Name: ${person.name}');
    print('Places: ${person.places}');
    print('Images: ${person.images[0].name}');
    print('Address: ${person.address.details.town}');

    print("Loading Photos...");
    Services.getPhotos().then((albums) {
      print('Albums: ${albums.length}');
      print('Album 0: ${albums[3].title}');
    });
  }

  @override
  void initState() {
    super.initState();
    loadPerson();
  }

 

Complete Source Code

Get the source code from here.

 

2 thoughts on “Complex JSON Parsing in Flutter / Dart

  1. Sagar V Hande

    Hello,

    Please help me to parse below JSON

    [
    {
    “places”: [
    {
    “place_name”: “Lal bagh”,
    “values”: {
    “id_place”: 1,
    “best_session”: “All-Time”,
    “near_by_place”: “Lal bagh, Cubbon Park”
    }
    },
    {
    “place_name”: “Cubbon Park”,
    “values”: {
    “id_place”: 2,
    “best_session”: “All-Time”,
    “near_by_place”: “Vidhana Souda”
    }
    },
    {
    “place_name”: “Vidhana Souda”
    },
    {
    “place_name”: “Nandhi Betta”
    },
    {
    “place_name”: “Bengaluru Palace”
    },
    {
    “place_name”: “Chinnaswamy Stadium”
    }
    ],
    “dist_name”: “Bengaluru”
    },
    {
    “places”: [
    {
    “place_name”: “Chitradurga”,
    “values”: {
    “id_place”: 5,
    “best_session”: “Winter and Summer”,
    “near_by_place”: “Davangere”
    }
    },
    {
    “place_name”: “Kunduvada Kere”,
    “values”: {
    “id_place”: 6,
    “best_session”: “Rainy”,
    “near_by_place”: “Baati Gudda”
    }
    }
    ],
    “dist_name”: “Davangere”
    },
    {
    “places”: [
    {
    “place_name”: “Mysore place”,
    “values”: {
    “id_place”: 3,
    “best_session”: “All-Time”,
    “near_by_place”: “Mysore Zoo”
    }
    },
    {
    “place_name”: “Mysore Zoo”,
    “values”: {
    “id_place”: 4,
    “best_session”: “All-Time”,
    “near_by_place”: “Mysore Place”
    }
    }
    ],
    “dist_name”: “Mysore”
    },
    {
    “places”: [],
    “dist_name”: “Shimoga”
    },
    {
    “places”: [],
    “dist_name”: “Manglore”
    },
    {
    “places”: [],
    “dist_name”: “Hubli”
    },
    {
    “places”: [
    {
    “place_name”: “Abbe Falls”
    },
    {
    “place_name”: “Tadiyandomal”
    }
    ],
    “dist_name”: “Madikeri”
    },
    {
    “places”: [
    {
    “place_name”: “Mullayengiri”
    },
    {
    “place_name”: “Baba Budangiri”
    }
    ],
    “dist_name”: “Chikamaglore”
    }
    ]

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *