Difficulty in parsing JSON - flutter

I want to develop a flutter app and I am finding it difficult to parse this JSON I have seen posts regarding this but I am finding it difficult to parse this. Help a beginner out! Here is the JSON link " https://api.covid19india.org/state_district_wise.json "
I am simply using:
Future getJsonDistrictData() async {
var response = await http.get(Uri.encodeFull(url1));
var converttojson1 = json.decode(response.body);
setState(() {
myData= converttojson1;
});
}
Text("${myData['Kerala']['districtData']['Thrissur']['confirmed']}")
But this would mean I have to write the same line for every district confirmed cases.
How should I proceed?

I have made the following example of an implementation you can use the parse the data from the URL in your question.
It can be simplified if you don't need the lastUpdatedTime and delta_confirmed since it looks like this is always the empty String and zero in the API.
import 'dart:convert';
class State {
final Map<String, DistrictData> districts = {};
State.fromJson(dynamic json) {
for (final district in json['districtData'].keys) {
districts[district as String] =
DistrictData.fromJson(json['districtData'][district]);
}
}
#override
String toString() => districts.toString();
}
class DistrictData {
final int confirmed;
final DateTime lastUpdatedTime;
final int delta_confirmed;
DistrictData(this.confirmed, this.lastUpdatedTime, this.delta_confirmed);
factory DistrictData.fromJson(dynamic json) => DistrictData(
json['confirmed'] as int,
(json['lastupdatedtime'].isEmpty as bool)
? null
: (DateTime.parse(json['lastupdatedtime'] as String)),
json['delta']['confirmed'] as int);
#override
String toString() =>
'{ confirmed: $confirmed, lastUpdatedTime: $lastUpdatedTime, delta_confirmed: $delta_confirmed }';
}
void main() {
final states = json.decode(input).map(
(String key, dynamic value) => MapEntry(key, State.fromJson(value)))
as Map<String, State>;
states.forEach((key, value) => print('$key : $value'));
/*
Kerala : {Thrissur: { confirmed: 13, lastUpdatedTime: null, delta_confirmed: 0 }, Alappuzha: { confirmed: 5, lastUpdatedTime: null, delta_confirmed: 0 }}
Delhi : {East Delhi: { confirmed: 1, lastUpdatedTime: null, delta_confirmed: 0 }}
*/
}
const input = '''
{
"Kerala": {
"districtData": {
"Thrissur": {
"confirmed": 13,
"lastupdatedtime": "",
"delta": {
"confirmed": 0
}
},
"Alappuzha": {
"confirmed": 5,
"lastupdatedtime": "",
"delta": {
"confirmed": 0
}
}
}
},
"Delhi": {
"districtData": {
"East Delhi": {
"confirmed": 1,
"lastupdatedtime": "",
"delta": {
"confirmed": 0
}
}
}
}
}
''';

