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();
}
Related
I have a user model that am saving in shared preferences when I try to read the data (or even save it ) I get this exception
Unhandled Exception: type 'UserPerimeter' is not a subtype of type 'Map<String, dynamic>'
This is my user model :
import 'dart:convert';
import 'package:deepnrise/models/settings/perimeter.dart';
import 'package:deepnrise/models/user/user_perims.dart';
User user(String str) => User.fromJson(json.decode(str));
class User {
// ignore: non_constant_identifier_names
User({
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 User.fromJson(Map<String, dynamic> json) {
return User(
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;
}
}
UserPerim 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,
};
}
When I use the online data it works but in shared prefs doesn't , do anyone know what seems to be the problem , if you can help I'd be grateful .
You need to convert perimeter to a json in the following line:
data['perimeters'] = perimeters;
Make it:
data['perimeters'] = perimeters.tojson();
I have an application with news api from https://newsapi.org/
My model from quicktype:
// To parse this JSON data, do
//
// final news = newsFromJson(jsonString);
import 'package:meta/meta.dart';
import 'dart:convert';
List<News> newsFromJson(String str) =>
List<News>.from(json.decode(str).map((x) => News.fromJson(x)));
String newsToJson(List<News> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class News {
News({
required this.status,
required this.totalResults,
required this.articles,
});
final String status;
final int totalResults;
final List<Article> articles;
factory News.fromJson(Map<String, dynamic> json) => News(
status: json["status"],
totalResults: json["totalResults"],
articles: List<Article>.from(
json["articles"].map((x) => Article.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"status": status,
"totalResults": totalResults,
"articles": List<dynamic>.from(articles.map((x) => x.toJson())),
};
}
class Article {
Article({
required this.source,
required this.author,
required this.title,
required this.description,
required this.url,
required this.urlToImage,
required this.publishedAt,
required this.content,
});
final Source source;
final String author;
final String title;
final String description;
final String url;
final String urlToImage;
final DateTime publishedAt;
final String content;
factory Article.fromJson(Map<String, dynamic> json) => Article(
source: Source.fromJson(json["source"]),
author: json["author"] == null ? null : json["author"],
title: json["title"],
description: json["description"],
url: json["url"],
urlToImage: json["urlToImage"],
publishedAt: DateTime.parse(json["publishedAt"]),
content: json["content"],
);
Map<String, dynamic> toJson() => {
"source": source.toJson(),
"author": author == null ? null : author,
"title": title,
"description": description,
"url": url,
"urlToImage": urlToImage,
"publishedAt": publishedAt.toIso8601String(),
"content": content,
};
}
class Source {
Source({
required this.id,
required this.name,
});
final String id;
final String name;
factory Source.fromJson(Map<String, dynamic> json) => Source(
id: json["id"] == null ? null : json["id"],
name: json["name"],
);
Map<String, dynamic> toJson() => {
"id": id == null ? null : id,
"name": name,
};
}
In my remoteservice.dart:
import 'package:http/http.dart' as http;
import 'package:nocovid/models/news.dart';
import 'package:nocovid/utils/constant.dart';
class RemoteServices {
static var client = http.Client();
static Future<List<News>?> fetchNews() async {
final String endpoint =
'https://newsapi.org/v2/everything?q=covid19&apiKey=' + kAPIKey;
final Uri url = Uri.parse(endpoint);
final response = await client.get(url);
if (response.statusCode == 200) {
var jsonString = response.body;
return newsFromJson(jsonString);
} else {
return null;
}
}
}
newscontroller.dart
import 'package:get/state_manager.dart';
import 'package:nocovid/models/news.dart';
import 'package:nocovid/services/remote_services.dart';
class NewsController extends GetxController {
var newsList = <News>[].obs;
#override
void onInit() {
fetchNews();
super.onInit();
}
void fetchNews() async {
var news = await RemoteServices.fetchNews();
if (news != null) {
newsList.value = news;
}
}
}
And get this errors:
and
the call is performed regularly but upon showing the data, it generates these errors.
I checked some codes on github and everything seems to work, while i can't get going
Change
List<News> newsFromJson(String str) =>
List<News>.from(json.decode(str).map((x) => News.fromJson(x)));
To
News newsFromJson(String str) => News.fromJson(json.decode(str));
The Reason for this is News object is not a list, it's a complex JSON with a map that consists of a list of Articles. You need to go through API properly.
If you want a model you can use quicktype. Just paste in the URL response.
Also Change
static Future<List<News>?> fetchNews()
to
static Future<News> fetchNews()
I want to save a list of objects into my local memory using the shared_preferences package.
Let's assume that this is my class:
class Person{
String name;
String age;
String gender;
}
How do I do that with shared_preferences?
I am looking forward to hearing from all of you. Thank you.
You can save a List<String> with shared_preferences.
Therefore, we need to convert the Person class, and its list, into a String by encoding them as JSON:
class Person {
String name;
String age;
String gender;
Person({this.name, this.age, this.gender});
factory Person.fromJson(Map<String, dynamic> parsedJson) {
return new Person(
name: parsedJson['name'] ?? "",
age: parsedJson['age'] ?? "",
gender: parsedJson['gender'] ?? "");
}
Map<String, dynamic> toJson() {
return {
"name": this.name,
"age": this.age,
"gender": this.gender,
};
}
}
void _savePersons(List<Person> persons) async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
List<String> personsEncoded = persons.map((person) => jsonEncode(person.toJson())).toList();
await sharedPreferences.setStringList('accounts', accounts);
}
In the same fashion, we can get the saved List<Person> as a JSON object and de-serialize it:
List<Person> _getPersons(List<Person> persons) async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
await sharedPreferences.setStringList('accounts', accounts);
return persons.map((person) => Person.fromJson(person)).toList();
}
I have a working json parsing from my commerce API. all are working fine except for storing the add cart product to the shared preferences. How can I achieve this? I got an error of type
'ProductsModel' is not a subtype of type 'Map<String, dynamic>';
Here's my ProductsModel
class ProductsList{
final List<ProductsModel> products;
ProductsList({this.products});
factory ProductsList.fromJSON(List<dynamic> parsedJson){
List <ProductsModel> productsList = new List<ProductsModel>();
productsList = parsedJson.map((i) => ProductsModel.fromJSON(i)).toList();
return new ProductsList(
products: productsList
);
}
}
class ProductsModel {
final int id;
final String name;
final String catalog_visibility;
final String description;
final String short_description;
final String price;
final String regular_price;
final String sale_price;
final String date_created;
final List<CategoriesModel> categories;
final List<ImagesModel> images;
ProductsModel(
{this.id,
this.name,
this.catalog_visibility,
this.description,
this.short_description,
this.price,
this.regular_price,
this.sale_price,
this.date_created,
this.categories,
this.images
});
factory ProductsModel.fromJSON(Map<String, dynamic> parsedJson) {
var categoriesList = parsedJson['categories'] as List;
var imagesList = parsedJson['images'] as List;
List<ImagesModel> dataImages = imagesList.map((i) => ImagesModel.fromJSON(i)).toList();
List<CategoriesModel> dataCategories =
categoriesList.map((i) => CategoriesModel.fromJSON(i)).toList();
return ProductsModel(
id: parsedJson['id'],
name: parsedJson['name'],
catalog_visibility: parsedJson['catalog_visibility'],
description: parsedJson['description'],
short_description: parsedJson['short_description'],
regular_price: parsedJson['regular_price'],
sale_price: parsedJson['sale_price'],
date_created: parsedJson['date_created'],
categories: dataCategories,
images: dataImages
);
}
}
class CategoriesModel {
final int id;
final String name;
CategoriesModel({this.id, this.name});
factory CategoriesModel.fromJSON(Map<String, dynamic> parsedJson) {
return CategoriesModel(id: parsedJson['id'], name: parsedJson['name']);
}
}
class ImagesModel{
final int id;
final String src;
final String name;
ImagesModel({this.id,this.src,this.name});
factory ImagesModel.fromJSON(Map<String,dynamic> parsedJson){
return ImagesModel(
id: parsedJson['id'],
src: parsedJson['src'],
name: parsedJson['name']
);
}
}
and I am testing to stored the ProductsModel only by using this function only
Here's my function
storedCart(products){
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setString('cart', products);
}
STEP 1 : Add a toMap() method in your class
Map<String,dynamic> toMap() {
var map = new Map<String, dynamic>();
map["id"] = id;
map["name"] = name;
map["description"] = description;
// Add all other fields
return map;
}
STEP 2 : While storing this in SharedPreferences call the toMap() method on the object
This will return a Map<String,dynamic> representation of your current object.
Map<String,dynamic> productsMap = products.toMap();
STEP 3 : Convert the object to String by using json.encode() and store it !
storedCart(productsMap){
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setString('cart', json.encode(productsMap));
}
Note :
Dont forget to import dart:convert
While retrieving the object don't forget to use json.decode()
If you are having trouble understanding why we used json.encode(), try printing the object before and after using the function, you'll notice that when we convert our object to JSON it becomes a big String, Therefore it is possible for us to store it in SharedPreferences using the "putString()" method.
I am trying to save result from json to SharedPreferrence but i keep getting Unhandled Exception: type 'String' is not a subtype of type 'int' of 'index'
This is my Code
_register(BuildContext context, User user) async {
var _userService = UserService();
var registeredUser = await _userService.createUser(user);
var encodeFirst = json.encode(registeredUser.body);
var result = json.decode(encodeFirst);
if(result['result'] == true){
SharedPreferences _prefs = await SharedPreferences.getInstance();
_prefs.setInt("userId", result["user"]["id"]);
_prefs.setString("userName", result["user"]["name"]);
_prefs.setString("userEmail", result["user"]["email"]);
Navigator.push(
context, MaterialPageRoute(builder: (context) => CheckoutScreen(cartItems: this.widget.cartItems,)));
} else {
_showSnackMessage(Text('Failed to register the user!', style: TextStyle(color: Colors.red),));
}
}
this is my User, UserService and Repository file
class User{
int id;
String name;
String email;
String password;
toJson(){
return{
'id': id.toString(),
'name': name,
'email': email,
'password': password
};
}
}
class UserService {
Repository _repository;
UserService(){
_repository = Repository();
}
createUser(User user) async{
return await _repository.httpPost('register', user.toJson());
}
}
httpPost(String api, data) async {
return await http.post(_baseUrl + "/" + api, body: data);
}
var encodeFirst = json.encode(registeredUser.body); will call User toJson()
And in toJson() , you have set 'id': id.toString(),
when you do var result = json.decode(encodeFirst);
It's actually a string not int
Correct toJson() please see below
// To parse this JSON data, do
//
// final user = userFromJson(jsonString);
import 'dart:convert';
User userFromJson(String str) => User.fromJson(json.decode(str));
String userToJson(User data) => json.encode(data.toJson());
class User {
int id;
String name;
String email;
String password;
User({
this.id,
this.name,
this.email,
this.password,
});
factory User.fromJson(Map<String, dynamic> json) => User(
id: json["id"],
name: json["name"],
email: json["email"],
password: json["password"],
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"email": email,
"password": password,
};
}