Trying to fetch json data in flutter - json

I am trying to fetch json data from this url- "https://jsonplaceholder.typicode.com/photos". And I am following this flutter cookbook tutorial - "https://flutter.dev/docs/cookbook/networking/background-parsing"
My model class looks like this-
class ModelData {
ModelData({
this.albumId,
this.id,
this.title,
this.url,
this.thumbnailUrl,
});
final int albumId;
final int id;
final String title;
final String url;
final String thumbnailUrl;
factory ModelData.fromJson(Map<String, dynamic> json) => ModelData(
albumId: json["albumId"] as int,
id: json["id"] as int,
title: json["title"] as String,
url: json["url"] as String,
thumbnailUrl: json["thumbnailUrl"] as String,
);
}
And my parseData method looks like this-
List<ModelData> parseData(String responseBody) {
final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>();
return parsed
.map<ModelData>((json) => ModelData().fromJson(json)).toList();
}
The problem is in the last line of this method. It says "error: The method 'fromJson' isn't defined for the type 'ModelData'. (undefined_method at [flutter_rest] lib\main.dart:61)". i don't see any typo problem here. What might going wrong here?

Factory methods act like a static method but you are initialising the class by using ModelData().
Try like this:
ModelData.fromJson(json)

Related

FLUTTER- How to save a List<Object> into shared Preferences?

I want to add a product to cart and save it, so that when i open the app again, it is present in the cart. i can add multiple products to cart, so I am looking to save a List<Products>
I want to save a List into sharedPreferences and retrieve the same, but there are no methods for that. I tried using setStringList but I am unable to convert the string into object. And the data is not getting saved also.
my class model-
import 'dart:convert';
class Products {
Products({
required this.title,
required this.price,
required this.description,
required this.image,
this.quantity = 0,
});
final String title;
final double price;
final String description;
final String image;
int quantity;
factory Products.fromRawJson(String str) =>
Products.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory Products.fromJson(Map<String, dynamic> json) => Products(
title: json["title"],
price: json["price"].toDouble(),
description: json["description"],
image: json["image"],
);
Map<String, dynamic> toJson() => {
"title": title,
"price": price,
"description": description,
"image": image,
};
}
The shared_preferences library has only the options to save the following.
int
string
List
double
boolean
Reference:
https://pub.dev/documentation/shared_preferences/latest/shared_preferences/SharedPreferences-class.html
But what you could do is to create a List<String> in their jsonEncode form and save it.
Convert the List to List by encoding each of them using https://api.flutter.dev/flutter/dart-convert/jsonEncode.html
Once done you can save it and while decoding it similarly use jsonDecode
Hope this helps.
Thanks!
import 'dart:convert';
//first converts your array to json string store it in session
String strJsonString = json.encode(arrayProducts);
//save strJsonString as String into your session
//when you want to retrive it from session just decode session value
List<Products> = json.decode(strJsonString);

How to loop a list of maps from json api dart/flutter

I have create a class model to receive json data from API
class Competition {
int id;
String name;
String code;
String type;
String emblem;
Competition({
required this.id,
required this.name,
required this.code,
required this.type,
required this.emblem,
});
factory Competition.fromJson(Map<String, dynamic> data) {
return Competition(
id: data["matches"][0]["competition"]['id'],
name: data["matches"][0]["competition"]['name'],
code: data["matches"][0]["competition"]['code'],
type: data["matches"][0]["competition"]['type'],
emblem: data["matches"][0]["competition"]['emblem'],
);
}
}
the code work properly, every time index [0] change the coming data change for the next competition details
i want to make this index change automatically for fetching all data at one time, this index represent list data["matches"].length
My Api service look like
class ServiceApi {
Future<Competition > getmatches() async {
http.Response response = await http.get(
Uri.parse('_url'),
headers: {'X-Auth-Token': '_key'});
String body = response.body;
Map<String, dynamic> data = jsonDecode(body);
Competition compitition = Competition.fromJson(data);
int numberOfCompetition = data["matches"].length;
return matches;
}
}
You can map it like this
List<Competition> compititionList = data['matches'].map((item) => Competition.fromJson(item));
print(compittionList[0].name);
Btw theres a typo(spelling mistake) in competition (just incase you want to fix it)
And thr model should be
class Competition {
int id;
String name;
String code;
String type;
String emblem;
Competition({
required this.id,
required this.name,
required this.code,
required this.type,
required this.emblem,
});
factory Competition.fromJson(Map<String, dynamic> data) {
return Competition(
id: data["competition"]['id'],
name: data["competition"]['name'],
code: data["competition"]['code'],
type: data["competition"]['type'],
emblem: data["competition"]['emblem'],
);
}
}