Copy your JSON in this link(https://javiercbk.github.io/json_to_dart/) and get model Class.
Example:
For example your Model Class Name is CovidModel. As you get response from network call, pass data to you model class and get object like this:
CovidModel _covidModel = CovidModel.fromJson(response.data);
now you can use _covidModel to get inner objects and show result in app page.

Related

Cast to model List<Map<String,dynamic>> issue flutter

I want convert my response API to model repository in flutter but always get error in type of model
use Dio for api request
this is my response API :
{
"success": 1,
"list": [
{
"id": "1",
"driver_id": "11081",
"company_id": "9",
"school_id": "4",
"status": 1,
"createdAt": "2022-10-14T09:22:00.000Z",
"updatedAt": "2022-10-14T09:22:03.000Z"
},
{
"id": "2",
"driver_id": "11081",
"company_id": "9",
"school_id": "5",
"status": 1,
"createdAt": "2022-10-14T20:36:47.000Z",
"updatedAt": "2022-10-14T20:36:49.000Z"
}
]
}
I try get data like this :
Future<List<ServiceEntity>> getAll() async {
final List<ServiceEntity> services = [];
try {
final response = await httpClient.post("v1/teacher/get-list");
validateResponse(response);
(response.data['list'] as List).forEach((jsonObject) {
services.add(ServiceEntity.fromJson(jsonObject));
});
} on DioError catch (e) {
exceptionHttpRequest(e);
}
return services;
}
and model is :
class ServiceEntity {
final int id;
ServiceEntity.fromJson(Map<String, dynamic> json)
: id = json['id'];
}
When i build app and debug always get this error :
I/flutter (29931):
type 'String' is not a subtype of type 'int'
I test many things but in fact did not understand what is the issue
The problem is exactly what the error says. String is not a subtype of int.
Look at the data:
The "id" is stored as a String.
Then you try pull it out in the ServiceEntitys fromJson to an int.
a. Either just store the value as an int, because that's what it is, just b like the success field.
b. or parse the string into an int.
Below an example with chatty printing to explain the type changes.
const data = {
"id": "1",
};
try{
// value stored as a String
final value = data["id"] as String;
print(value.runtimeType);
print(value);
// parse into an int
final id = int.tryParse(value);
print(id.runtimeType);
print(id);
}catch(e){
print("ERROR ${e}");
}
Your id data type is String on response, to use it as int on model class you can parse to int,
id = int.tryParse(json['id']) ?? 0;
if parser failed, it will get 0.
More about converting json and tryParse

How to map a json list in flutter using JSONSerializable

I am trying to map a json list in my application using JSON Serializable. But I am not able to map it.
Following is the response from the API:
{
"code": 200,
"message": "Countries Lists",
"count": 250,
"data": [
{
"id": 1,
"name": "Afghanistan"
},
{
"id": 2,
"name": "Aland Islands"
},
{
"id": 3,
"name": "Albania"
},
{
"id": 4,
"name": "Algeria"
},
{
"id": 5,
"name": "American Samoa"
},
{
"id": 6,
"name": "Andorra"
},
{
"id": 7,
"name": "Angola"
},
{
"id": 8,
"name": "Anguilla"
},
{
"id": 9,
"name": "Antarctica"
},
{
"id": 10,
"name": "Antigua And Barbuda"
},
{
"id": 11,
"name": "Argentina"
},
{
"id": 12,
"name": "Armenia"
},
{
"id": 13,
"name": "Aruba"
},
{
"id": 14,
"name": "Australia"
},
{
"id": 15,
"name": "Austria"
},
{
"id": 16,
"name": "Azerbaijan"
},
{
"id": 17,
"name": "Bahamas The"
},
{
"id": 18,
"name": "Bahrain"
},
{
"id": 19,
"name": "Bangladesh"
},
{
"id": 20,
"name": "Barbados"
}
]
}
Following is my response file:
#JsonSerializable()
class BaseResponse {
#JsonKey(name: "code")
int? status;
#JsonKey(name: "message")
String? message;
}
#JsonSerializable(explicitToJson: true)
class AllCountryResponse extends BaseResponse {
#JsonKey(name: "data")
List<CountryResponse> data;
AllCountryResponse(this.data);
//from JSON
factory AllCountryResponse.fromJson(Map<String, dynamic> json) =>
_$AllCountryResponseFromJson(json);
//to JSON
Map<String, dynamic> toJson() => _$AllCountryResponseToJson(this);
}
#JsonSerializable()
class CountryResponse {
#JsonKey(name: "id")
String? id;
#JsonKey(name: "name")
String? name;
CountryResponse(this.id, this.name);
//from JSON
factory CountryResponse.fromJson(Map<String, dynamic> json) =>
_$CountryResponseFromJson(json);
//to JSON
Map<String, dynamic> toJson() => _$CountryResponseToJson(this);
}
I am able to generate the responses.g dart file.
Following is my mapper class file:
class Countries {
String id,name;
Countries(this.id,this.name);
}
class AllCountries{
List<Countries> countries;
AllCountries(this.countries);
}
extension CountryResponseMapper on CountryResponse? {
Countries toDomain() {
return Countries(
this?.id.orEmpty() ?? EMPTY, this?.name.orEmpty() ?? EMPTY);
}
}
extension AllCountriesResponseMapper on AllCountryResponse? {
AllCountries toDomain() {
return AllCountries(this?.data.map((e) => e.toDomain()).toList() ?? []);
}
}
Once I run my api I do get 200 status while using my bio, but after that it shows me the default error I have set, i.e. "Something went wrong". Which means there is an issue in mapping the response.
Can someone help me with mapping this list please?
This code should work.
This code is generated by a very small and simple script (which was written in a few minutes).
class Response {
Response(
{required this.code,
required this.message,
required this.count,
required this.data});
factory Response.fromJson(Map json) {
return Response(
code: json['code'] as int?,
message: json['message'] as String?,
count: json['count'] as int?,
data: json['data'] == null
? []
: (json['data'] as List).map((e) => Data.fromJson(e as Map)).toList(),
);
}
final int? code;
final String? message;
final int? count;
final List<Data> data;
static List<Response> fromJsonList(List json) {
return json.map((e) => Response.fromJson(e as Map)).toList();
}
Map<String, dynamic> toJson() {
return {
'code': code,
'message': message,
'count': count,
'data': data.map((e) => e.toJson()).toList(),
};
}
static List<Map<String, dynamic>> toJsonList(List<Response> list) {
return list.map((e) => e.toJson()).toList();
}
}
class Data {
Data({required this.id, required this.name});
factory Data.fromJson(Map json) {
return Data(
id: json['id'] == null ? 0 : json['id'] as int,
name: json['name'] == null ? '' : json['name'] as String,
);
}
final int id;
final String name;
static List<Data> fromJsonList(List json) {
return json.map((e) => Data.fromJson(e as Map)).toList();
}
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
};
}
static List<Map<String, dynamic>> toJsonList(List<Data> list) {
return list.map((e) => e.toJson()).toList();
}
}
Code generation script:
import 'dart:io';
import 'package:object_serializer/json_serializer_generator.dart';
import 'package:yaml/yaml.dart';
void main() {
final classes = loadYaml(_classes) as Map;
final g = JsonSerializerGenerator();
final classesCode = g.generateClasses(classes);
final values = {
'classes': classesCode,
};
var source = g.render(_template, values);
source = g.format(source);
File('bin/stackoverflow.dart').writeAsStringSync(source);
}
const _classes = r'''
Response:
fields:
code: int?
message: String?
count: int?
data: List<Data>
Data:
fields:
id: int
name: String
''';
const _template = r'''
{{classes}}
''';

