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.
Author by
Smart HO
Updated on December 25, 2022Comments
-
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 over 3 yearsyou should first parse your json to dart
-
Smart HO over 3 yearsI 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 over 3 yearsI 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 over 3 yearswhat I have given is an example, I have very big list of cities and their attractions. I need to do this programatically.
-
Dung Ngo over 3 years@ChessMax answer is what I had in mind, check if that help your case
-
-
Smart HO over 3 yearsThanks, but I get an error under cities "error: The type 'Type' used in the 'for' loop must implement Iterable."
-
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 over 3 yearsYes, 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 over 3 yearsTry to change it like that:
for (final city in Cities as List<Object>)
. -
Smart HO over 3 yearsNow I get an error under
['attractions']
: "error: The operator '[]' isn't defined for the type 'Object'." -
ChessMax over 3 yearsLooks like it should be:
for (final city in Cities as List<Map<String, Object>>)
-
Smart HO over 3 yearsNow 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 over 3 yearsStrange, 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 over 3 yearsI have included in now in my question, the JSON model class , please check
-
Smart HO over 3 yearsThanks, 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 over 3 yearsSo, 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 over 3 yearsI 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 over 3 yearsPerfect, it works fine now. Thanks ChessMax for your support, appreciated .