Null-safety for fromJson like methods

I want to define a simple class model UserResponse in Flutter 2.0.5 and build a fromJson method attached to this class to create an instance easily after receiving the data from the backend in json format.
class UserResponse {
String name;
UserResponse ({
required this.name,
});
UserResponse.fromJson(Map<String, dynamic> json) {
name= json['name'].toString();
}
}
The dart compiler however throws an error here:
dart(not_initialized_non_nullable_instance_field)
Furthermore:
Non-nullable instance field 'name' must be initialized.
Try adding an initializer expression, or add a field initializer in this constructor, or mark it 'late'.
If I know that I will only call the fromJson method if I have all the required data, how should I create the new Instance in this method? I don't want to change the name field in the class to late.
Use a factory constructor.
class UserResponse {
final String name;
UserResponse({
required this.name,
});
factory UserResponse.fromJson(Map<String, dynamic> json) {
return UserResponse(name: json['name'].toString());
}
}
For null-safety. You need to be check null right way. And front-end need handle server don't return this key, we need mock data and sure app can't crash.
class UserResponse {
UserResponse({
this.name,
});
final String? name;
factory UserResponse.fromRawJson(String str) =>
UserResponse.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory UserResponse.fromJson(Map<String, dynamic> json) => UserResponse(
name: json["name"] == null ? null : json["name"].toString(),
);
Map<String, dynamic> toJson() => {
"name": name == null ? null : name,
};
}
According to this very similar question there are mainly to ways:
Use an initializer list for the method
Use a factory method
Thus,
UserResponse.fromJson(Map<String, dynamic> json) :
name= json['name'] as String;
or
factory UserResponse.fromJson(Map<String, dynamic> json) {
return UserResponse(
name: json['name'] as String,
);
}

How to decode nested JSON List of Objects in Dart/Flutter

I'm trying to figure out how I can decode the following JSON in Flutter.
https://covid.ourworldindata.org/data/owid-covid-data.json
I tried the following structure, but it doesn't work.
#JsonSerializable()
class StatisticsResponse {
Map<String, Country> data;
//List<Country> data;
StatisticsResponse({this.data});
factory StatisticsResponse.fromJson(Map<String, dynamic> json) =>
_$StatisticsResponseFromJson(json);
}
#JsonSerializable()
class Country {
String continent;
String location;
int population;
//Map<String, Data> data;
List<Data> data;
Country({this.continent, this.location, this.population, this.data
});
factory Country.fromJson(Map<String, dynamic> json) =>
_$CountryFromJson(json);
}
Use Map to convert dynamic to String. Directly assigning List to List will throw an error. You have create getters yourself.
Consider this example:
(jsonDecode(response.body)["data"] as List).map((e) => e as Map<String, dynamic>)?.toList();
Now assign to an instance of the custom class you have made.

Parse json array without names in Dart

I cannot parse such json
[{"operation_id":"38911","external_id":null,"status":"SUCCESS","date":"2019-12-01T12:30:08.000Z","amount":200}]
The problem lies in array with dynamic names. Here's my POJO:
class PaymentHistoryResponse {
final List<History> list;
PaymentHistoryResponse({this.list});
}
class History {
final String operationId;
final dynamic externalId;
final String status;
final DateTime date;
final int amount;
History({
#required this.operationId,
#required this.externalId,
#required this.status,
#required this.date,
#required this.amount
});
factory History.fromJson(String str) => History.fromMap(json.decode(str));
String toJson() => json.encode(toMap());
factory History.fromMap(Map<String, dynamic> json) => History(
operationId: json["operation_id"],
externalId: json["external_id"],
status: json["status"],
date: DateTime.parse(json["date"]),
amount: json["amount"]
);
Map<String, dynamic> toMap() => {
"operation_id": operationId,
"external_id": externalId,
"status": status,
"date": date.toIso8601String(),
"amount": amount
};
}
I also receive other json containing arrays, but named ones and I was able to decode them. How can I convert this one? P.s I've also made some research through this site and found some quite similar questions but a bit different and it didn't help me.
Since this is an array and not just a JSON you will need to do something like this:
mList = List<UserModel>.from(response.data.map((i) => UserModel.fromJson(i)));
Hint: for generating models with toJson and fromJson use this website:
https://javiercbk.github.io/json_to_dart/