how to replace some string from outside in json file - json

I have a localization map like:
'en': {
"timeIsUpTitle": "Time is Up!",
"workingTimeText": "You are working for{{}} {{}} {{}}.."
},
'tr': {
'timeIsUpTitle': 'Zaman doldu!',
"workingTimeText": "{}{}{}çalışıyorsun..."
},
how can I fill these {} sections on the outside? I have some getters for these strings such as,
String workingTimeText(String hours, String minutes, String seconds) => localeValues['workingTimeText']!;
String get timeIsUpTitle => localeValues['timeIsUpTitle']!;

Here is a simple example of how to update the Map. You can create your own function based on your preferences.
void main() {
for (var key in data.keys) {
Map<String, String>? value = data[key];
if (value == null) return;
value.update("workingTimeText", (value) => 'New Data');
}
data.values.forEach(print);
}
var data = {
"en": {
"timeIsUpTitle": "Time is Up!",
"workingTimeText": "You are working for{{}} {{}} {{}}.."
},
"tr": {
"timeIsUpTitle": "Zaman doldu!",
"workingTimeText": "{}{}{}çalışıyorsun..."
}
};
Output:
{timeIsUpTitle: Time is Up!, workingTimeText: New Data}
{timeIsUpTitle: Zaman doldu!, workingTimeText: New Data}

I solved with format package in pub dev (it's the same as python's format funct.)

Related

Error: Expected a value of type 'Iterable<dynamic>', but got one of type '_JsonMap'

Have tried to create a List of objects out of a json file.
I get this error: Error: Expected a value of type 'Iterable', but got one of type '_JsonMap'
Future <List<Inspection>> FutureInspections() async {
var inspections = <Inspection>[];
final String response = await rootBundle.loadString('assets/sample.json');
var inspectionsJson = json.decode(response);
for (var inspectionJson in inspectionsJson) {
inspections.add(Inspection.fromJson(inspectionJson));
}
return inspections;
}
[Update 03.11.2021 Inspection class]
class Inspection
{
String _description="";
int _interval=0;
int _state=0;
DateTime _date=new DateTime.now();
Inspection(this._description, this._interval, this._state, this._date);
Inspection.fromJson(Map<String, dynamic>json){
_description=json['description'];
_interval=json['interval'];
_state=json['state'];
_date=json['date'];
}
DateTime get date => _date;
set date(DateTime value) {
_date = value;
}
int get state => _state;
set state(int value) {
_state = value;
}
int get interval => _interval;
set interval(int value) {
_interval = value;
}
String get description => _description;
set description(String value) {
_description = value;
}
}
the error pops up at this part of the code:
inspections.add(Inspection.fromJson(inspectionJson));
[Update 03.11.2021 Json-File]
Json-File:
{
"inspections": [
{
"date": "01.01.2021",
"state": "1",
"interval": "7",
"description": "SampleText1"
},
{
"date": "01.01.2021",
"state": "2",
"interval": "3",
"description": "SampleText2"
}
]
}
I don't understand why. Can you please help me?
Response of json.decode is a _JsonMap. Out of it, extract the inspections as below.
Future<List<Inspection>> FutureInspections() async {
………
var inspectionsJson = json.decode(response);
final inspect = inspectionsJson['inspections']; <———
for (var resp in inspect) {
inspections.add(Inspection.fromJson(resp));
}
return inspections;
}
Also the json sample shown has String type for interval and state, String for date variable, but the Inspection class has int and DateTime types.This might need to change to String. After the values are put as String, they can be later converted to the desired type.

How to search in json object in angular using a string?

