Flutter null safety with fromJson - flutter

Recently migrating to Flutter null safety feature, I have a lot of Classes that I need to update.
For my models, I use fromJson to deserialize the data from a json object. This forces me to put the late keyword for each field that is non optional.
Is that the right approach?
class ServerSession {
late String sessionId;
late String refreshToken;
late String accessToken;
ServerSession({required this.sessionId, required this.refreshToken, required this.accessToken});
ServerSession.fromJson(Map<String, dynamic> json) {
sessionId = json['session_id'] ?? json['sessionId'];
refreshToken = json['refresh_token'] ?? json['refreshToken'];
accessToken = json['access_token'] ?? json['accessToken'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['sessionId'] = this.sessionId;
data['refreshToken'] = this.refreshToken;
data['accessToken'] = this.accessToken;
return data;
}
}

No, it is not. You should be using the initializer list for initializing fields of your class. You can read more about the initializer list in the language tour.
class ServerSession {
String sessionId;
String refreshToken;
String accessToken;
ServerSession({required this.sessionId, required this.refreshToken, required this.accessToken});
ServerSession.fromJson(Map<String, dynamic> json) :
sessionId = json['session_id'] ?? json['sessionId'],
refreshToken = json['refresh_token'] ?? json['refreshToken'],
accessToken = json['access_token'] ?? json['accessToken'];
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['sessionId'] = this.sessionId;
data['refreshToken'] = this.refreshToken;
data['accessToken'] = this.accessToken;
return data;
}
}
I personally would use the "normal" constructor for the object and make fromJson a factory constructor, though either method works.
class ServerSession {
String sessionId;
String refreshToken;
String accessToken;
ServerSession({required this.sessionId, required this.refreshToken, required this.accessToken});
factory ServerSession.fromJson(Map<String, dynamic> json) {
return ServerSession(
sessionId: json['session_id'] ?? json['sessionId'],
refreshToken: json['refresh_token'] ?? json['refreshToken'],
accessToken: json['access_token'] ?? json['accessToken']
);
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['sessionId'] = this.sessionId;
data['refreshToken'] = this.refreshToken;
data['accessToken'] = this.accessToken;
return data;
}
}

Related

Save nested objects in shared preferences

