6
votes

I have trouble getting data from a complex json, below is the json in the request.

{
   "results":{
      "TotalRecordCount":"1",
      "Records":[
         {
            "code":"PCK_34333338365C93E2D50DB9C",
            "address":"1 AV KHEIREDDINE PACHA Imm Pacha centre BLOC B tunis Tunis 1000",
            "contact_phone":"99608258"
         }
      ],
      "Result":"OK"
   }
}

Below is the model I made.

import 'dart:convert';

class Pickup {
  String status;
  List message;
  //Map<String ,dynamic> results;
  Results results;
  Pickup(
    {this.status,
     this.message,
     this.results,
  });
  factory Pickup.fromJson(Map<String, dynamic> json) {
    return Pickup(
             status: json["status"] as String,
             results: Results.fromJson(json["results"]),

           );
  }
}

class Results {
  String TotalRecordCount;
  records Records;

  Results({this.TotalRecordCount,this.Records});

  factory Results.fromJson(Map<String, dynamic> json) {
    return Results(
    TotalRecordCount: json["TotalRecordCount"],
    Records:records.fromJson(json["Records"]),

    );
  }
}

class records{
  String code;
  String address;
  String contact_phone;

  records({
    this.code,
    this.address,
    this.contact_phone
  });

  factory records.fromJson(Map<String, dynamic> json) {
    return records(
      code: json["code"],
      address: json["address"],
      contact_phone: json["contact_phone"],
    );
  }
}

Now Im trying to parse the records to get the code or address and print it.

if (response.statusCode == 200) {
  print(response.body);
  final responseJson = json.decode(response.body);
  var da=Pickup.fromJson(responseJson);
  Results dat=da.results;
  records data=dat.Records;
  print(data.address);
}

The response.body is working fine but when I try to parse results or records I got 'List' is not a subtype of type 'Map<String, dynamic>' error

4

4 Answers

17
votes

I will definitely recommend you this website json to dart App Quicktype just don't forget to select Dart in the right side.

You just put your json in la left and in will give you something like this:

// To parse this JSON data, do
//
//     final pickUp = pickUpFromJson(jsonString);

import 'dart:convert';

PickUp pickUpFromJson(String str) => PickUp.fromJson(json.decode(str));

String pickUpToJson(PickUp data) => json.encode(data.toJson());

class PickUp {
    Results results;

    PickUp({
        this.results,
    });

    factory PickUp.fromJson(Map<String, dynamic> json) => new PickUp(
        results: Results.fromJson(json["results"]),
    );

    Map<String, dynamic> toJson() => {
        "results": results.toJson(),
    };
}

class Results {
    String totalRecordCount;
    List<Record> records;
    String result;

    Results({
        this.totalRecordCount,
        this.records,
        this.result,
    });

    factory Results.fromJson(Map<String, dynamic> json) => new Results(
        totalRecordCount: json["TotalRecordCount"],
        records: new List<Record>.from(json["Records"].map((x) => Record.fromJson(x))),
        result: json["Result"],
    );

    Map<String, dynamic> toJson() => {
        "TotalRecordCount": totalRecordCount,
        "Records": new List<dynamic>.from(records.map((x) => x.toJson())),
        "Result": result,
    };
}

class Record {
    String code;
    String address;
    String contactPhone;

    Record({
        this.code,
        this.address,
        this.contactPhone,
    });

    factory Record.fromJson(Map<String, dynamic> json) => new Record(
        code: json["code"],
        address: json["address"],
        contactPhone: json["contact_phone"],
    );

    Map<String, dynamic> toJson() => {
        "code": code,
        "address": address,
        "contact_phone": contactPhone,
    };
}

at the beginning it will tell you how you can use it.

// To parse this JSON data, do
//
//     final pickUp = pickUpFromJson(jsonString);

So when you call it in you code its gonna be something like this.

  Future<Pickup> getPickup() async {
    var response = await http.get(url);
    return pickUpFromJson(response.body);
  }

This code could be call for a FutureBuilder for example or wherever you set the code to wait for a future.

2
votes

We will parse a complex JSON that contains some fields and an array of objects field. It looks like this:

