I have string like this,
{id:1, name: lorem ipsum, address: dolor set amet}
And I need to convert that string to json, how I can do it in dart flutter? thank you so much for your help.
You have to use json.decode. It takes in a json object and let you handle the nested key value pairs. I'll write you an example
import 'dart:convert';
// actual data sent is {success: true, data:{token:'token'}}
final response = await client.post(url, body: reqBody);
// Notice how you have to call body from the response if you are using http to retrieve json
final body = json.decode(response.body);
// This is how you get success value out of the actual json
if (body['success']) {
//Token is nested inside data field so it goes one deeper.
final String token = body['data']['token'];
return {"success": true, "token": token};
}
Create a model class
class User {
int? id;
String? name;
String? address;
User({this.id, this.name, this.address});
User.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
address = json['address'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['name'] = this.name;
data['address'] = this.address;
return data;
}
}
In the logic section
String data ='{id:1, name: lorem ipsum, address: dolor set amet}';
var encodedString = jsonEncode(data);
Map<String, dynamic> valueMap = json.decode(encodedString);
User user = User.fromJson(valueMap);
Also need to import
import 'dart:convert';
You can also convert JSON array to list of Objects as following:
String jsonStr = yourMethodThatReturnsJsonText();
Map<String,dynamic> d = json.decode(jsonStr.trim());
List<MyModel> list = List<MyModel>.from(d['jsonArrayName'].map((x) => MyModel.fromJson(x)));
And MyModel is something like this:
class MyModel{
String name;
int age;
MyModel({this.name,this.age});
MyModel.fromJson(Map<String, dynamic> json) {
name= json['name'];
age= json['age'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['name'] = this.name;
data['age'] = this.age;
return data;
}
}
String name = "{click_action: FLUTTER_NOTIFICATION_CLICK, sendByImage: https://ujjwalchef.staging-server.in/uploads/users/1636620532.png, status: done, sendByName: mohittttt, id: HM11}";
List<String> str = name.replaceAll("{","").replaceAll("}","").split(",");
Map<String,dynamic> result = {};
for(int i=0;i<str.length;i++){
List<String> s = str[i].split(":");
result.putIfAbsent(s[0].trim(), () => s[1].trim());
}
print(result);
}
You must need to use this sometimes
Map<String, dynamic> toJson() {
return {
jsonEncode("phone"): jsonEncode(numberPhone),
jsonEncode("country"): jsonEncode(country),
};
}
This code give you a like string {"numberPhone":"+225657869", "country":"CI"}. So it's easy to decode it's after like that
json.decode({"numberPhone":"+22565786589", "country":"CI"})
You must import dart:encode libary. Then use the jsonDecode function, that will produce a dynamic similar to a Map
https://api.dartlang.org/stable/2.2.0/dart-convert/dart-convert-library.html
For converting string to JSON we have to modify it with custom logic, in here first we remove all symbols of array and object and then we split text with special characters and append with key and value(for map).
Please try this code snippet in dartpad.dev
import 'dart:developer';
void main() {
String stringJson = '[{product_id: 1, quantity: 1, price: 16.5}]';
stringJson = removeJsonAndArray(stringJson);
var dataSp = stringJson.split(',');
Map<String, String> mapData = {};
for (var element in dataSp) {
mapData[element.split(':')[0].trim()] = element.split(':')[1].trim();
}
print("jsonInModel: ${DemoModel.fromJson(mapData).toJson()}");
}
String removeJsonAndArray(String text) {
if (text.startsWith('[') || text.startsWith('{')) {
text = text.substring(1, text.length - 1);
if (text.startsWith('[') || text.startsWith('{')) {
text = removeJsonAndArray(text);
}
}
return text;
}
class DemoModel {
String? productId;
String? quantity;
String? price;
DemoModel({this.productId, this.quantity, this.price});
DemoModel.fromJson(Map<String, dynamic> json) {
log('json: ${json['product_id']}');
productId = json['product_id'];
quantity = json['quantity'];
price = json['price'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['product_id'] = productId;
data['quantity'] = quantity;
data['price'] = price;
return data;
}
}
Related
I'm trying to deserialize a json file and create instances from it but whatever way I use, I end up stucked because of the dynamic type :
type '_Map<String, dynamic>' is not a subtype of type 'Map<String, int>'
Here's my model :
class Race {
final String name;
final Map<String, int> abilitiesUpdater;
const Race({
required this.name,
required this.abilitiesUpdater
});
static fromJson(json) => Race(name: json['name'], abilitiesUpdater: json['abilitiesUpdater']);
}
Here's how I'm trying to deserialize the json file :
class RacesApi {
static Future<List<Race>> getRacesLocally(BuildContext context) async {
final assetBundle = DefaultAssetBundle.of(context);
final String fileContent = await assetBundle.loadString('Assets/COC_Monstres/Races.json');
List<dynamic> parsedListJson = jsonDecode(fileContent);
List<Race> racesList = List<Race>.from(parsedListJson.map<Race>((dynamic i) => Race.fromJson(i)));
return racesList;
}
}
Here's my json file :
[
{
"name": "Vampire",
"abilitiesUpdater": {
"DEX": 2,
"CHA": 2
}
},
{
"name": "Créature du lagon",
"abilitiesUpdater": {
"FOR": 2,
"CON": 2
}
},
...
]
How can I properly cast this json object to fit into my class ?
This works:
class Race {
final String name;
// changed to dynamic
final Map<String, dynamic> abilitiesUpdater;
const Race({required this.name, required this.abilitiesUpdater});
static fromJson(json) =>
Race(name: json['name'], abilitiesUpdater: json['abilitiesUpdater']);
}
Maybe after get the object you can parse that dynamic into int if you need it.
Change your Model Class to this:
class Race {
Race({
required this.name,
required this.abilitiesUpdater,
});
late final String name;
late final AbilitiesUpdater abilitiesUpdater;
Race.fromJson(Map<String, dynamic> json){
name = json['name'];
abilitiesUpdater = AbilitiesUpdater.fromJson(json['abilitiesUpdater']);
}
Map<String, dynamic> toJson() {
final _data = <String, dynamic>{};
_data['name'] = name;
_data['abilitiesUpdater'] = abilitiesUpdater.toJson();
return _data;
}
}
class AbilitiesUpdater {
AbilitiesUpdater({
required this.FOR,
required this.CON,
});
late final int FOR;
late final int CON;
AbilitiesUpdater.fromJson(Map<String, dynamic> json){
FOR = json['FOR'];
CON = json['CON'];
}
Map<String, dynamic> toJson() {
final _data = <String, dynamic>{};
_data['FOR'] = FOR;
_data['CON'] = CON;
return _data;
}
}
you can cast the json['abilitiesUpdater'] as Map<String, int> because internally flutter will set it default as Map<String, dynamic>
Code
class Race {
final String name;
final Map<String, int> abilitiesUpdater;
const Race({
required this.name,
required this.abilitiesUpdater
});
static fromJson(json) => Race(name: json['name'], abilitiesUpdater: json['abilitiesUpdater']) as Map<String,int>;
}
it is working fine with me i tried it here is the link to the code https://dartpad.dev/?id=550918b56987552eb3d631ce8cb9e063.
If you still getting error you can try this
class Race {
final String name;
final Map<String, int> abilitiesUpdater;
Race({
required this.name,
required this.abilitiesUpdater
});
static fromJson(json) => Race(name: json['name'], abilitiesUpdater: (json['abilitiesUpdater']as Map<String,int>)) ;
}
or you can try this
class Race {
final String name;
final Map<String, int> abilitiesUpdater;
const Race({required this.name, required this.abilitiesUpdater});
static fromJson(json) => Race(
name: json['name'],
abilitiesUpdater: json['abilitiesUpdater']
.map((key, value) => MapEntry<String, int>(key, value as int)),
);
}
Edit : To have something a little bit more handy and scalable, I created an extension, and it works fine eventhough I have to cast twice the object...
My model :
// import my extension
class Race {
Race({
required this.name,
required this.abilitiesUpdater,
});
late final String name;
late final Map<String, int> abilitiesUpdater;
// late final AbilitiesUpdater abilitiesUpdater;
Race.fromJson(Map<String, dynamic> json){
name = json['name'];
abilitiesUpdater = (json['abilitiesUpdater'] as Map<String, dynamic>).parseToStringInt();
}
}
My extension :
extension Casting on Map<String, dynamic> {
Map<String, int> parseToStringInt() {
final Map<String, int> map = {};
forEach((key, value) {
int? testInt = int.tryParse(value.toString());
if (testInt != null) {
map[key] = testInt;
} else {
debugPrint("$value can't be parsed to int");
}
});
return map;
}
}
Once again, any help on cleaning this is appreciated !
Original answer :
Thanks to Sanket Patel's answer, I ended up with a few changes that made my code works. However I'm pretty clueless on why I can't directly cast a
Map<String, dynamic>
object into a
Map<String, int>
one.
Any info on this would be appreciated :)
Here's how I changed my model class in the end :
class Race {
Race({
required this.name,
required this.abilitiesUpdater,
});
late final String name;
late final AbilitiesUpdater abilitiesUpdater;
Race.fromJson(Map<String, dynamic> json){
name = json['name'];
abilitiesUpdater = AbilitiesUpdater.fromJson(json['abilitiesUpdater']);
}
}
class AbilitiesUpdater {
final Map<String, int> abilitiesUpdater = {};
AbilitiesUpdater.fromJson(Map<String, dynamic> json){
json.forEach((key, value) {
abilitiesUpdater[key] = int.parse(value.toString());
});
}
}
the app.quicktype.io cannot convert.
they are converting and skip the digit class name
class ScoreCardModel {
bool? status;
String? msg;
Data? data;
ScoreCardModel({this.status, this.msg, this.data});
ScoreCardModel.fromJson(Map<String, dynamic> json) {
status = json['status'];
msg = json['msg'];
data = json['data'] = Data.fromJson(json['data']);
}
}
class Data {
String? result;
Scorecard? scorecard;
Data({this.result, this.scorecard});
Data.fromJson(Map<String, dynamic> json) {
result = json['result'];
scorecard = json['scorecard'] != null
? Scorecard.fromJson(json['scorecard'])
: null;
}
}
the quicktype cannot work with digits, I don't know why is this. I think they are in the developing stage. I Have the answer. I'm looking for the correct answer.
You can use https://jsontodart.com/, They are just including digit as model(Class) name. But You have to rename the model name like follows,
class 1 {
String score;
String wicket;
String ball;
1({this.score, this.wicket, this.ball});
1.fromJson(Map<String, dynamic> json) {
score = json['score'];
wicket = json['wicket'];
ball = json['ball'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['score'] = this.score;
data['wicket'] = this.wicket;
data['ball'] = this.ball;
return data;
}
}
to
class teamA {
String score;
String wicket;
String ball;
teamA({this.score, this.wicket, this.ball});
teamA.fromJson(Map<String, dynamic> json) {
score = json['score'];
wicket = json['wicket'];
ball = json['ball'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['score'] = this.score;
data['wicket'] = this.wicket;
data['ball'] = this.ball;
return data;
}
}
I have array of country json objects like this
[{"id":4,"name":"Afghanistan","alpha2":"af","alpha3":"afg"},
{"id":8,"name":"Albania","alpha2":"al","alpha3":"alb"},
{"id":12,"name":"Algeria","alpha2":"dz","alpha3":"dza"},..
I have got them to a map like this
Map<String, dynamic> jsonMap;
jsonMap = json.decode(jsonString);
After this I have the data like this
[{id: 4, name: Afghanistan, alpha2: af, alpha3: afg}, {id: 8, name: Albania, alpha2: al, alpha3: alb}, ...
What i want to do is create a List of county objects from this
Country
{
int id;
String name;
String alpha2;
String alpha3;
}
Can anyone explain how to do this conversion ?
The best way to do it is to make a PODO out of this,
class Country {
int id;
String name;
String alpha2;
String alpha3;
Country({this.id, this.name, this.alpha2, this.alpha3});
Country.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
alpha2 = json['alpha2'];
alpha3 = json['alpha3'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['name'] = this.name;
data['alpha2'] = this.alpha2;
data['alpha3'] = this.alpha3;
return data;
}
}
Now using this you can access the fromJson method and also use the toJson method.
I use this straight forward way:
List<TestModel> myTestModel;
var response = await http.get("myTestUrl");
myTestModel=(json.decode(response.body) as List).map((i) =>
TestModel.fromJson(i)).toList();
The link can be really helpful:
json_serializable
I have created one model like this :
class SalesRepResponse {
bool errors;
List<Data> data;
int statusCode;
SalesRepResponse({this.errors, this.data, this.statusCode});
SalesRepResponse.fromJson(Map<String, dynamic> json) {
errors = json['errors'];
if (json['data'] != null) {
data = new List<Data>();
json['data'].forEach((v) {
data.add(new Data.fromJson(v));
});
}
statusCode = json['status_code'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['errors'] = this.errors;
if (this.data != null) {
data['data'] = this.data.map((v) => v.toJson()).toList();
}
data['status_code'] = this.statusCode;
return data;
}
}
class Data {
int id;
String displayName;
Data({this.id, this.displayName});
Data.fromJson(Map<String, dynamic> json) {
id = json['id'];
displayName = json['display_name'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['display_name'] = this.displayName;
return data;
}
}
And i get the same response from API also and i parse data like this :
var result = SalesRepResponse.fromJson(json.decode(response1.body));
But it stores all the value in SalesRepResponse/Data class as null.
Someone please help me with this.
Thanks in advance.
you have to specify the data in your json like this
var result = SalesRepResponse.fromJson(json.decode(response1.body['data/etc']));
mean that u have to specify the data which have data for SalesRepResponse by checking your json response
As for the script below, I have two different json for single record and multiple record as a list. I can parse the single data using the Person class. For the json with a list, I'm using ther PersonList class but I'm getting an error because the json key result is not needed anymore. Is there a way to parse the list without changing the Person class? Or should I not use the PersonList class and just create a List<Person>?
I saw this example but its only working if the json is a whole list like this
var jsonResponse = convert.jsonDecode(rawJsonMulti) as List;
return jsonResponse.map((p) => Person.fromJson(p).toList();
Can you show me how to use the above script using my json. Thanks.
import 'dart:convert';
void main() {
String rawJsonMulti = '{"result": [{"name":"Mary","age":30},{"name":"John","age":25}]}';
String rawJsonSingle = '{"result": {"name":"Mary","age":30}}';
// Working for non list json
// final result = json.decode(rawJsonSingle);
// var obj = Person.fromJson(result);
// print(obj.name);
final result = json.decode(rawJsonMulti);
var obj = PersonList.fromJson(result);
print(obj.listOfPerson[0].name);
}
class PersonList {
final List<Person> listOfPerson;
PersonList({this.listOfPerson});
factory PersonList.fromJson(Map<String, dynamic> json) {
var personFromJson = json['result'] as List;
List<Person> lst =
personFromJson.map((i) => Person.fromJson(i)).toList();
return PersonList(listOfPerson: lst);
}
}
class Person {
String name;
int age;
//will only work on result is not a list
Person({this.name, this.age});
factory Person.fromJson(Map<String, dynamic> json) {
return Person(name: json['result']['name'],
age: json['result']['age']);
}
// This will work on json with list but not in single
// factory Person.fromJson(Map<String, dynamic> json) {
// return Person(name: json['name'],
// age: json['age']);
// }
}
If you convert the dynamic to a List<dynamic> you can map each element in the jsonDecoded list.
Example:
import 'dart:convert';
final decodedJson = jsonDecode(rawJsonMulti) as List<dynamic>;
final personList = decodedJson
.map((e) => Person.fromJson(
e as Map<String, dynamic>))
.toList();
return PersonList(listOfPerson: personList);
```
Try take a look at this solution where I have fixed your code:
import 'dart:convert';
void main() {
const rawJsonMulti =
'{"result": [{"name":"Mary","age":30},{"name":"John","age":25}]}';
const rawJsonSingle = '{"result": {"name":"Mary","age":30}}';
final resultMulti = json.decode(rawJsonMulti) as Map<String, dynamic>;
final personListMulti = PersonList.fromJson(resultMulti);
print(personListMulti.listOfPerson[0]); // Mary (age: 30)
print(personListMulti.listOfPerson[1]); // John (age: 25)
final resultSingle = json.decode(rawJsonSingle) as Map<String, dynamic>;
final personListSingle = PersonList.fromJson(resultMulti);
print(personListSingle.listOfPerson[0]); // Mary (age: 30)
}
class PersonList {
final List<Person> listOfPerson;
PersonList({this.listOfPerson});
factory PersonList.fromJson(Map<String, dynamic> json) {
if (json['result'] is List) {
final personsFromJson = json['result'] as List;
return PersonList(listOfPerson: [
...personsFromJson
.cast<Map<String, Object>>()
.map((i) => Person.fromJson(i))
]);
} else {
final personFromJson = json['result'] as Map<String, Object>;
return PersonList(listOfPerson: [Person.fromJson(personFromJson)]);
}
}
}
class Person {
String name;
int age;
Person({this.name, this.age});
factory Person.fromJson(Map<String, dynamic> json) {
return Person(name: json['name'] as String, age: json['age'] as int);
}
#override
String toString() => '$name (age: $age)';
}