Create Json Arrays and List with SharedPreferences - flutter

I have been using shared_preferences to create and write in Json Files. The Problem i facing is i dont know how to create a Json Array and a List in shared_preferences.
I want to save and read a Json List.
read(String key) async {
final prefs = await SharedPreferences.getInstance();
return json.decode(prefs.getString(key));
}
save(String key, value) async {
final prefs = await SharedPreferences.getInstance();
prefs.setString(key, json.encode(value));
}
remove(String key) async {
final prefs = await SharedPreferences.getInstance();
prefs.remove(key);
}
} ```

Example on DartPad.
Save a list to SharedPreferences with setStringList:
const String key = "users";
List<User> users = [User(name: "tester")];
List<String> jsonList = users.map((user) => user.toJson()).toList();
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setStringList(key, jsonList);
Read a list from SharedPreferences with getStringList:
jsonList = prefs.getStringList(key);
users = jsonList.map((json) => User.fromJson(json)).toList();
The user class with json convert: JSON and serialization
class User {
String name;
int age;
User({
this.name,
this.age,
});
factory User.fromJson(String str) => User.fromMap(json.decode(str));
String toJson() => json.encode(toMap());
factory User.fromMap(Map<String, dynamic> json) => User(
name: json["name"],
age: json["age"],
);
Map<String, dynamic> toMap() => {
"name": name,
"age": age,
};
}

Just map your json array to List<String> and after you can use the setStringList function provided in shared_preferences.dart
/// Saves a list of strings [value] to persistent storage in the background.
///
/// If [value] is null, this is equivalent to calling [remove()] on the [key].
Future<bool> setStringList(String key, List<String> value) =>
_setValue('StringList', key, value);

Related

How to access token saved as a variable in different dart page in a secured storage

I have saved a token as a variable in flutter secure storage in a file called login_response_model.dart and I am trying to access it in the home screen, but I keep getting error as undefined name:
Here is the login_response_model.dart:
class LoginResponse {
dynamic? key;
List<dynamic>? non_field_errors;
LoginResponse({this.key, this.non_field_errors});
factory LoginResponse.fromJson(mapOfBody) {
return LoginResponse(
key: mapOfBody['key'],
non_field_errors: mapOfBody['non_field_errors'],
);
}
}
LoginResponseModel loginResponseJson(String str) =>
LoginResponseModel.fromJson(json.decode(str));
class LoginResponseModel {
dynamic? key;
List<dynamic>? non_field_errors;
LoginResponseModel({this.key, this.non_field_errors});
LoginResponseModel.fromJson(mapOfBody) {
key:
mapOfBody['key'];
non_field_errors:
mapOfBody['non_field_errors'];
print(mapOfBody['key']);
// Create storage
final storage = new FlutterSecureStorage();
// Write value
storage.write(key: 'Token', value: mapOfBody['key']);
}
Map<String, dynamic> toJson() {
final _data = <String, dynamic>{};
_data['key'] = key;
_data['non_field_errors'] = non_field_errors;
return _data;
}
}
class Data {
Data({
required this.username,
required this.email,
required this.date,
required this.id,
required this.key,
});
late final String username;
late final String email;
late final String date;
late final String id;
late final String key;
Data.fromJson(Map<String, dynamic> json) {
username = json['username'];
email = json['email'];
date = json['date'];
id = json['id'];
key = json['key'];
}
Map<String, dynamic> toJson() {
final _data = <String, dynamic>{};
_data['username'] = username;
_data['email'] = email;
_data['date'] = date;
_data['id'] = id;
_data['key'] = key;
return _data;
}
}
Here is the homescreen:
Future<User> fetchUser() async {
var url = Uri.parse(Config.apiURL + Config.userProfileAPI);
var value = storage.read(key: 'Token');
My question:
How can I access the token saved in a secured storage into the home screen?
Is there an easier and more secure way to access the token saved other than the way I have arranged it?
Use can you SharedPreference & save token here. Each time you want to use, you just need to:
SharedPreferences prefs = await SharedPreferences.getInstance();
String token = prefs.getString("key_token") ?? "";
However, each time you want to use it, you again need to use async function & wait until it give you saved token. Although it doesn't take so much time & space but we need to notice this. You can init a global variable to save token whenever open app or login success. Learn more about Singleton.
Example in my app: data_instance.dart
class DataInstance {
static DataInstance _instance = new DataInstance.internal();
DataInstance.internal();
factory DataInstance() => _instance;
late String accessToken;
initPreference() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
DataInstance().accessToken = prefs.getString("key_token_haha")?? '';
}
}
In main.dart:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await DataInstance().initPreference();
runApp(const MyApp());
}

How to save a list of objects locally in Flutter?

I have a page from which I need to save data locally as a list. To save, I use SharedPrefs, there, through the model, I save the data as a list. But I ran into a problem that I can not specify the format for receiving data List, tell me how can I save data as a list and receive data as a list?
class RecentlySearchedModel {
String name;
String address;
RecentlySearchedModel({
required this.name,
required this.address,
});
factory RecentlySearchedModel.fromJson(Map<String, dynamic> json) {
return RecentlySearchedModel(
name: json['name'] as String,
address: json['address'] as String,
);
}
Map<String, dynamic> toJson() {
return {
'name': name,
'address': address,
};
}
}
repository
#override
Future setResentlySearched({required List<RecentlySearchedModel> searchedList}) async {
final SharedPrefs prefs = SharedPrefs();
await prefs.setString(_name, jsonEncode( ))
}
#override
Future<List<RecentlySearchedModel>?> getResentlySearched() async {
final SharedPrefs prefs = SharedPrefs();
final data = await prefs.getString(_name);
if (data == null) return null;
return List<RecentlySearchedModel>.fromJson(
jsonDecode(data),
);
}
update your repository like this.
#override
Future setResentlySearched({required List<RecentlySearchedModel> searchedList}) async {
final SharedPrefs prefs = SharedPrefs();
await prefs.setString(_name, jsonEncode(searchedList.toJson());
}
#override
Future<List<RecentlySearchedModel>?> getResentlySearched() async {
final SharedPrefs prefs = SharedPrefs();
final data = await prefs.getString(_name);
if (data == null) return null;
Iterable l = json.decode(data);
List<RecentlySearchedModel> posts = List<RecentlySearchedModel>.from(l.map((model)=> RecentlySearchedModel.fromJson(model)));
return posts;
}
i havent try to complie, but its should be like this
Future setResentlySearched({required List<RecentlySearchedModel> searchedList}) async {
List<Map<String,dynamic>> listItem = searchedList.map((e)=> e.toJson()).toList();
String jsonString = jsonEncode(listItem);
final SharedPrefs prefs = SharedPrefs();
await prefs.setString(_name, jsonString)
}
and get it back
Future<List<RecentlySearchedModel>?> getResentlySearched() async {
final SharedPrefs prefs = SharedPrefs();
final data = await prefs.getString(_name);
if (data == null) return null;
return (jsonDecode(data) as List).map((e)=> RecentlySearchedModel.fromJson(e)).toList();
}

How to save list data in SharedPreferences flutter

I make data connection with database to bring a list of data such as the following code:
var listDATA = [];
Future listDATAs() async {
api = '*************';
var response = await http.post(Uri.parse(api));
var responsebody = jsonDecode(response.body);
if (responsebody.length >0){
for (int i = 0; i < responsebody.length; i++) {
listDATA.add(responsebody[i]['name']+ ':' + responsebody[i]['image'].toString());
}
return responsebody;
}else{
}
}
How can I store listDATA in Shared Preferences I need to save name and image ? Then recall it to display after storage
It's preferred not to store non-primitive data types in SharedPreferences as it supports only primitive data types by default. But still there is a way to do it.
you can store the response body of your API call without decoding JSON to a String value.
// Obtain shared preferences.
final prefs = await SharedPreferences.getInstance();
// Save an String value to 'response' key.
await prefs.setString('response', response.body);
if you have response types of List, you can use setStringList method
await prefs.setStringList('items', <String>['Earth', 'Moon', 'Sun']);
in this way you can store list value in shared preference
static setListValue(String key, List< ProductsModel > value) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString(key, jsonEncode(value.map((e) => e.toJson()).toList()));
}
her I make a standard method to store list values from any class by calling
setListValue('store_list', listData);
after that, you have to make a method for getting this list value
//getListValue
static Future<List<ProductsModel>?> getListValue(String key) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
final dataMap = jsonDecode(prefs.getString(key) ?? '[]') as
List<dynamic>;
return dataMap.map<ProductsModel>((item) {
return ProductsModel.fromJson(item);
}).toList();
}
after that, you can call this method like this
var listValue = await SPUtils.getListValue('store_list');
// for saving the list in shared preferences
final prefs = await SharedPreferences.getInstance();
prefs.setString("list",jsonEncode(listDATA));
// for getting the list from shared preferences
final prefs = await SharedPreferences.getInstance();
List listDATA = jsonDecode(prefs.get("list"));
You can follow those steps.
convert your object to map with toMap() method.
encode your map to string with encode() method.
Save the string to shared preferences.
final SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setString('key', encodedData);
// Fetch and decode data
final String musicsString = await prefs.getString('musics_key');
Example :
import 'dart:convert';
void main() async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
final String encodedData = Music.encode([
Music(id: 1, ...),
Music(id: 2, ...),
Music(id: 3, ...),
]);
await prefs.setString('musics_key', encodedData);
// Fetch and decode data final String musicsString = await prefs.getString('musics_key');
final List<Music> musics = Music.decode(musicsString); }
class Music {
final int id;
final String name,
size,
rating,
duration, img; bool favorite;
Music({
this.id,
this.rating,
this.size,
this.duration,
this.name,
this.img,
this.favorite, });
factory Music.fromJson(Map<String, dynamic> jsonData) {
return Music(
id: jsonData['id'],
rating: jsonData['rating'],
size: jsonData['size'],
duration: jsonData['duration'],
name: jsonData['name'],
img: jsonData['img'],
favorite: false,
); }
static Map<String, dynamic> toMap(Music music) => {
'id': music.id,
'rating': music.rating,
'size': music.size,
'duration': music.duration,
'name': music.name,
'img': music.img,
'favorite': music.favorite,
};
static String encode(List<Music> musics) => json.encode(
musics
.map<Map<String, dynamic>>((music) => Music.toMap(music))
.toList(),
);
static List<Music> decode(String musics) =>
(json.decode(musics) as List<dynamic>)
.map<Music>((item) => Music.fromJson(item))
.toList(); }

Flutter & Shared Preferences : How do I save a list (of object) to local memory?

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();
}

Flutter Save Object on SharedPreferences

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.