Hi guys I have an api I use that responds like this:
responds
{
"RAW": {
"BTC": {
"USD": {
"TYPE": "5",
"MARKET": "CCCAGG",
"FROMSYMBOL": "BTC",
"TOSYMBOL": "USD",
"FLAGS": "1026",
"PRICE": 41091.49,
"LASTUPDATE": 1649873443,
"MEDIAN": 41085.18,
"LASTVOLUME": 0.001056,
"LASTVOLUMETO": 43.38595008,
Now to convert and use it in darts (modeling) we have to do the mapping operation, right? Does anyone know how to do this when this response is nested! I did it, but I know it's not right
My code
class CryptoEntity {
final String basecode;
// final String targetcod;
final int price;
final int volume;
final int change;
CryptoEntity.fromjason(Map<String, dynamic> jason)
: basecode = jason['FROMSYMBOL'],
// targetcod = jason['target'],
price = jason['PRICE'],
volume = jason['VOLUMEDAY'],
change = jason['LASTVOLUME'];
}
Use freezed package and json serializable for code generation, it is good for the long term development but this requires basic knowledge in flutter.
Use Online JSON to Dart converter, this site generates null safety dart class. With this solution, all you need is to change the class names after each conversion manually, and note for the fromJson factory constructor method and toJson class method.
try this:
class CryptoEntity {
final String? basecode; // ? => means that this field can be null
// final String targetcod;
final int? price;
final int? volume;
final int? change;
//constroctor
CryptoEntity(this.basecode, this.price, .. );
factory CryptoEntity.fromjason(Map<String, dynamic> jason){
return CryptoEntity(
price = jason['PRICE'],
volume = jason['VOLUMEDAY'],
change = jason['LASTVOLUME'];
);
}
}
You can turn the json into an object
import 'dart:convert';
MyModel myModelFromMap(String str) => MyModel.fromMap(json.decode(str));
String myModelToMap(MyModel data) => json.encode(data.toMap());
class MyModel {
MyModel({
required this.raw,
});
Raw raw;
factory MyModel.fromMap(Map<String, dynamic> json) => MyModel(
raw: Raw.fromMap(json["RAW"]),
);
Map<String, dynamic> toMap() => {
"RAW": raw.toMap(),
};
}
class Raw {
Raw({
required this.btc,
});
Btc btc;
factory Raw.fromMap(Map<String, dynamic> json) => Raw(
btc: Btc.fromMap(json["BTC"]),
);
Map<String, dynamic> toMap() => {
"BTC": btc.toMap(),
};
}
class Btc {
Btc({
required this.usd,
});
Usd usd;
factory Btc.fromMap(Map<String, dynamic> json) => Btc(
usd: Usd.fromMap(json["USD"]),
);
Map<String, dynamic> toMap() => {
"USD": usd.toMap(),
};
}
class Usd {
Usd({
required this.type,
required this.market,
required this.fromsymbol,
required this.tosymbol,
required this.flags,
required this.price,
required this.lastupdate,
required this.median,
required this.lastvolume,
required this.lastvolumeto,
});
String type;
String market;
String fromsymbol;
String tosymbol;
String flags;
double price;
int lastupdate;
double median;
double lastvolume;
double lastvolumeto;
factory Usd.fromMap(Map<String, dynamic> json) => Usd(
type: json["TYPE"],
market: json["MARKET"],
fromsymbol: json["FROMSYMBOL"],
tosymbol: json["TOSYMBOL"],
flags: json["FLAGS"],
price: json["PRICE"].toDouble(),
lastupdate: json["LASTUPDATE"],
median: json["MEDIAN"].toDouble(),
lastvolume: json["LASTVOLUME"].toDouble(),
lastvolumeto: json["LASTVOLUMETO"].toDouble(),
);
Map<String, dynamic> toMap() => {
"TYPE": type,
"MARKET": market,
"FROMSYMBOL": fromsymbol,
"TOSYMBOL": tosymbol,
"FLAGS": flags,
"PRICE": price,
"LASTUPDATE": lastupdate,
"MEDIAN": median,
"LASTVOLUME": lastvolume,
"LASTVOLUMETO": lastvolumeto,
};
}
You can use it like this
MyModel myModel = myModelFromMap(jsonDecode(json));
https://app.quicktype.io/
Related
Greetings
I am having this problem converting the following json to TodayWeather Entity:
How can I use the named constructor TodayHours?
I've been looking for a solution for this issue for a few days now, but I haven't found much, please guide me.
json:
{
"days": [
{
"datetime": "2023-01-05",
"datetimeEpoch": 1672864200,
"tempmax": 8.8,
"tempmin": 2.3,
"temp": 5.3,
"windspeed": 8.6,
"winddir": 223.9,
"visibility": 19.7,
"sunrise": "06:43:43",
"sunset": "16:30:24",
"conditions": "Snow, Rain, Overcast",
"hours": [
{
"datetime": "00:00:00",
"datetimeEpoch": 1672864200,
"temp": 4.4,
"humidity": 27.65,
"windspeed": 6.5,
"winddir": 249.2,
"visibility": 24.1,
"conditions": "Partially cloudy"
},
{
"datetime": "01:00:00",
"datetimeEpoch": 1672864200,
"temp": 4.4,
"humidity": 27.65,
"windspeed": 6.5,
"winddir": 249.2,
"visibility": 24.1,
"conditions": "Partially cloudy"
}
]
}
]
}
and my TodayWeather Entitiy is :
class TodayWeather {
final String datetime;
final num dateEpoch;
final String conditions;
final num tempMax;
final num tempMin;
final num windDir;
final num windSpeed;
final String sunRise;
final String sunSet;
final num humidity;
final num visibility;
final List<TodayHourse> hours;
TodayWeather.fromJson(Map<String, dynamic> json)
: datetime = json['days'][0]['datetime'],
dateEpoch = json['days'][0]['datetimeEpoch'],
conditions = json['days'][0]['conditions'],
tempMax = json['days'][0]['tempmax'],
tempMin = json['days'][0]['tempmin'],
windDir = json['days'][0]['winddir'],
windSpeed = json['days'][0]['windspeed'],
sunRise = json['days'][0]['sunrise'],
sunSet = json['days'][0]['sunset'],
humidity = json['days'][0]['humidity'],
visibility = json['days'][0]['visibility'],
hours = List<TodayHourse>.from(
json['days'][0]['hours'].map((x) => x.toJson())).toList();
}
and my TodayHours Entitiy is :
class TodayHourse {
final String datetime;
final num dateEpoch;
final String conditions;
final num temp;
final num windDir;
final num windSpeed;
final num humidity;
final num visibility;
Map<String, dynamic> toJson() => {
'datetime': datetime,
'datetimeEpoch': dateEpoch,
'conditions': conditions,
'temp': temp,
'winddir': windDir,
'windspeed': windSpeed,
'humidity': humidity,
'visibility': visibility
};
TodayHourse.fromJson(Map<String, dynamic> json)
: datetime = json['days'][0]['datetime'],
dateEpoch = json['days'][0]['datetimeEpoch'],
conditions = json['days'][0]['conditions'],
temp = json['days'][0]['temp'],
windDir = json['days'][0]['winddir'],
windSpeed = json['days'][0]['windspeed'],
humidity = json['days'][0]['humidity'],
visibility = json['days'][0]['visibility'];
}
this method is parsing Json to TodayWeather:
#override
Future<TodayWeather> getTodayWeather() async {
final response = await httpClient.get(
'36.31559%2C59.56796/today?unitGroup=metric&key=Key&contentType=json');
validResponse(response);
return TodayWeather.fromJson(response.data);
}
First change your TodayHourse.fromJson to this:
TodayHourse.fromJson(Map<String, dynamic> json)
: datetime = json['datetime'],
dateEpoch = json['datetimeEpoch'],
conditions = json['conditions'],
temp = json['temp'],
windDir = json['winddir'],
windSpeed = json['windspeed'],
humidity = json['humidity'],
visibility = json['visibility'];
your hours is list of Map and you don't need to use json['days'][0]. Then in your TodayWeather.fromJson, change hours to this:
hours = (json['days'][0]['hours'] as List).map((x) => TodayHourse.fromJson(x)).toList();
you are using wrong function instead of toJson, you need to call TodayHourse.fromJson(x).
Try to use this model:
class TodayWeather {
TodayWeather({required this.days});
final List<Day> days;
factory TodayWeather.fromJson(Map<String, dynamic> json) => TodayWeather(
days: List<Day>.from(json["days"].map((x) => Day.fromJson(x))),
);
}
class Day {
Day({
required this.datetime,
required this.datetimeEpoch,
required this.tempmax,
required this.tempmin,
required this.temp,
required this.windspeed,
required this.winddir,
required this.visibility,
required this.sunrise,
required this.sunset,
required this.conditions,
required this.hours,
});
final DateTime datetime;
final int datetimeEpoch;
final double tempmax, tempmin, temp, windspeed, winddir, visibility;
final String sunrise, sunset, conditions;
final List<Hour> hours;
factory Day.fromJson(Map<String, dynamic> json) => Day(
datetime: DateTime.parse(json["datetime"]),
datetimeEpoch: json["datetimeEpoch"],
tempmax: json["tempmax"].toDouble(),
tempmin: json["tempmin"].toDouble(),
temp: json["temp"].toDouble(),
windspeed: json["windspeed"].toDouble(),
winddir: json["winddir"].toDouble(),
visibility: json["visibility"].toDouble(),
sunrise: json["sunrise"],
sunset: json["sunset"],
conditions: json["conditions"],
hours: List<Hour>.from(json["hours"].map((x) => Hour.fromJson(x))),
);
}
class Hour {
Hour({
required this.datetime,
required this.datetimeEpoch,
required this.temp,
required this.humidity,
required this.windspeed,
required this.winddir,
required this.visibility,
required this.conditions,
});
final int datetimeEpoch;
final double temp, humidity, windspeed, winddir, visibility;
final String datetime, conditions;
factory Hour.fromJson(Map<String, dynamic> json) => Hour(
datetime: json["datetime"],
datetimeEpoch: json["datetimeEpoch"],
temp: json["temp"].toDouble(),
humidity: json["humidity"].toDouble(),
windspeed: json["windspeed"].toDouble(),
winddir: json["winddir"].toDouble(),
visibility: json["visibility"].toDouble(),
conditions: json["conditions"],
);
}
First of all for more clear way to parse JSON arrays you can create helper method in your models, I call it Model.fromJsonList
static List<WeatherDay> fromJsonList(dynamic jsonList) {
if (jsonList == null || jsonList.isEmpty) return [];
return (jsonList as List).map((e) => WeatherDay.fromJson(e)).toList();
}
So by this method you can parse array response very easy and clean for example:
Future<WeatherDay> fetchTodayWeather() async {
final response = await httpClient.get(
'36.31559%2C59.56796/today?unitGroup=metric&key=Key&contentType=json');
final List<WeatherDay> weatherDays = WeatherDay.fromJsonList(response.data["days"]);
return weatherDays.first;
}
Totally we have:
class WeatherDay {
WeatherDay( {
#required this.datetime,
#required this.hours,
});
final String datetime;
final List<WeatherHour> hours;
factory WeatherDay.fromJson(Map<String, dynamic> json) {
return WeatherDay(
datetime: json['datetime'] as String,
hours: WeatherHour.fromJsonList(json['hours']),
);
}
static List<WeatherDay> fromJsonList(dynamic jsonList) {
if (jsonList == null || jsonList.isEmpty) return [];
return (jsonList as List).map((e) => WeatherDay.fromJson(e)).toList();
}
}
class WeatherHour {
WeatherHour( {
#required this.dateEpoch,
#required this.conditions,
});
final num dateEpoch;
final String conditions;
factory WeatherHour.fromJson(Map<String, dynamic> json) {
return WeatherHour(
dateEpoch: json['datetimeEpoch'] as num,
conditions: json['conditions'] as String,
);
}
static List<WeatherHour> fromJsonList(dynamic jsonList) {
if (jsonList == null || jsonList.isEmpty) return [];
return (jsonList as List).map((e) => WeatherHour.fromJson(e)).toList();
}
}
Note: I didn't parse all variable, do it by yourself.
I can't figure out how to decode a JSON to a specific Map.
First of all I have a map that stores the date as the map key, and the value is a list of objects.
I also made custom methods to convert the objects to JSON.
The class model for the list of objects is:
class Task {
late int taskId;
late bool isCompleted;
late String text;
late PriorityItem priority;
Map<String, dynamic> toJson() =>
{
"id": taskId,
"isCompleted": isCompleted,
"text": text,
"priority": priority.toString(),
};
factory Task.fromJson(Map<String, dynamic> json) =>
Task(
json["isCompleted"],
taskId:json["id"],
text: json["text"],
priority: json["priority"]);
}
enum PriorityItem{
low,
medium,
high
}
The map is stored inside another class called TaskList as
static LinkedHashMap<DateTime, List<Task>> weeklyTaskMap = LinkedHashMap<DateTime, List<Task>>();
static Map<String, dynamic> toJson(LinkedHashMap<DateTime, List<Task>> taskMap) {
Map<String, dynamic> myMap = {};
taskMap.forEach((key, value) {
myMap[key.toIso8601String()] = List<dynamic>.from(value.map((x) => x.toJson()));
});
return myMap;
}
static LinkedHashMap<DateTime, List<Task>> fromJson(Map<String, dynamic> json) {
LinkedHashMap<DateTime, List<Task>> myMap = {} as LinkedHashMap<DateTime, List<Task>>;
json.forEach((key, value) {
myMap[DateTime.parse(key)] = List<Task>.from(json[value]
.map((x) => Task.fromJson(value)));
});
return myMap;
}
Encoding the map to JSON is working just fine, this would be an output after encoding the map:
{
"2022-11-14T15:38:52.879009": [
{
"id": 0,
"isCompleted": false,
"text": "how to get rid ",
"priority": "PriorityItem.medium"
},
{
"id": 1,
"isCompleted": false,
"text": "good morning and I ",
"priority": "PriorityItem.low"
}
],
"2022-11-15T00:00:00.000Z": [
{
"id": 2,
"isCompleted": false,
"text": "how to get rid of the ",
"priority": "PriorityItem.high"
}
]
}
Methods used to encode and decode:
void getMapsFromPrefs() async {
SharedPreferences getMaps = await _prefs;
Map dailyMap = TaskList.fromJson(jsonDecode(getMaps.getString('daily')!));
LinkedHashMap<DateTime, List<Task>> weeklyMap = jsonDecode(getMaps.getString('weekly')!);
TaskList.taskMap = dailyMap;
TaskList.weeklyTaskMap = weeklyMap;
}
void saveMapsToPrefs() async {
SharedPreferences getMaps = await _prefs;
getMaps.clear();
var dailyTasksJson = json.encode(TaskList.toJson(TaskList.taskMap));
var weeklyTasksJson = json.encode(TaskList.toJson(TaskList.weeklyTaskMap));
getMaps.setString('daily', dailyTasksJson);
getMaps.setString('weekly', weeklyTasksJson);
print("saved ${getMaps.getString('daily')}");
}
The only problem I have is decoding the JSON to my desired Map.
I hope this is understandable, if anyone needs extra information please feel free to ask :)
Thank you.
A possible quick fix could be updating your .fromJSON class method, it looks like you forgot the isCompleted field.
factory Task.fromJson(Map<String, dynamic> json) =>
Task(
isCompleted: json["isCompleted"],
taskId:json["id"],
text: json["text"],
priority: json["priority"]);
The issue was inside the fromJson() function, I was generating the list from an invalid variable
Updated method:
static LinkedHashMap<DateTime, List<Task>> fromJson(Map<String, dynamic> json) {
LinkedHashMap<DateTime, List<Task>> tempMap = LinkedHashMap<DateTime, List<Task>>();
json.forEach((key, value) {
tempMap.addAll({DateTime.parse(key): **List<Task>.from(value.map((x) => Task.fromJson(x)))**
});
});
return tempMap;
}
Hello Im trying to get data from the Jasonplaceholder Api, and I want to map it in a dart model
but I tried videos on YouTube and none of them work and I use autogenerated models but the data that received are inside a list but in that list have nested maps
var myMap=[{
"name" : "Ravindu",
"age" : 20,
"scl" : "smc",
"address" :
{
"city" : "Kegalle",
"country" : "sri lanka"
}
},
{
"name" : "Ravindu1",
"age" : 20,
"scl" : "smc1",
"address" :
{
"city" : "Kegalle1",
"country" : "sri lanka1"
}
}];
like this I want this to map to a Molde class and also, I want to know how to access Items inside this map tried myMap[0]["address"] but it only retrieve the whole map of address in the 0 index
so How can I pass these type of Json data to a model class
this is the actual url im working with
'''final String url ="https://jsonplaceholder.typicode.com/users"'''
I get this error when I try this on darpad
Uncaught Error: TypeError: Instance of 'JsLinkedHashMap<String, String>': type 'JsLinkedHashMap<String, String>' is not a subtype of type 'List'
this is the code I tried on dartpad
void main() {
var myMap=[{
"name" : "Ravindu",
"age" : 20,
"scl" : "smc",
"address" :
{
"city" : "Kegalle",
"country" : "sri lanka"
}
},
{
"name" : "Ravindu1",
"age" : 20,
"scl" : "smc1",
"address" :
{
"city" : "Kegalle1",
"country" : "sri lanka1"
}
}];
print(myMap[0]);
var addressList = myMap[0]["address"]["city"];
print(addressList);
(addressList as List).forEach((i){
print(i["country"]);
});
}
The addressList will get from myMap[0]["address"] which will be another map. On Map, forEach callback provide key and value .forEach((key, value) {
void main() {
List<Map<String, dynamic>> myMap = [
{
"name": "Ravindu",
"age": 20,
"scl": "smc",
"address": {"city": "Kegalle", "country": "sri lanka"}
},
{
"name": "Ravindu1",
"age": 20,
"scl": "smc1",
"address": {"city": "Kegalle1", "country": "sri lanka1"}
}
];
print(myMap[0].toString());
final addressList = myMap[0]["address"]["city"];
print(addressList.toString()); // kegalle
final Map<String, String> address = myMap[0]["address"];
address.forEach((key, value) {
print(" $key $value");
});
}
I am also using Dart class generator extion
class Person {
final String? name;
final int? age;
final String? scl;
final Address? address;
Person({
this.name,
this.age,
this.scl,
this.address,
});
Map<String, dynamic> toMap() {
final result = <String, dynamic>{};
if(name != null){
result.addAll({'name': name});
}
if(age != null){
result.addAll({'age': age});
}
if(scl != null){
result.addAll({'scl': scl});
}
if(address != null){
result.addAll({'address': address!.toMap()});
}
return result;
}
factory Person.fromMap(Map<String, dynamic> map) {
return Person(
name: map['name'],
age: map['age']?.toInt(),
scl: map['scl'],
address: map['address'] != null ? Address.fromMap(map['address']) : null,
);
}
String toJson() => json.encode(toMap());
factory Person.fromJson(String source) => Person.fromMap(json.decode(source));
}
class Address {
final String? city;
final String? country;
Address({
this.city,
this.country,
});
Map<String, dynamic> toMap() {
final result = <String, dynamic>{};
if(city != null){
result.addAll({'city': city});
}
if(country != null){
result.addAll({'country': country});
}
return result;
}
factory Address.fromMap(Map<String, dynamic> map) {
return Address(
city: map['city'],
country: map['country'],
);
}
String toJson() => json.encode(toMap());
factory Address.fromJson(String source) => Address.fromMap(json.decode(source));
}
try to get the json structure with this model.
First of all be sure to have json_annotation and http as a normal dependency, and json_serializable, build_runner as a dev dependencies.
Example of pubspec.yaml:
dependencies:
json_annotation: ^4.7.0
# used for HTTP calls
http: ^0.13.5
# other dependencies
dev_dependencies:
build_runner: ^2.3.2
json_serializable: ^6.5.4
# other dependencies
Then you should create a model with the fromJson method. This is going to be used to deserialize the JSON you retrieve from the API call. I'm going to use a Dart file named user.dart
import 'package:json_annotation/json_annotation.dart';
part 'user.g.dart';
#JsonSerializable()
class User {
const User({
required this.id,
required this.name,
required this.username,
required this.email,
required this.address,
});
final int id;
final String name;
final String username;
final String email;
final Address address;
/// Connect the generated [_$UserFromJson] function to the `fromJson`
/// factory.
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
/// Connect the generated [_$UserToJson] function to the `toJson` method.
Map<String, dynamic> toJson() => _$UserToJson(this);
}
#JsonSerializable()
class Address {
const Address({
required this.city,
required this.street,
required this.zipcode,
});
final String city;
final String street;
final String zipcode;
factory Address.fromJson(Map<String, dynamic> json) =>
_$AddressFromJson(json);
Map<String, dynamic> toJson() => _$AddressToJson(this);
}
Now in your Terminal you should run flutter pub run build_runner build --delete-conflicting-outputs to build the generated file, in my case it will generate a file called user.g.dart.
Now you need a service to make the HTTP call and return the list of users, I'm going to create a file called users_service.dart
import 'dart:convert';
import 'package:stackoverflow/user.dart';
import 'package:http/http.dart' as http;
class UsersService {
Future<List<User>> getUsers() async {
final uri = Uri.parse('https://jsonplaceholder.typicode.com/users');
final response = await http.get(uri);
final responseString = response.body;
final jsonList = List.from(jsonDecode(responseString));
return jsonList.map((json) => User.fromJson(json)).toList();
}
}
Here you must focus on the jsonDecode method that converts the JSON to a Dart object, and in the User.fromJson method that deserializes the JSON object converting it into a valid User Dart class.
As you can see the address field is another class with its fromJson implementation.
This is the right way to perform JSON (de)serialization, because it doesn't involve doing it manually (more error prone)
Example usage:
import 'package:stackoverflow/users_service.dart';
Future<void> main() async {
final users = await UsersService().getUsers();
for (final user in users) {
print("${user.name} lives in ${user.address.city}");
}
}
which prints:
Leanne Graham lives in Gwenborough
Ervin Howell lives in Wisokyburgh
Clementine Bauch lives in McKenziehaven
Patricia Lebsack lives in South Elvis
Chelsey Dietrich lives in Roscoeview
Mrs. Dennis Schulist lives in South Christy
Kurtis Weissnat lives in Howemouth
Nicholas Runolfsdottir V lives in Aliyaview
Glenna Reichert lives in Bartholomebury
Clementina DuBuque lives in Lebsackbury
Im working with rawg.io api and trying to get datas about games. There is a problem which i think it's about parsing data from json. I worked with easy apis which has not arrays or maps in it. But this data complicated and i guess that's why im getting always null results while try to print datas to screen.
Here is my code
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:video_games/load_data.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
Future<Welcome> apiCall() async {
final response = await http.get(Uri.parse(
'https://api.rawg.io/api/games?key=5ac29048d12d45d0949c77038115cb56'));
print(response.statusCode);
print(response.body);
return Welcome.fromJson(jsonDecode(response.body));
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: FutureBuilder<Welcome>(
future: apiCall(),
builder: (context, snapshot) {
// var growableList = [];
// List<Result> data = snapshot.data!.results;
// growableList.add(data[0].name);
return Text('${snapshot.data!.count}');
},
),
),
);
}
}
That is my response body and status code without using in a widget or parsing it
I/flutter ( 3666): 200
I/flutter ( 3666): {"count":679153,"next":"https://api.rawg.io/api/games?key=5ac29048d12d45d0949c77038115cb56&page=2","previous":null,"results":[{"id":3498,"slug":"grand-theft-auto-v","name":"Grand Theft Auto V","released":"2013-09-17","tba":false,"background_image":"https://media.rawg.io/media/games/456/456dea5e1c7e3cd07060c14e96612001.jpg","rating":4.48,"rating_top":5,"ratings":[{"id":5,"title":"exceptional","count":3217,"percent":58.97},{"id":4,"title":"recommended","count":1800,"percent":33.0},{"id":3,"title":"meh","count":348,"percent":6.38},{"id":1,"title":"skip","count":90,"percent":1.65}],"ratings_count":5389,"reviews_text_count":36,"added":16689,"added_by_status":{"yet":415,"owned":9874,"beaten":4491,"toplay":474,"dropped":835,"playing":600},"metacritic":97,"playtime":71,"suggestions_count":402,"updated":"2021-08-20T12:42:02","user_game":null,"reviews_count":5455,"saturated_color":"0f0f0f","dominant_color":"0f0f0f","platforms":[{"platform":{"id":1,"name":"Xbox One","slug":"xbox-one","image":null,"year_end":null,"year_
And this is my data class
// To parse this JSON data, do
//
// final welcome = welcomeFromJson(jsonString);
import 'dart:convert';
Welcome welcomeFromJson(String str) => Welcome.fromJson(json.decode(str));
String welcomeToJson(Welcome data) => json.encode(data.toJson());
class Welcome {
Welcome({
required this.count,
required this.next,
required this.previous,
required this.results,
});
int count;
String next;
String previous;
List<Result> results;
factory Welcome.fromJson(Map<String, dynamic> json) => Welcome(
count: json["count"],
next: json["next"],
previous: json["previous"],
results:
List<Result>.from(json["results"].map((x) => Result.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"count": count,
"next": next,
"previous": previous,
"results": List<dynamic>.from(results.map((x) => x.toJson())),
};
}
class Result {
Result({
required this.id,
required this.slug,
required this.name,
required this.released,
required this.tba,
required this.backgroundImage,
required this.rating,
required this.ratingTop,
required this.ratings,
required this.ratingsCount,
required this.reviewsTextCount,
required this.added,
required this.addedByStatus,
required this.metacritic,
required this.playtime,
required this.suggestionsCount,
required this.updated,
required this.esrbRating,
required this.platforms,
});
int id;
String slug;
String name;
DateTime released;
bool tba;
String backgroundImage;
int rating;
int ratingTop;
AddedByStatus ratings;
int ratingsCount;
String reviewsTextCount;
int added;
AddedByStatus addedByStatus;
int metacritic;
int playtime;
int suggestionsCount;
DateTime updated;
EsrbRating esrbRating;
List<Platform> platforms;
factory Result.fromJson(Map<String, dynamic> json) => Result(
id: json["id"],
slug: json["slug"],
name: json["name"],
released: DateTime.parse(json["released"]),
tba: json["tba"],
backgroundImage: json["background_image"],
rating: json["rating"],
ratingTop: json["rating_top"],
ratings: AddedByStatus.fromJson(json["ratings"]),
ratingsCount: json["ratings_count"],
reviewsTextCount: json["reviews_text_count"],
added: json["added"],
addedByStatus: AddedByStatus.fromJson(json["added_by_status"]),
metacritic: json["metacritic"],
playtime: json["playtime"],
suggestionsCount: json["suggestions_count"],
updated: DateTime.parse(json["updated"]),
esrbRating: EsrbRating.fromJson(json["esrb_rating"]),
platforms: List<Platform>.from(
json["platforms"].map((x) => Platform.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"id": id,
"slug": slug,
"name": name,
"released":
"${released.year.toString().padLeft(4, '0')}-${released.month.toString().padLeft(2, '0')}-${released.day.toString().padLeft(2, '0')}",
"tba": tba,
"background_image": backgroundImage,
"rating": rating,
"rating_top": ratingTop,
"ratings": ratings.toJson(),
"ratings_count": ratingsCount,
"reviews_text_count": reviewsTextCount,
"added": added,
"added_by_status": addedByStatus.toJson(),
"metacritic": metacritic,
"playtime": playtime,
"suggestions_count": suggestionsCount,
"updated": updated.toIso8601String(),
"esrb_rating": esrbRating.toJson(),
"platforms": List<dynamic>.from(platforms.map((x) => x.toJson())),
};
}
class AddedByStatus {
AddedByStatus();
factory AddedByStatus.fromJson(Map<String, dynamic> json) => AddedByStatus();
Map<String, dynamic> toJson() => {};
}
class EsrbRating {
EsrbRating({
required this.id,
required this.slug,
required this.name,
});
int id;
String slug;
String name;
factory EsrbRating.fromJson(Map<String, dynamic> json) => EsrbRating(
id: json["id"],
slug: json["slug"],
name: json["name"],
);
Map<String, dynamic> toJson() => {
"id": id,
"slug": slug,
"name": name,
};
}
class Platform {
Platform({
required this.platform,
required this.releasedAt,
required this.requirements,
});
EsrbRating platform;
String releasedAt;
Requirements requirements;
factory Platform.fromJson(Map<String, dynamic> json) => Platform(
platform: EsrbRating.fromJson(json["platform"]),
releasedAt: json["released_at"],
requirements: Requirements.fromJson(json["requirements"]),
);
Map<String, dynamic> toJson() => {
"platform": platform.toJson(),
"released_at": releasedAt,
"requirements": requirements.toJson(),
};
}
class Requirements {
Requirements({
required this.minimum,
required this.recommended,
});
String minimum;
String recommended;
factory Requirements.fromJson(Map<String, dynamic> json) => Requirements(
minimum: json["minimum"],
recommended: json["recommended"],
);
Map<String, dynamic> toJson() => {
"minimum": minimum,
"recommended": recommended,
};
}
Things i tried;
tried to convert response body to string before parsing
tried to change my widget to asnyc
tried to simplify my data class (to avoid arrays)
My opinion after research,
return Welcome.fromJson(jsonDecode(response.body));
this part can't work correctly cause of json decode can't decode complex datas which is has arrays and maps.
I stuck at this point and struggling. There is no document that i can do it correctly. Please help me about this.
I am calling an XML format API and converting it to Json to use it within a Flutter mobile app
I am using xml2Json and it is converting fine
As seen below I call print(jsonMap); and it displays the correct Json data in GData format
I then take my Json parse model, built with Quicktype.io off of the Json model and call locations = Locations.fromJson(jsonMap); as seen below to allow to to draw the required data out. I am currently then just calling print(locations); to check whether its working and the data is returning before implementing the parsed data into the app fully.
I have tried shuffling round everything, I've adapted the Model several times and tried all kinds of methods to parse the data.
I am calling other APIs with the exact same method successfully and the code method is identical in this one. The only difference is the xml2Json convert, which is converting fine (JsonMap printing converted XML correctly), so I'm struggling the see what should be different.
Thanks for reading
The call
Future<Locations> fetchLiveLocations() async {
var client = http.Client();
var locations;
Xml2Json xml2Json = new Xml2Json();
try{
var response = await client.get('API_CALL');
if (response.statusCode == 200) {
xml2Json.parse(response.body);
var jsonString = xml2Json.toGData();
var jsonMap = json.decode(jsonString);
print(jsonMap);
locations = Locations.fromJson(jsonMap);
print(locations);
}
} catch(Exception) {
return locations;
}
return locations;
}
Model
import 'dart:convert';
Locations locationsFromJson(String str) => Locations.fromJson(json.decode(str));
String locationsToJson(Locations data) => json.encode(data.toJson());
class Locations {
Locations({
this.vehicleActivity,
});
List<VehicleActivity> vehicleActivity;
factory Locations.fromJson(Map<String, dynamic> json) => Locations(
vehicleActivity: List<VehicleActivity>.from(json["VehicleActivity"].map((x) => VehicleActivity.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"VehicleActivity": List<dynamic>.from(vehicleActivity.map((x) => x.toJson())),
};
}
class VehicleActivity {
VehicleActivity({
this.recordedAtTime,
this.itemIdentifier,
this.validUntilTime,
this.monitoredVehicleJourney,
this.extensions,
});
DateTime recordedAtTime;
String itemIdentifier;
DateTime validUntilTime;
MonitoredVehicleJourney monitoredVehicleJourney;
Extensions extensions;
factory VehicleActivity.fromJson(Map<String, dynamic> json) => VehicleActivity(
recordedAtTime: DateTime.parse(json["RecordedAtTime"]),
itemIdentifier: json["ItemIdentifier"],
validUntilTime: DateTime.parse(json["ValidUntilTime"]),
monitoredVehicleJourney: MonitoredVehicleJourney.fromJson(json["MonitoredVehicleJourney"]),
extensions: Extensions.fromJson(json["Extensions"]),
);
Map<String, dynamic> toJson() => {
"RecordedAtTime": recordedAtTime.toIso8601String(),
"ItemIdentifier": itemIdentifier,
"ValidUntilTime": validUntilTime.toIso8601String(),
"MonitoredVehicleJourney": monitoredVehicleJourney.toJson(),
"Extensions": extensions.toJson(),
};
}
class Extensions {
Extensions({
this.vehicleJourney,
});
VehicleJourney vehicleJourney;
factory Extensions.fromJson(Map<String, dynamic> json) => Extensions(
vehicleJourney: VehicleJourney.fromJson(json["VehicleJourney"]),
);
Map<String, dynamic> toJson() => {
"VehicleJourney": vehicleJourney.toJson(),
};
}
class VehicleJourney {
VehicleJourney({
this.operational,
this.vehicleUniqueId,
this.driverRef,
});
Operational operational;
int vehicleUniqueId;
int driverRef;
factory VehicleJourney.fromJson(Map<String, dynamic> json) => VehicleJourney(
operational: Operational.fromJson(json["Operational"]),
vehicleUniqueId: json["VehicleUniqueId"],
driverRef: json["DriverRef"],
);
Map<String, dynamic> toJson() => {
"Operational": operational.toJson(),
"VehicleUniqueId": vehicleUniqueId,
"DriverRef": driverRef,
};
}
class Operational {
Operational({
this.ticketMachine,
});
TicketMachine ticketMachine;
factory Operational.fromJson(Map<String, dynamic> json) => Operational(
ticketMachine: TicketMachine.fromJson(json["TicketMachine"]),
);
Map<String, dynamic> toJson() => {
"TicketMachine": ticketMachine.toJson(),
};
}
class TicketMachine {
TicketMachine({
this.ticketMachineServiceCode,
this.journeyCode,
});
dynamic ticketMachineServiceCode;
int journeyCode;
factory TicketMachine.fromJson(Map<String, dynamic> json) => TicketMachine(
ticketMachineServiceCode: json["TicketMachineServiceCode"],
journeyCode: json["JourneyCode"],
);
Map<String, dynamic> toJson() => {
"TicketMachineServiceCode": ticketMachineServiceCode,
"JourneyCode": journeyCode,
};
}
class MonitoredVehicleJourney {
MonitoredVehicleJourney({
this.lineRef,
this.directionRef,
this.publishedLineName,
this.operatorRef,
this.destinationRef,
this.vehicleLocation,
this.blockRef,
this.vehicleJourneyRef,
this.vehicleRef,
});
int lineRef;
String directionRef;
int publishedLineName;
String operatorRef;
int destinationRef;
VehicleLocation vehicleLocation;
int blockRef;
String vehicleJourneyRef;
int vehicleRef;
factory MonitoredVehicleJourney.fromJson(Map<String, dynamic> json) => MonitoredVehicleJourney(
lineRef: json["LineRef"],
directionRef: json["DirectionRef"],
publishedLineName: json["PublishedLineName"],
operatorRef: json["OperatorRef"],
destinationRef: json["DestinationRef"],
vehicleLocation: VehicleLocation.fromJson(json["VehicleLocation"]),
blockRef: json["BlockRef"],
vehicleJourneyRef: json["VehicleJourneyRef"],
vehicleRef: json["VehicleRef"],
);
Map<String, dynamic> toJson() => {
"LineRef": lineRef,
"DirectionRef": directionRef,
"PublishedLineName": publishedLineName,
"OperatorRef": operatorRef,
"DestinationRef": destinationRef,
"VehicleLocation": vehicleLocation.toJson(),
"BlockRef": blockRef,
"VehicleJourneyRef": vehicleJourneyRef,
"VehicleRef": vehicleRef,
};
}
class VehicleLocation {
VehicleLocation({
this.longitude,
this.latitude,
});
double longitude;
double latitude;
factory VehicleLocation.fromJson(Map<String, dynamic> json) => VehicleLocation(
longitude: json["Longitude"].toDouble(),
latitude: json["Latitude"].toDouble(),
);
Map<String, dynamic> toJson() => {
"Longitude": longitude,
"Latitude": latitude,
};
}
Response when I request specific data from the model
NoSuchMethodError (NoSuchMethodError: The getter 'vehicleActivity' was called on null.
Receiver: null