Search code examples
androidjsonfluttermobiledata-modeling

Flutter model for nested json


I'm creating a flutter app for data visualization. There will be 3 pages:

  • Filter page for filter criteria,
  • List page for visualizing serach result,
  • Details page.

I will receive a json like this:

data.json

[
    {
        "name": "Jhon",
        "surname": "Walker",
        "details": "{\"work\":{\"salary\":\"116\",\"company\":\"evolution\",\"image\":\"http://image.jpg\"},\"address\":{\"street\":\"grand station\",\"city\":\"salt lake\"}}"    
    },
    {
        "name": "Alan",
        "surname": "Turing",
        "details": "{\"work\":{\"salary\":\"116\",\"company\":\"evolution\",\"image\":\"http://image.jpg\"},\"address\":{\"street\":\"grand station\",\"city\":\"salt lake\"}}"    
    }
]

It could be a really long list.

I have already posted a question here about my code for this app which is not working, here is the discussion

Flutter app error

So now I' m asking a different question. Which is the best model for this json structure? I need to have direct access to all the fields in the details object. I would like to have the ability to directly get the field salary or company. I need to have access to the image field which will contain a url for an image to display in the app. In the linked post I have generated a model using serialization and built_value. It is not working in the code, I still get the error:

type String is not a subtype of type 'Map<String, dynamic>' in type cast

And no one solutions that I find online seems to work.

I have created another model without nested objects, this is how I made it: model.dart

class User {

  String name;

  String surname;

  String details;


  User({
    this.name,
    this.surname,
    this.details,
  });


  factory User.fromJson(Map<String, dynamic> json) => User(
    name: json["name"],
    surname: json["surname"],
    details: json["details"],
  );

  Map<String, dynamic> toJson() => {
    "name": name,
    "surname": surname,
    "details": details,
  };
}

With this model I' m able to display the data on a ListView but the details field is one only big string and I have no idea about how to access the fields in the details object. I can only think to regualr expression but it sounds kind of tricky, and why I should use regualr expression when I have JSON?

Which model is the best for this json? Should I change path? Do you have any advice for a better data model, or maybe a solution for using the data model correctly from the discussion that I linked? I' m not asking the same question, I' m just trying to find the right solution for accessing deatils fields using standard json.

Thank you!


Solution

  • Here is the solution with the model I'm currently using:

    model.dart

    import 'dart:convert';
    
    List<User> userFromJson(String str) =>
        List<User>.from(json.decode(str).map((x) => User.fromJson(x)));
    
    String userToJson(List<User> data) =>
        json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
    
    class User {
      User({
        this.name,
        this.surname,
        this.areaName,
        this.details,
      });
    
      String name;
      String surname;
      String areaName;
      String details;
    
      factory User.fromJson(Map<String, dynamic> json) => User(
            name: json["name"],
            surname: json["surname"],
            areaName: json["areaName"],
            details: json["details"],
          );
    
      Map<String, dynamic> toJson() => {
            "name": name,
            "surname": surname,
            "areaName": areaName,
            "details": details,
          };
    }
    
    Details DetailsFromJson(String str) => Details.fromJson(json.decode(str));
    
    String DetailsToJson(Details data) => json.encode(data.toJson());
    
    class Details {
      Details({
        this.work,
        this.address,
      });
    
      Work work;
      Address address;
    
      factory Details.fromJson(Map<String, dynamic> json) => Details(
            work: Work.fromJson(json["work"]),
            address: Address.fromJson(json["address"]),
          );
    
      Map<String, dynamic> toJson() => {
            "work": work.toJson(),
            "address": address.toJson(),
          };
    }
    
    class Address {
      Address({
        this.street,
        this.city,
      });
    
      String street;
      String city;
    
      factory Address.fromJson(Map<String, dynamic> json) => Address(
            street: json["street"],
            city: json["city"],
          );
    
      Map<String, dynamic> toJson() => {
            "street": street,
            "city": city,
          };
    }
    
    class Work {
      Work({
        this.salary,
        this.company,
      });
    
      String salary;
      String company;
    
      factory Work.fromJson(Map<String, dynamic> json) => Work(
            salary: json["salary"],
            company: json["company"],
          );
    
      Map<String, dynamic> toJson() => {
            "salary": salary,
            "company": company,
          };
    }
    

    Thank you for the help!