Flutter: Join specific field of JSON file together to become a list itself

536

Something like that should work:

import 'dart:convert';

var data = """  [{
    "city": "London",
    "attractions": [
      {
        "name": "Attraction1",
        "localrank": 10,
        "intrank": 4
      },
      {
        "name": "Attraction2",
        "localrank": 4,
        "intrank": 5
      }
    ]
  },
  {
    "city": "Hong Kong",
    "attractions": [
      {
        "name": "Attraction3",
        "localrank": 10,
        "intrank": 4
      },
      {
        "name": "Attraction4",
        "localrank": 4,
        "intrank": 5
      }
    ]
  },
  {
    "city": "Cario",
    "attractions": [
      {
        "name": "Attraction5",
        "localrank": 10,
        "intrank": 4
      },
      {
        "name": "Attraction6",
        "localrank": 4,
        "intrank": 5
      }
    ]
  }
] """;

List<Cities> citiesFromJson(String str) =>
    List<Cities>.from(json.decode(str).map((x) => Cities.fromJson(x)));
String citiesToJson(List<Cities> data) =>
    json.encode(List<dynamic>.from(data.map((x) => x.toJson())));

class Cities {
  Cities({
    this.city,
    this.attractions,
  });

  String city;
  List<Attraction> attractions;

  factory Cities.fromRawJson(String str) => Cities.fromJson(json.decode(str));

  String toRawJson() => json.encode(toJson());

  factory Cities.fromJson(Map<String, dynamic> json) => Cities(
    city: json["city"],
    attractions: List<Attraction>.from(
        json["attractions"].map((x) => Attraction.fromJson(x))),
  );

  Map<String, dynamic> toJson() => {
    "city": city,
    "attractions": List<dynamic>.from(attractions.map((x) => x.toJson())),
  };
}

class Attraction {
  Attraction({
    this.name,
    this.localrank,
    this.intrank,
  });

  String name;
  int localrank;
  int intrank;

  factory Attraction.fromRawJson(String str) =>
      Attraction.fromJson(json.decode(str));

  String toRawJson() => json.encode(toJson());

  factory Attraction.fromJson(Map<String, dynamic> json) => Attraction(
    name: json["name"],
    localrank: json["localrank"],
    intrank: json["intrank"],
  );

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

class Globals {
  static List<Cities> citylist = [];
}

Future<String> fetchData() async {
  // String data =
  // await DefaultAssetBundle.of(context).loadString("assets/data.json");
  final jsonResult = json.decode(data);
  print('$jsonResult oop');
  // this.setState(() {
    jsonResult.forEach(
            (element) => Globals.citylist.add(new Cities.fromJson(element)));
  // });

  var result = getAttractionsByCity('London');

  print(result.join('\n'));

  return "Success!";
}

List<String> getAttractionsByCity(String value) {
  var result = <String>[];

  for (final city in Globals.citylist) {
    if (city.city == value) {
      final attractions = city.attractions;

      for (final attraction in attractions) {
        result.add(attraction.name);
      }
    }
  }

  return result;
}

void main() async {
  await fetchData();
}

It's a working example. You can copy and paste this code to HTTP://dartpad.dev and run it to see the result.

Share:
536
Smart HO
Author by

Smart HO

Updated on December 25, 2022

Comments

  • Smart HO
    Smart HO over 1 year

    I have a json file with a list of different types of data.

    I wanted to join the "name" field of all attractions of each city together as a list. The expected result after joining, for example for Longo city will be like this:

    Attraction1

    Attraction2

    The data in JSON file is structured like this:

      {
        "city": "London",
        "attractions": [
          {
            "name": "Attraction1",
            "localrank": 10,
            "intrank": 4
          },
          {
            "name": "Attraction2",
            "localrank": 4,
            "intrank": 5
          }
        ]
      },
      {
        "city": "Hong Kong",
        "attractions": [
          {
            "name": "Attraction3",
            "localrank": 10,
            "intrank": 4
          },
          {
            "name": "Attraction4",
            "localrank": 4,
            "intrank": 5
          }
        ]
      },
      {
        "city": "Cario",
        "attractions": [
          {
            "name": "Attraction5",
            "localrank": 10,
            "intrank": 4
          },
          {
            "name": "Attraction6",
            "localrank": 4,
            "intrank": 5
          }
        ]
      }
    ] 
    

    I used the following code, but I get an error :

    cities.attractions.name.join("\n")
    

    Json model class is this:

    List<Cities> citiesFromJson(String str) =>
        List<Cities>.from(json.decode(str).map((x) => Cities.fromJson(x)));
    String citiesToJson(List<Cities> data) =>
        json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
    
    class Cities {
      Cities({
        this.city,
        this.attractions,
      });
    
      String city;
      List<Attraction> attractions;
    
      factory Cities.fromRawJson(String str) => Cities.fromJson(json.decode(str));
    
      String toRawJson() => json.encode(toJson());
    
      factory Cities.fromJson(Map<String, dynamic> json) => Cities(
            city: json["city"],
            attractions: List<Attraction>.from(
                json["attractions"].map((x) => Attraction.fromJson(x))),
          );
    
      Map<String, dynamic> toJson() => {
            "city": city,
            "attractions": List<dynamic>.from(attractions.map((x) => x.toJson())),
          };
    }
    
    class Attraction {
      Attraction({
        this.name,
        this.localrank,
        this.intrank,
      });
    
      String name;
      int localrank;
      int intrank;
    
      factory Attraction.fromRawJson(String str) =>
          Attraction.fromJson(json.decode(str));
    
      String toRawJson() => json.encode(toJson());
    
      factory Attraction.fromJson(Map<String, dynamic> json) => Attraction(
            name: json["name"],
            localrank: json["localrank"],
            intrank: json["intrank"],
          );
    
      Map<String, dynamic> toJson() => {
            "name": name,
            "localrank": localrank,
            "intrank": intrank,
          };
    }
    

    And this also calling json file:

      Future<String> fetchData() async {
        String data =
            await DefaultAssetBundle.of(context).loadString("assets/data.json");
        final jsonResult = json.decode(data);
        print('$jsonResult oop');
        this.setState(() {
          jsonResult.forEach(
              (element) => Globals.citylist.add(new Cities.fromJson(element)));
        });
        return "Success!";
      }
    
    
    • Dung Ngo
      Dung Ngo over 3 years
      you should first parse your json to dart
    • Smart HO
      Smart HO over 3 years
      I have already done parse in dart, but the code is too long to include here. I am able to use all these fields in a listview builder. What I need now is a way to join the text fields of each city attraction
    • Dung Ngo
      Dung Ngo over 3 years
      I suggest just adding the names to a List<String>. For ex: ["Attraction 1", "Attraction 2"]. Then when you want to show it, add "\n" later in between each String
    • Smart HO
      Smart HO over 3 years
      what I have given is an example, I have very big list of cities and their attractions. I need to do this programatically.
    • Dung Ngo
      Dung Ngo over 3 years
      @ChessMax answer is what I had in mind, check if that help your case
  • Smart HO
    Smart HO over 3 years
    Thanks, but I get an error under cities "error: The type 'Type' used in the 'for' loop must implement Iterable."
  • ChessMax
    ChessMax over 3 years
    cities is the name of a variable that holds your JSON data. If your variable has another name, just change it.
  • Smart HO
    Smart HO over 3 years
    Yes, Just change it it is Cities with capital C, but now I get this error "error: The type 'Type' used in the 'for' loop must implement Iterable. "
  • ChessMax
    ChessMax over 3 years
    Try to change it like that: for (final city in Cities as List<Object>).
  • Smart HO
    Smart HO over 3 years
    Now I get an error under ['attractions'] : "error: The operator '[]' isn't defined for the type 'Object'."
  • ChessMax
    ChessMax over 3 years
    Looks like it should be: for (final city in Cities as List<Map<String, Object>>)
  • Smart HO
    Smart HO over 3 years
    Now no error in the code, but when I run the app in the simulator, red screen appears with this error "type '_Type' is not a subtype of type 'List<Map<String, Object>>' in type cast"
  • ChessMax
    ChessMax over 3 years
    Strange, maybe your Cities don't contain a parsed JSON data? Or it has a different format. I can't say what exactly wrong with this uninformative error. Try to print(Cities) and see what is in it.
  • Smart HO
    Smart HO over 3 years
    I have included in now in my question, the JSON model class , please check
  • Smart HO
    Smart HO over 3 years
    Thanks, but your example join the attractions for all cities. I wanted the attractions of each city to be joined. I am actually having two listview builders, one to show list of cities, and then if pressed, another page will show the second listview builder of the attractions of that city. where I need to have a share icon on the appbar to share all the attractions of that city at once. that is why i need to join them first so that they can be shared added to the share button.
  • ChessMax
    ChessMax over 3 years
    So, you need a list of cities with joined attractions? Like that: London - Attraction1 Attraction2, Hong Kong - Attraction 3, Attraction 4 ... ? Or you need to get joined attractions by city name?
  • Smart HO
    Smart HO over 3 years
    I need only a list of attractions for that specific city that shows in the second page, for example in the first page, I pressed on London, then second page will show the attractions of London as cards. Now I need to place an icon on the appbar of that page, where I can allow sharing of all the attractions of London at once, one below the other.
  • Smart HO
    Smart HO over 3 years
    Perfect, it works fine now. Thanks ChessMax for your support, appreciated .