how can get dynamic key json in flutter

"
success": true,
"result": {
"values": {
"asdf": [],
"dj": [
{
"id": 18,
"ownerId": "5b0b3932-e262-4ac4-923c-13daf2bd4a3c",
"ownerName": "tester",
"name": "masr",
"description": "she was and firebase have also had to make their decision and make the beg to 8be 8the 8same 6th 7century 8of 8and 6and 88th century ones in flutter take on my favourite ",
"statusId": "PENDING",
"status": null,
"price": 9000.00,
"isPublic": false,
"startDate": "2022-05-26T00:00:00",
"expectedEndDate": "2022-05-27T00:00:00",
"finishDate": null,
"interests": [
{
"id": "my-first-interest",
"isDeleted": false
},
{
"id": "gdg",
"isDeleted": false
},
{
"id": "dj",
"isDeleted": false
}
]
},
]
}
}
the dynamic key is asdf and dj change form user to anoter
i want to get id or ownername .... etc without object can any one help me in this cause
Since you don't know the key name in advance, you will have to iterate over all of them looking for JSON object members that look like they contain ID and owner. Something like this:
import 'dart:convert';
import 'dart:io';
void main() {
final decoded = json.decode(File('json1.json').readAsStringSync());
// values will be a JSON object
final values = decoded['result']['values'] as Map<String, dynamic>;
// values.values will be all of the JSON arrays in that object
// do a whereType just to rule out any other fields in the JSON object
// use expand to merge all lists together
// and wheretype again to double check that we only have JSON objects
// further check that only JSON objects with the right values are selected
// and map these to PODOs
final result = values.values
.whereType<List>()
.expand((e) => e)
.whereType<Map>()
.where((e) => e.containsKey('id') && e.containsKey('ownerId'))
.map<IdAndOwner>((m) => IdAndOwner(m['id'], m['ownerId']))
.toList();
print(result); // prints [Id/OwnerId=18/5b0b3932-e262-4ac4-923c-13daf2bd4a3c]
}
class IdAndOwner {
final int id;
final String ownerId;
IdAndOwner(this.id, this.ownerId);
#override
String toString() => 'Id/OwnerId=$id/$ownerId';
}

Push array into list flutter