I have an object that contains a json array , which am trying to store in shared preferences but i don't know how to do so .
This is my model :
import 'dart:convert';
import 'package:deepnrise/models/settings/perimeter.dart';
import 'package:deepnrise/models/user/user_perims.dart';
UserWithPerim user(String str) => UserWithPerim.fromJson(json.decode(str));
class UserWithPerim {
// ignore: non_constant_identifier_names
UserWithPerim({
required this.identifier,
required this.firstName,
required this.lastName,
required this.email,
required this.role,
required this.perimeters,
});
String identifier;
String firstName;
String lastName;
String email;
String role;
List<UserPerimeter> perimeters;
factory UserWithPerim.fromJson(Map<String, dynamic> json) {
return UserWithPerim(
identifier: json['identifier'] ?? "",
firstName: json['firstName'] ?? "",
lastName: json['lastName'] ?? "",
email: json['email'] ?? "",
role: json['role'] ?? "",
perimeters: (json['perimeters'] as List)
.map((p) => UserPerimeter.fromJson(p))
.toList(),
);
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['identifier'] = identifier;
data['firstName'] = firstName;
data['lastName'] = lastName;
data['role'] = role;
data['email'] = email;
data['perimeters'] = perimeters;
return data;
}
}
This the perimeters model :
import 'dart:convert';
Userperimeters(String str) => UserPerimeter.fromJson(json.decode(str));
String UserPerimToJson(UserPerimeter data) => json.encode(data.tojson());
class UserPerimeter {
// ignore: non_constant_identifier_names
UserPerimeter(
{required this.id, required this.label, required this.perimeterId});
// ignore: non_constant_identifier_names
int id;
String label;
int perimeterId;
factory UserPerimeter.fromJson(Map<String, dynamic> json) {
return UserPerimeter(
id: json['id'] ?? "",
label: json['label'] ?? "",
perimeterId: json["perimeterId"] ?? "");
}
Map<String, dynamic> tojson() => {
"id": id,
"label": label,
"perimeterId": perimeterId,
};
}
For now I've two models of my user object , one that contains the perils list and one that doesn't because whenever I try to store my user in shared prefs I get this exception thrown :
Unhandled Exception: type 'UserPerimeter' is not a subtype of type 'Map<String, dynamic>'
This is how am saving and reading my user:
saveUser(value) async {
final prefs = await SharedPreferences.getInstance();
String user = jsonEncode(User.fromJson(value));
prefs.setString(Preferences.USER_KEY, user);
}
Future<User?> getUser() async {
final prefs = await SharedPreferences.getInstance();
if (prefs.containsKey(Preferences.USER_KEY)) {
Map<String, dynamic> userMap =
jsonDecode(prefs.getString(Preferences.USER_KEY) ?? "");
User user = User.fromJson(userMap);
return user;
}
}
Is there a way with which I can store the whole user model with the perils object list without making two models of the user object ? thank you so much in advance.
The work around here to convert your whole json response to string.
save that string into sharedprefs, then you can call it back and decode it using:
var response = json.decode(prefs.getString("response");
So, the full idea:
prefs.setString("response",json.encode(response.body));
using that String as json format again:
MyModel model = MyModel.fromJson(json.decode(prefs.getString("response")));
I hope you find what you need from this idea.
Convert the list of perimeters to list of Json like this:
if (this.perimeters != null) {
data['perimeters'] = this.perimeters!.map((v) => v.toJson()).toList();
}

I get an error when I do tojson in flutter

I tried tojson in flutter, but I get the following error:
[VERBOSE-2:ui_dart_state.cc(199)] Unhandled Exception: type 'List<Tag>' is not a subtype of type 'String' in type cast
this is my code
import 'package:flutter_traveling/model/Tag.dart';
class Diary {
String? title;
String? location;
String? address;
List<Tag>? tagList;
List<Pages>? pages;
String? date;
Diary({
this.title,
this.location,
this.tagList,
this.pages,
this.date,
this.address,
});
Diary.fromJson(Map<String, dynamic> json) {
title = json['title'] ?? "";
location = json['location'] ?? "";
address = json["address"] ?? "";
tagList = json['tag_list'] ?? <Tag>[];
pages = json['pages'] ?? <Pages>[];
date = json['date'] == null ? '' : json['date'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['title'] = this.title;
data['location'] = this.location;
data['tag_list'] = this.tagList;
data['pages'] = this.pages;
data['date'] = this.date;
data['address'] = this.address;
return data;
}
}
class Pages {
int? order;
String? description;
List<String>? images;
Pages({
this.order,
this.description,
this.images,
});
Pages.fromJson(Map<String, dynamic> json) {
order = json['order'] ?? 0;
description = json['description'] ?? "";
images = json['images'] == null ? [] : json["images"].cast<String>();
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['order'] = this.order;
data['description'] = this.description;
data['images'] = this.images;
return data;
}
}
class Tag {
int? id;
String? tagName;
Tag({this.id, this.tagName});
Tag.fromJson(Map<String, dynamic> json) {
id = json['id'];
tagName = json['tag_name'] ?? "";
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['tag_name'] = this.tagName;
return data;
}
}
I don't know what causes this error to occur. please help
My guess is that when I run tojson, there seems to be a problem with the type, but I don't know which part and how to fix it, I'm just starting out with flutter, any advice would be appreciated.
i got err when change code like this.
data['tag_list'] = this.tagList.toString();
data['pages'] = this.pages.toString();
error is
Unhandled Exception: type 'String' is not a subtype of type 'List<Tag>?'
Try to replace
tagList = json['tag_list'] ?? <Tag>[];
with
tagList = List<Tag>.from(json["tag_list"].map((x) => Tag.fromJson(x)))
And this line
data['tag_list'] = this.tagList;
with
data['tag_list'] = this.tagList.map((tag) => tag.toJson()),
you should call the toJson() methods from your tags as well:
data['tag_list'] = this.tagList.map((tag) => tag.toJson()),

Problem with mapping list of images inside the products list using woocommerce api in flutter

class ProductModel {
late String name;
late int id;
late String status;
late String price;
late List<Images> images;
ProductModel(
this.name,
this.id,
this.status,
this.images,
this.price,
);
ProductModel.fromJson(Map<String, dynamic> json) {
name = json['name'];
id = json['id'];
status = json['status'];
//images = json['images'];
images = json['image'];
if (json['images'] != null) {
images = new List<Images>(); // error on List<Images>() "The default 'List' constructor //isn't available when null safety is enabled.
json['images'].forEach((v) {
images.add(new Images.fromJson(v));
});
}
price = json['price'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['name'] = this.name;
data['id'] = this.id;
data['status'] = this.status;
if (this.images != null) {
data['images'] = this.images.map((v) => v.toJson()).toList();
}
data['price'] = this.price;
return data;
}
}
// ignore: camel_case_types
class Images {
late int id;
late String src;
late String title;
Images({
this.id = 0,
this.src = "",
this.title = "",
});
Images.fromJson(Map<String, dynamic> json) {
id = json['id'];
src = json['src'];
title = json['title'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['src'] = this.src;
data['title'] = this.title;
return data;
}
}
I want to list the products of my Woocommerce site in the Flutter app, But getting an error mentioned in the code, please help. Please guide me the best way to model the JSON into Dart class. Tried converting online using https://javiercbk.github.io/json_to_dart/ but this gives lots of errors
Well it seems you are initializing the List incorrectly.
It should be:
images = <Images>[];
Also, you do not need to initialize with the new keyword anymore.

HTTP GET request result into array

so i have this http req payload, and i want to push it into an array, can someone help me?
The payload
{
"status":200,
"length":3,
"results":[
{
"_id":"60cd70b3fb9fe400117e8c6b",
"title":"Welcome to xxx",
"body":"Welcome to xx! We’re excited that everyone’s here and hope your ready for an epic weekend."
},
{
"_id":"60cd70b3fb9fe400117e8c6c",
"title":"Lunch Info",
"body":"Lunch is from our generous sponsors Lorem Ipsum! It will be served in the left atrium under the palm trees."
},
{
"_id":"60cd70b3fb9fe400117e8c6d",
"title":"Leash Dogs",
"body":"A friendly reminder that dogs must be leashed at all times, no matter how cute <3"
}
]
}
My Provider Code [UPDATED]
//So I've tried to debug on my own, and number 1 and number 2 is printed, while number 3 is not. I suspect its because of the way I handle extractedData.
class Announcements {
int? status;
int? length;
List<Results>? results;
Announcements(
{required this.status, required this.length, required this.results});
Announcements.fromJson(Map<String, dynamic> json) {
status = json['status'];
length = json['length'];
if (json['results'] != null) {
results = [];
json['results'].forEach((v) {
results!.add(new Results.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['status'] = this.status;
data['length'] = this.length;
if (this.results != null) {
data['results'] = this.results!.map((v) => v.toJson()).toList();
}
return data;
}
}
// so i've used your online converter json
class Results {
String? sId;
String? title;
String? body;
Results({required this.sId, required this.title, required this.body});
Results.fromJson(Map<String, dynamic> json) {
sId = json['_id'];
title = json['title'];
body = json['body'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['_id'] = this.sId;
data['title'] = this.title;
data['body'] = this.body;
return data;
}
}
class AnnouncementProvider with ChangeNotifier {
AnnouncementProvider(String? token, items);
List _items = [];
List get items {
return [..._items];
}
// List<Announcements> parseAnnouncement(String responseBody) {
// }
Future<List<Announcements>> fetchAnnouncements(String authToken) async {
//var url = Uri.https('api-staging.xxx.us.org', '/1.0/announcements');
final response = await http.get(
Uri.parse('https://api-staging.xxx.us.org/1.0/announcements'),
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer $authToken',
},
);
print(response.body);
final t = Announcements.fromJson(response.body as Map<String, dynamic>);
print(t.results);
return t.results;
}
}
What I need to know is, how do I return the list correctly, since the print(t.results) is actually not printed for some reason, so now it only shows "An error has occured" in my interface.
Thanks for helping!
Consider making a Dart Model object for the same, I would highly recommend you to do so because this is guaranteed serialization and type safe
For your case I used an imaginary name FoodItems for the type of data you received from your api endpoint
class FoodItems {
int status;
int length;
List<Results> results;
FoodItems({this.status, this.length, this.results});
FoodItems.fromJson(Map<String, dynamic> json) {
status = json['status'];
length = json['length'];
if (json['results'] != null) {
results = new List<Results>();
json['results'].forEach((v) {
results.add(new Results.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['status'] = this.status;
data['length'] = this.length;
if (this.results != null) {
data['results'] = this.results.map((v) => v.toJson()).toList();
}
return data;
}
}
class Results {
String sId;
String title;
String body;
Results({this.sId, this.title, this.body});
Results.fromJson(Map<String, dynamic> json) {
sId = json['_id'];
title = json['title'];
body = json['body'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['_id'] = this.sId;
data['title'] = this.title;
data['body'] = this.body;
return data;
}
}
Now you can easily cast your response.body to the FoodItems class using fromJson method and then get the desired list of Results and then iterate over it
In my honest opinion, it makes it much simpler this way
Note: I would highly recommend reading the following
This is a nice article from the Flutter Developers themselves
Android Studio Plugin to do the serialization for you
Online converter

I want to retrive each entity from following data in flutter

I want to sort each entity from following data in flutter
i.e enrollment_no,nationality,mother this data is coming from api
"personal":
"{\"enrollment_no\":\"1701\",
\"nationality\":\"INDIAN\",
\"driver_mobile\":\"-\",
\"mother\":\"JAGRUTIBAHEN SHRIKANT SONI\",
\"email\":\"SHRIKANT206#YAHOO.CO.IN\",
\"student_photo\":\"/container/school_data/BRS/photo/Student/1701.jpg\",
\"name\":\"NEYSA SHRIKANT SONI\",
\"mother_mobile\":\"+971507603564\",
\"father_mobile\":\"+971503171294\",
\"father\":\"SHRIKANT INDUKANT SONI\"}",
//I trying following code to sort data but can't achieve
if(personal == data['personal']) {
for (int i = 0; i < data['personal'].length; i++)
{
arrayp = personal;
print(arrayp);
var array1=arrayp[0]['father'];
print(array1);
}
}
1. Your JSON from API
{
"personal":
{
"enrollment_no": "1701",
"nationality": "INDIAN",
"driver_mobile": "-",
"mother": "JAGRUTIBAHEN SHRIKANT SONI",
"email": "SHRIKANT206#YAHOO.CO.IN",
"student_photo": "/container/school_data/BRS/photo/Student/1701.jpg",
"name": "NEYSA SHRIKANT SONI",
"mother_mobile": "+971507603564",
"father_mobile": "+971503171294",
"father": "SHRIKANT INDUKANT SONI"
}
}
2. Go To https://javiercbk.github.io/json_to_dart/
Convert your Json to Dart Classes.
class Personal {
PersonalData personal;
Personal({this.personal});
factory Personal.fromJson(Map<String, dynamic> json) {
return Personal(
personal: json['personal'] != null ?
PersonalData.fromJson(json['personal']) : null,
);
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.personal != null) {
data['personal'] = this.personal.toJson();
}
return data;
}
}
class PersonalData {
String driver_mobile;
String email;
String enrollment_no;
String father;
String father_mobile;
String mother;
String mother_mobile;
String name;
String nationality;
String student_photo;
PersonalData({this.driver_mobile, this.email, this.enrollment_no, this.father, this.father_mobile, this.mother, this.mother_mobile, this.name, this.nationality, this.student_photo});
factory PersonalData.fromJson(Map<String, dynamic> json) {
return PersonalData(
driver_mobile: json['driver_mobile'],
email: json['email'],
enrollment_no: json['enrollment_no'],
father: json['father'],
father_mobile: json['father_mobile'],
mother: json['mother'],
mother_mobile: json['mother_mobile'],
name: json['name'],
nationality: json['nationality'],
student_photo: json['student_photo'],
);
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['driver_mobile'] = this.driver_mobile;
data['email'] = this.email;
data['enrollment_no'] = this.enrollment_no;
data['father'] = this.father;
data['father_mobile'] = this.father_mobile;
data['mother'] = this.mother;
data['mother_mobile'] = this.mother_mobile;
data['name'] = this.name;
data['nationality'] = this.nationality;
data['student_photo'] = this.student_photo;
return data;
}
}
3. Now time for you api response
_getResponseFromApi() asyn{
var response = await http.post({your parameters})
var data = Personal.fromJson(json.decode(response.body));
var listOfPersonData = data.personal
}