Flutter: Search special Arabic character in local file json - json

I am building flutter app with local json file, my json looks like
[
{
"category": "ملابس",
"count": 1,
"description": "ملابس رجالي",
"reference": "",
"color": "أحمر "
}
]
I need the user to find the product when he/she search e.g color, if the user search exactly 'أحمر' its works fine, but if the entered value was 'احمر' the condtion will be false so there is nothing appear in the list.
search function
Future<void> searchJson(query) async {
final jsondata = await rootBundle.loadString('assets/json/product.json');
final list = await json.decode(jsondata) as List<dynamic>;
List data = list
.where((map) => map['color']
.replaceAll(RegExp(String.fromCharCodes(arabicTashkelChar)), "")
.contains(query))
.toList();
setState(() {
items = data;
});
}
and here here is my arabicTashkelChar list for special Arabic character
const Iterable<int> arabicTashkelChar = [
1617,
124,
1614,
124,
1611,
124,
1615,
124,
1612,
124,
1616,
124,
1613,
124,
1618,
625,
627,
655,
];
I used arabicTashkelChar to make the string like this 'اللغَةُ الْعَرَبِيَّة' to this 'اللغة العربية'.
I don't have any problem with arabicTashkelChar its works fine my problem only with Alif (أ إ آ).
Now I want to make string like 'أحمر' to 'احمر'
Also 'آ أ إ ' to 'ا' how to achieve this thing?

you need to make some thing like this
void main() {
String myChar = 'أإآ';
print(myChar); // result = أإآ
String newChar = normalise(myChar);
print(newChar ); // result ااا
}
String myNormalise(String input) {
return input
// Replace Alifs with Hamza Above/Below and with Madda Above by Alif
.replaceAll('\u0622', '\u0627')
.replaceAll('\u0623', '\u0627')
.replaceAll('\u0625', '\u0627');
}
Edit
In your setuation your search code will be:
Future<void> searchJson(query) async {
final jsondata = await rootBundle.loadString('assets/json/product.json');
final list = await json.decode(jsondata) as List<dynamic>;
List data = list
.where((map) => map['color']
.replaceAll('\u0622', '\u0627')
.replaceAll('\u0623', '\u0627')
.replaceAll('\u0625', '\u0627')
.replaceAll(RegExp(String.fromCharCodes(arabicTashkelChar)), '')
.contains(query))
.toList();
setState(() {
items = data;
});
}
Another methode add a new element to your json file called search and write waht you want the user search for, so the json will some thing like:
[
{
"category": "ملابس",
"count": 1,
"description": "ملابس رجالي",
"reference": "",
"color": "أحمر ",
"search":"احمر"
}
]
And then change
...
List data = list.where((map) => map['search'].contains(query)).toList();
...
This is the answer for you question.

Related

How to access array inside array in flutter