So i'm trying to create a list with objects of type 'MessageListItem'. I'm trying to push data returned from my API into the list. The variable I want it pushed into is 'messages'. I am getting an error in the 'getMessages()' function.
The error I am getting is: A value of type 'MessageListItem' can't be assigned to a variable of type 'List'.
The API call & code is:
List<MessageListItem> messages;
getMessages() async {
List<MessageListItem> res = MessageListItem.fromJson(await getMessageList());
// I'm getting the error on the line above.
print(res);
}
Future<dynamic> getMessageList() async {
final response = await http.get(baseUrl + 'message/jxchumber');
print(response.statusCode);
if (response.statusCode == 200) {
var res = json.decode(response.body);
return res;
} else {
throw Exception('Failed to get data');
}
}
MessageListItem Class
class MessageListItem {
int id;
int senderId;
int recipientId;
String senderUsername;
String recipientUsername;
int itemId;
String messageContentString;
bool read;
dynamic dateTimeSent;
MessageListItem(
{this.id,
this.senderId,
this.recipientId,
this.senderUsername,
this.recipientUsername,
this.itemId,
this.messageContentString,
this.read,
this.dateTimeSent});
factory MessageListItem.fromJson(Map<String, dynamic> json) {
return MessageListItem(
id: json['id'],
senderId: json['senderId'],
recipientId: json['recipientId'],
senderUsername: json['senderUsername'],
recipientUsername: json['recipientUsername'],
itemId: json['itemId'],
messageContentString: json['messageContentString'],
read: json['read'],
dateTimeSent: json['dateTimeSent'],
);
}
}
The data being returned from the API is:
[
{
"id": 4,
"senderId": 1,
"recipientId": 3,
"senderUsername": "jxchumber",
"recipientUsername": "pavster31",
"itemId": 0,
"messageContentString": "hello1",
"read": false,
"dateTimeSent": "2020-12-14T22:23:55.1473414"
},
{
"id": 3,
"senderId": 1,
"recipientId": 9,
"senderUsername": "jxchumber",
"recipientUsername": "larsen",
"itemId": 0,
"messageContentString": "hello1",
"read": false,
"dateTimeSent": "2020-12-14T16:04:50.8232055"
}
]
I'm trying to push it into the variable 'messages'
Try this
getMessages() async {
var list = await getMessageList();
List<MessageListItem> res = list.map((i)=>MessageListItem.fromJson(i)).toList();
}

How to handle difference responses API?

How to handle the difference between the results of a successful and failed fire response?
RESPONSE SUCCESS:
{
"header":{
"status":true,
"respcode":"00",
"message":"Successfully."
},
"data":{
"userid":"3485345",
"password":"3423424",
"bit18":"0000",
}
}
RESPONSE FAILED:
{
"header":{
"status":false,
"respcode":"01",
"message":"Userid Tidak Terdaftar"
},
"data":""
}
assuming you'll always have headers in your responses, you can do something like this:
Map<String, dynamic> res1 = {
"header": {"status": true, "respcode": "00", "message": "Successfully."},
"data": {
"userid": "3485345",
"password": "3423424",
"bit18": "0000",
}
};
Map<String, dynamic> res2 = {
"header": {
"status": false,
"respcode": "01",
"message": "Userid Tidak Terdaftar"
},
"data": ""
};
// bla = res2 for failed case
final bla = res1;
if (bla['header']['status']) {
print(res1['data']['userid']);
// do your success code here
} else {
// do your fail code here
print('fail');
}
I don't know why in the failed case, data is string (and not object). In theory, the failed case should have an empty object instead of a string. Any way, assuming you don't have control over the server's response, you might want to do something like below :
(The first two lines I wrote just to make sure the parsing works.)
Map<String, dynamic> mData = {
"header":{
"status":true,
"respcode":"00",
"message":"Successfully."
},
"data":{
"userid":"3485345",
"password":"3423424",
"bit18":"0000",
}
};
String jData = json.encode(mData);
Map<String, dynamic> decodedBody = json.decode(jData);
print(decodedBody["header"]["respcode"]); // prints 00
if (decodedBody['header']['status'])
{
User user = User.fromJson(decodedBody['data']);
print(user.userId); // This prints 3485345
}
else {
// login failed
}
And the User model is defined as below :
class User {
final String userId;
final String password;
final String bit18;
User({#required this.userId, #required this.password, this.bit18});
User.fromJson(Map json)
: this.userId = json['userid'],
this.password = json['password'],
this.bit18 = json['bit18'];
}