Json
{
"rootData": {
"test1": {
"testData0": "Previous data",
"testData1": "Earlier Data"
},
"test2": {
"testData0": "Partial data",
"testData1": "Services data"
},
"test3": {
"testData0": "Regular data",
"testData1": {
"testData0": "Your package"
}
}
}
}
Component.ts
import * as configData from './myData.json';
getData(data: string){
console.log(configData.rootData.test1.testData0); //returns "Previous Data.
return configData.rootData.{{data}}.testData0;
}
This getData method is being called in a loop passing a string with values of "test1" the first time "test2" the second time and "test3" the third time called.
I want to do something like this
return configData.rootData.{{data}}.testData0; //should return Previous data, then "partial data" if called again because test2 will be passed in data string.
I know this is not possible the way I am doing it because {{data}} is not defined in my json object.
The goal is to check for the object inside the object. The string data is returning values existing in the json object. I want to use that data to dynamically search in the json file and pull the values.
I know my attempt is not valid. I would like to know if there is an alternative to make this work as I intended.
To get the value with the key in Object, you can use Object[key] (here, key is variable name) and this will return the value of the selected key.
return configData.rootData[data]?.testData0; // Javascript case
So instead of using {{ }}, replace it with square brackets and you will get the result.
And on the above code, rootData[data]?.testData0 has same meaning as rootData[data] ? rootData[data].testData0 : undefined so this will be needed for validation check. (unexpected data value input)
On Typescript,
if (data in configData.rootData && "testData0" in configData.rootData[data]) {
return configData.rootData[data].testData0;
} else {
return undefined;
}
const input = {
"rootData": {
"test1": {
"testData0": "Previous data",
"testData1": "Earlier Data"
},
"test2": {
"testData0": "Partial data",
"testData1": "Services data"
},
"test3": {
"testData0": "Regular data",
"testData1": {
"testData0": "Your package"
}
}
}
};
let data = 'test1';
console.log(input.rootData[data]?.testData0);
data = 'test2';
console.log(input.rootData[data]?.testData0);
data = 'test3';
console.log(input.rootData[data]?.testData0);
data = 'test4';
console.log(input.rootData[data]?.testData0);
data = 'test5';
if (data in input.rootData) {
console.log('Existed', input.rootData[data].testData0);
} else {
console.log('Not Existed');
}
I use ng2-search-filter.
By directive
<tr *ngFor="let data of configData | filter:searchText">
<td>{{testData0}}</td>
<td>{{testData1}}</td>
...
</tr>
Or programmatically
let configDataFiltered = new Ng2SearchPipe().transform(this.configData, searchText);
Practical example: https://angular-search-filter.stackblitz.io

How to decode large json array in flutter