Here i got some list of array
{
"id": 1,
"username": "dragonknight",
"password": "123",
"email": "dragon#mail.com",
"nama_lengkap": "Dragon Knight",
"createdAt": "2022-04-13T05:50:00.559Z",
"updatedAt": "2022-04-13T05:50:00.559Z",
"grupId": 1,
"grup": {
"id": 1,
"nama_grup": "fleetime",
"deskripsi": "Ini deskripsi",
"createdAt": "2022-04-13T05:53:18.423Z",
"updatedAt": "2022-04-13T05:53:18.423Z"
}
},
the problem is i want to enter grup array and enter nama_grup in flutter how do i do that. i tried with username and nama_lengkap and data show up correctly. but with grup it shows as null.
home.dart
https://pastebin.com/raw/F3Ha8vKK
You need to separate grup from object then access it. Wait for shared instance loaded then find for user string, if found do the json decode. Here is the working example:
class _DashboardState extends State<Dashboard> {
final Future<SharedPreferences> localStorage = SharedPreferences.getInstance();
String nama_grup = '';
#override
void initState() async {
super.initState();
// wait for SharedPreferences instance
final prefs = await localStorage;
// find user string from SharedPreferences
final String? user = prefs.getString('user');
var userGrup = [];
if (user != null) {
// decode json string if found
var userDecoded = json.decode(user);
setState(() {
userGrup.add(userDecoded['grup']);
nama_grup = userGrup[0]['nama_grup'];
});
}
}
...

How can I update/add new information to my local JSOn file in Flutter? (without creating any classes)

I made a small application, sort of like a library app where you can add books you've read. So, I have a local JSON file, which looks like this:
[
{
"name": "Harry Potter and the Deathly Hallows",
"author": "J.K. Rowling",
"rating": "4.5",
"category": "Fantasy",
"url": "some url"
},
{
"name": "For Whom The Bell Tolls",
"author": "E. Hemingway",
"rating": "4",
"category": "Novel",
"url": "some url#2"
}
]
In my main.dart file I have a function that reads my JSON file, decodes and loads it in a list named "data":
readData(){
DefaultAssetBundle.of(context).loadString("json/books.json").then((s){
setState(() {
data = json.decode(s);
});
});
}
#override
void initState() {
super.initState();
readData();
}
I can easily add new books to "data" and everything is fine except for one thing, - I don't know how to update/write information to JSON, so the app could show me the updated list with the new book after a restart. I've added. How do I do this? And what should I write into the JSON file, - the updated List with all books or just a Map with a new book?
Answer to NelsonThiago
This code is in "class AddingPageState extends State":
Future<String> get _localPath async {
final directory = await getApplicationDocumentsDirectory();
return directory.path;
}
Future<File> get _localFile async {
final path = await _localPath;
return File('$path/books.json');
}
Future<File> writeData(List list) async { // "list" is the updated book-list
final file = await _localFile;
String encodedData = jsonEncode(list);
return file.writeAsString('$encodedData');
}
And I call "writeData" in onPressed function.
It would be better to make this using a local NoSql database like sembast, this way you could add, delete and update your data. But as you are already working with json, You just need to encode your new changed data to json and write to the file again.
To write and read files, instead of using rootBundle read this read and write files.
As I can see from your JSON file, you are storing the Books as a list of JSON objects, which will make things easier.
But your request of solving this without adding new classes is a bit strange because adding a Book class in your case would make things much easier.
So I am going to give you a solution that assumes that you create a new Book class.
Start by reading the file as you are currently doing.
Store the content of the file in a List of dynamic List.
Iterate through the list using the map function, add using the from JSON function in the Book class decode the JSON to a book object, then apply the toList() function on that map.
Return the result to your UI and treat it as any other list.
When you want to add a new Book, create a new object of the book class and add it to your list.
When the user finishes adding, transform the list to a JSON object agian and store it in the file again;
Something like this:
The Book Class:
class Book {
String? name;
String? author;
String? rating;
String? category;
String? url;
Book({
required this.name,
required this.author,
required this.rating,
required this.category,
required this.url,
});
Book.fromJson(Map<String, dynamic> json) {
name = json['name'];
author = json['author'];
rating = json['rating'];
category = json['category'];
url = json['url'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['name'] = this.name;
data['author'] = this.author;
data['rating'] = this.rating;
data['category'] = this.category;
data['url'] = this.url;
return data;
}
#override
String toString() {
return 'Book(name: $name, author: $author, rating: $rating, category: $category, url: $url)';
}
}
And main function
void main() {
/// read the file the way you like
List<dynamic> list = [
{
"name": "Harry Potter and the Deathly Hallows",
"author": "J.K. Rowling",
"rating": "4.5",
"category": "Fantasy",
"url": "some url"
},
{
"name": "For Whom The Bell Tolls",
"author": "E. Hemingway",
"rating": "4",
"category": "Novel",
"url": "some url#2"
}
];
List<Book> books = list
.map(
(jsonObject) => Book.fromJson(jsonObject),
)
.toList();
print(books);
Book newBook = Book(
name: 'Some Book',
author: 'Some Author',
rating: 'Some rating',
category: 'Some category',
url: 'Some Url');
books.add(newBook);
print(books);
books
.map(
(book) => book.toJson(),
)
.toList();
//Write the the file again to storage or anywhere else
}
See the following example. But it requires to create a class. The sample json file is like below (pretty much similar to your json file) -
[
{"name":"Ash","age":"22","hobby":"golf"},
{"name":"philip","age":"17","hobby":"fishing"},
{"name":"charles","age":"32","hobby":"drawing"},
]
And I am editing the above code answered by Ward Suleiman so that you can read from a local json file and write to it-
import 'dart:io';
import 'dart:convert';
List<Player> players = [];
void main() async{
print("hello world");
final File file = File('D:/Sadi/.../test.json'); //load the json file
await readPlayerData(file); //read data from json file
Player newPlayer = Player( //add a new item to data list
'Samy Brook',
'31',
'cooking'
);
players.add(newPlayer);
print(players.length);
players //convert list data to json
.map(
(player) => player.toJson(),
)
.toList();
file.writeAsStringSync(json.encode(players)); //write (the whole list) to json file
}
Future<void> readPlayerData (File file) async {
String contents = await file.readAsString();
var jsonResponse = jsonDecode(contents);
for(var p in jsonResponse){
Player player = Player(p['name'],p['age'],p['hobby']);
players.add(player);
}
}
And the Player class -
class Player {
late String name;
late String age;
late String hobby;
Player(
this.name,
this.age,
this.hobby,
);
Player.fromJson(Map<String, dynamic> json) {
name = json['name'];
age = json['age'];
hobby = json['hobby'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['name'] = this.name;
data['age'] = this.age;
data['hobby'] = this.hobby;
return data;
}
}

Unable to load JSON data to show in ListView

I need to get the json array data in flutter app by providing the get method.
The problem that I am facing is that I am not able to put the records in the empty list carList.
but I am getting the array of objects as shown below(POSTMAN) by
print(json.decode(response.body)) // in the file cars.dart
Hence if you could please help me on how to get the response in the List carlist = [];
Car_list.dart file calls the method for the get request.
Please let me know if you require any further information from my end.
Thankyou
POSTMAN
[
{
"id": "1",
"carModel" : "Maruti swift",
"carDescription" : "The car has a top speed of 180 km/hr"
},
{
"id": "1",
"carModel" : "Hyundai santro",
"carDescription" : "The car has a top speed of 150 km/hr"
},
{
"id": "1",
"carModel" : "Hyundai creta",
"carDescription" : "The car has a top speed of 160 km/hr"
}
]
CarsModel.dart
class Cars with ChangeNotifier{
String userId;
String carModel
String carDescription;
Cars(
{
this.userId = '1111',
this.carModel,
this.carDescription,
}
);
factory Cars.fromJSON(Map<String,dynamic> json) => Cars(
userId : json['userId'],
carModel : json['CarModel'],
carDescription : json['carDescription'],
);
toJSON() {
return {
'userId':'111',
'carModel':carModel,
'carDescription' : carDescription
};
}
cars.dart
class CarProvider with ChangeNotifier{
List<Cars> carlist = [
//Sample data to show the format in which the data needs to be shown as the listview gets populated from below records which we are supposed to get from postman
//Cars (
// userid: 1111,
// carModel: 'Maruti Alto',
// carDescription: 'Top speed 140 km/hr'
),
];
Future<void> readListofCars(int id) async {
print(id.toString());
const url = 'http://localhost/userlist';
// {'id': id.toString()
Map<String, String> headers = {
"Content-type": "application/json"};
try
{
final response = await http.get(url,headers: headers);
List<dynamic> bodyCars = jsonDecode(response.body);
List<Cars> loadedCars = bodyCars.map((dynamic item) => new Cars.fromJSON(item)).toList();
/*
for (Map i in bodyCars) {
_notificationitems.add(Cars.fromJSON(i));
}
*/
});
print(response.statusCode);
carlist = loadedCars;
print(json.decode(response.body));
notifyListeners();
}catch (error){
throw error;
}
}
Car_list.dart
class TabScreenCar extends StatefulWidget {
final String userId;
TabScreenCar(this.userId);
#override
_TabScreenCarState createState() => _TabScreenCarState();
}
class _TabScreenCarState extends State<TabScreenCar> {
#override
void didChangeDependencies() {
final id = 1111;
Provider.of<CarProvider>(context).readListofCars(id);
super.didChangeDependencies();
}
In your model class you have incorrect variable to fetch the json data
to make the process simple you can have a look at this link
https://stackoverflow.com/a/58708634/9236994
just paste your json response in https://javiercbk.github.io/json_to_dart/
and use the json model class which will be generated.
your issue will be resolved.
variable which you are using doesn't match with your json response
OR to keep it simple
use below mentioned fromJSON method
factory Cars.fromJSON(Map<String,dynamic> json) => Cars(
userId : json['id'],
carModel : json['carModel'],
carDescription : json['carDescription'],
);
EDIT
I think you are facing issue with setting up the data in your list variable too.
use below shown code to fill the response into list if cars data
List<Cars> loadedCars = List<Cars>();
var data = jsonDecode(response.body);
data.forEach((val) {
loadedCars.add(Cars.fromJSON(val));
}

Flutter json decode returns null

I'm getting a null return when I run the following code. Apparently I'm not accessing json correctly.
Is there another way to access json data? Or is it ok to use it like that?
Future Class - parsing json from a url
Future<List<User>> _getUsers() async {
var data = await http.get("https://...api.php");
if (data.statusCode == 200) {
print('Status Code 200: Ok!');
var jsonData = json.decode(data.body);
List<User> users = [];
for (var u in jsonData[0]) {
print(u[0]["title"]);
User user = User(u["id"], u["source"], u["desc"], u["link"], u["title"]);
users.add(user);
}
print(users.length);
return users;
} else {
throw Exception('Failed to load json');
}
}
Class
class User {
final int id;
final String source;
final String desc;
final String link;
final String title;
User(this.id, this.source, this.desc, this.link, this.title);
}
Basic json structure:
{
"0":{
"id":0,
"source":"XXX",
"link":"XXXX",
"title":"XXXX",
"desc":"XXXX"
},
"1":{
"id":1,
"source":"XXX",
"link":"XXXX",
"title":"XXXX",
"desc":"XXXX"
}
}
What am missing here? thanks.
You're trying to use something that isn't a list as a list. The json structure you've provided looks like part of an object and not a list.
A list would look like this:
[{
"id": 0,
"source": "XXX",
"link": "XXXX",
"title": "XXXX",
"desc": "XXXX"
}]
But since the underlying structure is a Map you could iterate over the keys, doing something like this:
for (var k in jsonData.keys) {
var u = jsonData[k];
print(u["title"]);
User user = User(u["id"], u["source"], u["desc"], u["link"], u["title"]);
}
Your json structure is not a real json. But if your json is like this:
{
"0":{
"id":0,
"source":"XXX",
"link":"XXXX",
"title":"XXXX",
"desc":"XXXX"
},
"1":{
"id":1,
"source":"XXX",
"link":"XXXX",
"title":"XXXX",
"desc":"XXXX"
}
}
You can get data like this:
for (int i = 0; i < length; i ++) {
User user = User(u["$i"]["id"], u["$i"]["source"], u["$i"]["desc"], u["$i"]["link"], u["$i"]["title"]);
users.add(user);
}

Grabbing a number from .JSON

I have a long list of data, in the following format:
[
{
"ID": "1234",
"date/time": "2016-07-18 18:21:44",
"source_address": "8011",
"lat": "40.585260",
"lng": "-105.084420",
}
]
And I am creating a script to extract the values out of each line. For example, if a line contains "ID": I want to be able to store the value "1234" into a variable, so I can store it in a different format.
Here is my code to detect "ID":
'use strict';
let lineReader = require('line-reader');
//.JSON variables from input file
let id;
//begin creating new object
console.log('var source = {');
//output the file
lineReader.eachLine('dataOut.json', function (line, last) {
//detect ID, and print it out in the new format
if (id =~ /^id:$/) {
console.log('id: "') + console.log('",');
}
//done
if (last) {
console.log('}');
return false; // stop reading
}
});
Once I detect the ID, I'm not sure how I can obtain the value that follows the "ID" on that line.
How can I store the values on a line, after I detect which line they are on?
Unless your json file is stupidly big, you can just require it and then it's an in memory JS object.
var obj = require('./dataOut.json');
// first element
console.log(obj[0]);