{
  "title": "Dart Tutorial",
  "description": "Way to parse Json",
  "author": {
    "name": "bezkoder",
    "age": 30
  },
  "tags": [
    {
      "name": "dart",
      "quantity": 12
    },
    {
      "name": "flutter",
      "quantity": 25
    }
  ]
}

We modify the Tutorial class to make it have a new List<Tag> tags field.

class Tutorial {
  String title;
  String description;
  User author;
  List<Tag> tags;

  Tutorial(this.title, this.description, this.author, [this.tags]);

  factory Tutorial.fromJson(dynamic json) {
    if (json['tags'] != null) {
      var tagObjsJson = json['tags'] as List;
      List<Tag> _tags = tagObjsJson.map((tagJson) => Tag.fromJson(tagJson)).toList();

      return Tutorial(
        json['title'] as String,
        json['description'] as String,
        User.fromJson(json['author']),
        _tags
      );
    } else {
      return Tutorial(
        json['title'] as String,
        json['description'] as String,
        User.fromJson(json['author'])
      );
    }
  }

  @override
  String toString() {
    return '{ ${this.title}, ${this.description}, ${this.author}, ${this.tags} }';
  }
}

– In the constructor method, we use square brackets [this.tags] to specify that this tags array is an option field.

– Like the way we parse array of JSON objects into a Dart List, we use map() and toList() to get List<Tag>.

List<Tag> _tags = tagObjsJson.map((tagJson) => Tag.fromJson(tagJson)).toList();

The main() function now look like this.

import 'dart:convert';

main() {
  String complexText =
      '{"title": "Dart Tutorial", "description": "Way to parse Json", "author": {"name": "bezkoder", "age": 30}, "tags": [{"name": "dart", "quantity": 12}, {"name": "flutter", "quantity": 25}]}';

  Tutorial complexTutorial = Tutorial.fromJson(jsonDecode(complexText));

  print(complexTutorial);
}

You can see the result with title, description, author, tags array after running the code above.

{ Dart Tutorial, Way to parse Json, { bezkoder, 30 }, [{ dart, 12 }, { flutter, 25 }] }

Base on : parse complex JSON

0
votes
{
   "results":{
      "TotalRecordCount":"1",
      "Records":[
         {
            "code":"PCK_34333338365C93E2D50DB9C",
            "address":"1 AV KHEIREDDINE PACHA Imm Pacha centre BLOC B tunis Tunis 1000",
            "contact_phone":"99608258"
         }
      ],
      "Result":"OK"
   }
}

The above JSON file consists of a list of "Records" within it hence making it a complex JSON. Below are the amendments I would like to contribute to the code -

class Pickup {
  String status;
  List message;
  //Map<String ,dynamic> results;
  Results results;
  Pickup(
    {this.status,
     this.message,
     this.results,
  });
  factory Pickup.fromJson(Map<String, dynamic> json) {
    return Pickup(
             status: json["status"] as String,
             results: Results.fromJson(json["results"]),

           );
  }
}
class Results {
  String TotalRecordCount;
  records Records;

  Results({this.TotalRecordCount,this.Records});



    factory Results.fromJson(Map<String, dynamic> json) {
        //since records is a list hence it is parsed separately by creating a 
        //list out of it.  
    



       listOfRecords = (json["Records"] as List)
      .map((i) => records.fromJson(i))
      .toList();


 
    return Results(
    TotalRecordCount: json["TotalRecordCount"],
    Records:listOfRecords //now the list is used here directly
),

    );
  }
}

class records{
  String code;
  String address;
  String contact_phone;

  records({
    this.code,
    this.address,
    this.contact_phone
  });

  factory records.fromJson(Map<String, dynamic> json) {
    return records(
      code: json["code"],
      address: json["address"],
      contact_phone: json["contact_phone"],
    );
  }

At last, we can use this wherever it is required like this -

if (response.statusCode == 200) {
  print(response.body);
  final responseJson = json.decode(response.body);
  var da = Pickup.fromJson(responseJson);
  Results dat = da.results;
  records data = dat.Records;
  print(data[0].address);  //since records was a list
}