I have a rather large json file that I have downloaded using my flutter app from a web api that's around 200MB using
final response = Dio().get(uri, options: Options(responseType: ResponseType.plain));
(Using default Dio options also uses json decoding, resulting in an out of memory exception.
This is not directly part of my problem but maybe it helps)
Now the problem starts after obtaining the json string.
When I use jsonDecode on the response body I run out of memory. (maybe the same function Dio uses?)
final data = jsonDecode(response.body); this runs out of memory
The json object itself is an array with a lot of items with a format like this:
[
{"data": {independent data1}},
{"data": {independent data2}},
...
]
and i would be fine just decoding one item at a time instead of everything at once to reduce memory usage. Is there another way to do process all the items in this array? Something like
jsonArrayDecode(response.body, onItemDecode: (item) { /*do stuff with item */ });
Or do I have to write my own json reader that can sequentially decode it?
Thanks to #pskink, I managed to solve my problem. I used the ResponseType.stream from Dio to get stream which can be processed using the reviver function argument from the JsonDecoder. I process all the data in the reviver and ignore the data in the onData function of the listener.
...
final response = await dio.get(uri,
options: Options(responseType: ResponseType.stream);
Function reviver = (key, value) {
if (/*value is element from top level list*/) {
processItem(value);
return null;
}
return value;
}
final completer = Completer();
response.data.stream.cast<List<int>>()
.transform(utf8.decoder)
.transform(JsonDecoder(reviver))
.listen(null, onDone: () { completer.complete(); });
await completer.future;
...
If the problem is really that the data file is very large, then the problem can be solved by not storing unnecessary objects during parsing.
This will only make sense if not all of the data is needed, but only some of the data.
In this case, we are talking about filtering data on the fly, that is, directly during the data parsing process.
Below is a small example of how this can be implemented.
import 'package:fast_json/fast_json_selector.dart' as parser;
import 'package:fast_json/fast_json_selector.dart' show JsonSelectorEvent;
void main(List<String> args) {
// Select users from the list by indexes [2..3] and terminate selection
final users = <User>[];
final level = '{} data [] 0 {}'.split(' ').length;
final elementLevel = '{} data [] 0'.split(' ').length;
void select(JsonSelectorEvent event) {
final levels = event.levels;
if (levels.length == level) {
final index = event.levels[elementLevel - 1] as int;
if (index >= 2 && index <= 3) {
final map = event.lastValue as Map;
final user = User.fromJson(map);
users.add(user);
}
// Free up memory
event.lastValue = null;
if (users.length == 2) {
throw const _TerminateException();
}
}
}
try {
parser.parse(_data, select: select);
} on _TerminateException {
//
}
print(users.join(', '));
}
const _data = '''
{
"success":true,
"data":[
{
"id":1,
"name":"Leanne Graham",
"username":"Bret",
"email":"Sincere#april.biz",
"address":{
"street":"Kulas Light",
"suite":"Apt. 556",
"city":"Gwenborough",
"zipcode":"92998-3874",
"geo":{
"lat":"-37.3159",
"lng":"81.1496"
}
},
"phone":"1-770-736-8031 x56442",
"website":"hildegard.org",
"company":{
"name":"Romaguera-Crona",
"catchPhrase":"Multi-layered client-server neural-net",
"bs":"harness real-time e-markets"
}
},
{
"id":2,
"name":"Ervin Howell",
"username":"Antonette",
"email":"Shanna#melissa.tv",
"address":{
"street":"Victor Plains",
"suite":"Suite 879",
"city":"Wisokyburgh",
"zipcode":"90566-7771",
"geo":{
"lat":"-43.9509",
"lng":"-34.4618"
}
},
"phone":"010-692-6593 x09125",
"website":"anastasia.net",
"company":{
"name":"Deckow-Crist",
"catchPhrase":"Proactive didactic contingency",
"bs":"synergize scalable supply-chains"
}
},
{
"id":3,
"name":"Clementine Bauch",
"username":"Samantha",
"email":"Nathan#yesenia.net",
"address":{
"street":"Douglas Extension",
"suite":"Suite 847",
"city":"McKenziehaven",
"zipcode":"59590-4157",
"geo":{
"lat":"-68.6102",
"lng":"-47.0653"
}
},
"phone":"1-463-123-4447",
"website":"ramiro.info",
"company":{
"name":"Romaguera-Jacobson",
"catchPhrase":"Face to face bifurcated interface",
"bs":"e-enable strategic applications"
}
},
{
"id":4,
"name":"Patricia Lebsack",
"username":"Karianne",
"email":"Julianne.OConner#kory.org",
"address":{
"street":"Hoeger Mall",
"suite":"Apt. 692",
"city":"South Elvis",
"zipcode":"53919-4257",
"geo":{
"lat":"29.4572",
"lng":"-164.2990"
}
},
"phone":"493-170-9623 x156",
"website":"kale.biz",
"company":{
"name":"Robel-Corkery",
"catchPhrase":"Multi-tiered zero tolerance productivity",
"bs":"transition cutting-edge web services"
}
},
{
"id":5,
"name":"Chelsey Dietrich",
"username":"Kamren",
"email":"Lucio_Hettinger#annie.ca",
"address":{
"street":"Skiles Walks",
"suite":"Suite 351",
"city":"Roscoeview",
"zipcode":"33263",
"geo":{
"lat":"-31.8129",
"lng":"62.5342"
}
},
"phone":"(254)954-1289",
"website":"demarco.info",
"company":{
"name":"Keebler LLC",
"catchPhrase":"User-centric fault-tolerant solution",
"bs":"revolutionize end-to-end systems"
}
}
]
}''';
class Company {
final String name;
Company({required this.name});
#override
String toString() {
return name;
}
static Company fromJson(Map json) {
return Company(
name: json['name'] as String,
);
}
}
class User {
final String city;
final int id;
final String name;
User({required this.city, required this.id, required this.name});
#override
String toString() {
return '$id:$name from $city';
}
static User fromJson(Map json) {
return User(
city: json['address']['city'] as String,
id: json['id'] as int,
name: json['name'] as String,
);
}
}
class _TerminateException {
const _TerminateException();
}

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 get Object property Name

I passed the following object:
var myVar = { typeA: { option1: "one", option2: "two" } }
I want to be able to pull out the key typeA from the above structure.
This value can change each time so next time it could be typeB.
So I would like to know if there is any way to do that
I was able to solve using 'keys'
for a json example like this:
{
"1-0001": {
"name": "red",
"hex": "FF0000"
},
"1-0002": {
"name": "blue",
"hex": "0000FF"
},
"1-0003": {
"name": "green",
"hex": "008000"
}
}
I was able to use
Map<String, dynamic> decoded = json.decode(jsonString);
for (var colour in decoded.keys) {
print(colour); // prints 1-0001
print(decoded[colour]['name']); // prints red
print(decoded[colour]['hex']); // prints FF0000
}
To get all filenames you can use:
var data = ...
var filenames = [];
for(var i = 0; i < data.length; i++) {
var item = data[0]['files'];
var key = item.keys.first;
var filename = item[key]['filename'];
filenames.add(filename);
}
print(filenames);
You need to define a data type.
It is basically a map of (key value-pair) where key is changed as stated in question typeA or typeB
This Object has 2 properties option1 and option2 which is also strings.
Here is the sample code to construct model and how to use it
import 'package:TestDart/TestDart.dart' as TestDart;
main(List<String> arguments) {
var map = new Map<String, MyObject>();
map['typeA'] = new MyObject("one", "two");
map['typeB'] = new MyObject("one", "two");
print(map['typeA'].toString());
print(map['typeA'].toString());
}
class MyObject {
String _option1;
String _option2;
MyObject(this._option1, this._option2);
String get option2 => _option2;
String get option1 => _option1;
#override
String toString() {
return 'MyObject{option1: $_option1, option2: $_option2}';
}
}
Relevant answer
map.forEach((key, value) {
print("Key : ${key} value ${value}");
});