Need help to parsing JSON in Flutter - dart

I am trying to get data from the internet in Flutter.
But I am getting an error on JSON parsing.
Can anyone tell me what is the problem?
I am trying to get data from this URL
https://swapi.co/api/starships/
Example JSON
{
"count": 37,
"next": "https://swapi.co/api/starships/?page=2",
"previous": null,
"results": [
{
"name": "Executor",
"model": "Executor-class star dreadnought",
"manufacturer": "Kuat Drive Yards, Fondor Shipyards",
"cost_in_credits": "1143350000",
"length": "19000",
"max_atmosphering_speed": "n/a",
"crew": "279144",
"passengers": "38000",
"cargo_capacity": "250000000",
"consumables": "6 years",
"hyperdrive_rating": "2.0",
"MGLT": "40",
"starship_class": "Star dreadnought",
"pilots": [],
"films": [
"https://swapi.co/api/films/2/",
"https://swapi.co/api/films/3/"
],
"created": "2014-12-15T12:31:42.547000Z",
"edited": "2017-04-19T10:56:06.685592Z",
"url": "https://swapi.co/api/starships/15/"
},
]
}
Model class
class RestModel {
final String name;
final String model;
final String manufacturer;
final String cost_in_credits;
final String length;
final String max_atmosphering_speed;
final String crew;
final String passengers;
final String cargo_capacity;
final String consumables;
final String hyperdrive_rating;
final String MGLT;
final String starship_class;
final List films;
final String pilots;
final String created;
final String edited;
final String url;
RestModel(
{this.name,
this.model,
this.manufacturer,
this.cost_in_credits,
this.length,
this.max_atmosphering_speed,
this.crew,
this.passengers,
this.cargo_capacity,
this.consumables,
this.hyperdrive_rating,
this.MGLT,
this.starship_class,
this.films,
this.pilots,
this.created,
this.edited,
this.url});
factory RestModel.fromJson(Map<String, dynamic> json) {
return RestModel(
name: json["name"],
model: json["model"],
manufacturer: json["manufacturer"],
cost_in_credits: json["cost_in_credits"],
max_atmosphering_speed: json["max_atmosphering_speed"],
crew: json["crew"],
passengers: json["passengers"],
cargo_capacity: json["cargo_capacity"],
consumables: json["consumables"],
hyperdrive_rating: json["hyperdrive_rating"],
MGLT: json["MGLT"],
starship_class: json["starship_class"],
films: json["flims"],
pilots: json["pilots"],
created: json["created"],
edited: json["edited"],
url: json["url"],
);
}
}
and the Flutter code is:
final link = "https://swapi.co/api/starships/";
List<RestModel> list;
Future getData() async {
var res = await http
.get(Uri.encodeFull(link), headers: {"Accept":"application/json"});
if (res.statusCode == 200) {
var data = json.decode(res.body);
var rest = data["results"];
for (var model in rest) {
list.add(RestModel.fromJson(model));
}
print("List Size: ${list.length}");
}
}
The main problem is when it tries to fill data from JSON.
RestModel.fromJson(model)
so what I have to change to fix this problem.

Try to cast the data 'results' to List , like this :
var rest = data["results"] as List;
Updated
Now that we know the error log: "No static method 'fromJson' declared in class 'RestModel'"
It's because you are using a static method in this line:
list.add(RestModel.fromJson(model));
You must change the call in order to use the factory constructor, like this :
list.add(new RestModel.fromJson(model));

Related

Using JSON Files for localization in GetX

I am trying to read translation files eg. en.json to use with GetX localization. I tried the following code but no success. Is there any better way of doing it? Somebody suggested using auto_localize with GetX, but I'll really appreciate if I can proceed without an extra package
Map<String, Map<String, String>> get keys => {
"ar": readJson("ar"),
"en": readJson("en"),
}
I tried loading the localization information using the following function
// Fetch content from the json file
Map<String, String> readJson(String languageCode) {
Map data = {};
rootBundle
.loadString('assets/translations/$languageCode.json')
.then((response) {
data = json.decode(response);
});
return data.map((key, value) {
return MapEntry(key, value.toString());
});
}
DebugPrint() gets shows that the files were successfully loaded. However, trying to display the loaded Maps doesn't work
The readJson should be Future and because of that the empty Map returned at the end.
The way i did
create languages.json file and put all texts to it.
[
{
"name": "English",
"code": "en_US",
"texts": {
"hello": "Hello World"
}
},
{
"name": "Arabic",
"code": "ar_AE",
"texts": {
"hello": "مرحبا بالعالم"
}
}
]
implement localization class like this
class LocalizationService extends Translations {
#override
Map<String, Map<String, String>> get keys => {};
static Future<void> initLanguages() async {
final _keys = await readJson();
Get.clearTranslations();
Get.addTranslations(_keys);
}
static Future<Map<String, Map<String, String>>> readJson() async {
final res = await rootBundle.loadString('assets/languages.json');
List<dynamic> data = jsonDecode(res);
final listData = data.map((j) => I18nModel.fromJson(j)).toList();
final keys = Map<String, Map<String, String>>();
listData.forEach((value) {
final String translationKey = value.code!;
keys.addAll({translationKey: value.texts!});
});
return keys;
}
}
As you see after getting the Map data, i used Get.addTranslations(); to set language keys.
this is a GetX function to add languages on air!
create model class to parse json data
class I18nModel {
String? name;
String? code;
Map<String, String>? texts;
I18nModel(
{this.name, this.code, this.texts});
I18nModel.fromJson(Map<String, dynamic> json) {
name = json['name'];
code = json['code'];
if (json['texts'] != null) {
texts = Map<String, String>.from(json['texts']);
}
}
}
And finally call await LocalizationService.initLanguages(); before going to your first Route.

Get size or length of json array response (restAssured Response interface)

We have REST API automation scripts using RestAssured. In this declared response object as public static Response response; and retrieving the response data using response.jsonPath().get("id"), during this trying to even get the size or length of the id, even need to get details about tags array.
JSON Response:
[
{
"id": 1,
"name": "test1",
"tags": [
{
"tagType": "details1",
"tag": {
"description": null
}
}
]
},
{
"id": 2,
"name": "test2",
"tags": [
{
"tagType": "details2",
"tag": {
"description": null
}
}
]
}
]
Tried below ways:
public static Response response;
List<String> resIDs = response.jsonPath().get("id");
System.err.println("Retrieved IDs from Response: " + resIDs);
O/P: is [1,2,3,4,5,6,7]
Tried as resIDs.size(), that also no response printed.
List<Object> size = response.jsonPath().getList("$");
System.err.println("ArraySize for IDs from Response: " + size);
or
int size = response.jsonPath().getList("$").size();
O/P: Not printed/nothing shown
Please guide how to get the size/length.
I don't seem to find any issue in your code, I just changed a bit to run locally and its working fine. Here's my code
public class S_62591968 {
public static Response postCallWithJsonBodyParam(String URL) {
return RestAssured.given().relaxedHTTPSValidation().contentType(ContentType.JSON).request().when().get(URL);
}
public static void main(String[] args) {
String url_endPoint = "http://localhost:8089/def/abc";
Response response = postCallWithJsonBodyParam(url_endPoint);
List<String> resIDs = response.jsonPath().get("id");
System.out.println("Retrieved IDs from Response : " + resIDs);
System.out.println("ArraySize for IDs from Response : " + resIDs.size());
}
}
Console :
Retrieved IDs from Response : [1, 2]
ArraySize for IDs from Response : 2

Swagger shows extra parameters in request body

We are using springfox-swagger-ui and springfox-swagger2 of version 2.7.0.
A post api has the following signature :
#ApiOperation("Edits information about employees")
#PostMapping(path = "/employee/edit", headers = EndPoints.VERSION_1)
#ApiResponses(value = {
#ApiResponse(code = 409, message = "Data mismatch"),
#ApiResponse(code = 400, message = "Invalid data passed")
})
public ResponseEntity<Employee> manageEmployee(
#RequestHeader("employeeId") final String iEmployeeId,
#RequestBody(required = true) #Valid final Employee iEmployee)
The object employee is:
public class Employee implements Serializable {
private static final long serialVersionUID = -7315844547195801413L;
private String employeeName;
private Long employeeId;
private #Valid #NotNull List<Address> addresses;
// getter and setter methods
#Validated
public static class Address implements Serializable {
private static final long serialVersionUID = 6748945632164495934L;
private String addressId;
#ValidAddress
private String addressName;
//getter and setter methods
}
}
But the swagger shows the request body as :
{
"addresses": {
"addressId": "string",
"addressName": "string",
"permanentAddress": [
{
"addressId": "string",
"addressName": "string"
}
]
},
"employeeName": "string",
"employeeId": 0
}
The object permanentAddress is not present in my code.
How can this be resolved?
Before questioning why permantnAddress, I think it's more important to find out why addresses is an object of addressId, addressName, and a list of Address. Something doesn't look right in the JSON.
The Employee object looks like:
{
addresses: [
addressId: "string",
addressName: "string"
],
employeeName: "string",
employeeId: 0
}
permanentAddress is the correct object for List addresses

failed due to: Bad state: No builder factory for BuiltList

I am using builtvalue for my PODO class
Following is my json response
{
"status": 1,
"msg": "Success",
"allotmentMasterID": "1",
"allotmentInfoID": "1",
"category": [
{
"categoryID": "1",
"categoryName": "Major",
"selectedCount": "0",
"status": 1
},
{
"categoryID": "2",
"categoryName": "Mandatory",
"selectedCount": "0",
"status": 0
},
{
"categoryID": "3",
"categoryName": "Minor",
"selectedCount": "0",
"status": 0
}
]
}
I have created a built value for this
Following are the classes
library specialisation_model_first_screen;
import 'package:built_collection/built_collection.dart';
import 'package:built_value/built_value.dart';
import 'package:built_value/serializer.dart';
part 'specialisation_model_first_screen.g.dart';
abstract class SpecialisationModelFirstScreen
implements
Built<SpecialisationModelFirstScreen,
SpecialisationModelFirstScreenBuilder> {
SpecialisationModelFirstScreen._();
factory SpecialisationModelFirstScreen(
[updates(SpecialisationModelFirstScreenBuilder b)]) =
_$SpecialisationModelFirstScreen;
#nullable
#BuiltValueField(wireName: 'status')
int get status;
#nullable
#BuiltValueField(wireName: 'msg')
String get msg;
#nullable
#BuiltValueField(wireName: 'allotmentMasterID')
String get allotmentMasterID;
#nullable
#BuiltValueField(wireName: 'allotmentInfoID')
String get allotmentInfoID;
#nullable
#BuiltValueField(wireName: 'category')
BuiltList<Category> get category;
static Serializer<SpecialisationModelFirstScreen> get serializer =>
_$specialisationModelFirstScreenSerializer;
}
abstract class Category implements Built<Category, CategoryBuilder> {
Category._();
factory Category([updates(CategoryBuilder b)]) = _$Category;
#nullable
#BuiltValueField(wireName: 'categoryID')
String get categoryID;
#nullable
#BuiltValueField(wireName: 'categoryName')
String get categoryName;
#nullable
#BuiltValueField(wireName: 'selectedCount')
String get selectedCount;
#nullable
#BuiltValueField(wireName: 'status')
int get status;
static Serializer<Category> get serializer => _$categorySerializer;
}
library serializers;
import 'package:built_value/serializer.dart';
part 'package:dice_clutter/models/serializers/serializers.g.dart';
#SerializersFor(const [SpecialisationModelFirstScreen])
Serializers serializers = _$serializers;
Serializers standardSerializers = (serializers.toBuilder()..addPlugin(StandardJsonPlugin())).build();
Following is my serializers.g.dart file
part of serializers;
Serializers _$serializers = (new Serializers().toBuilder()
..add(SpecialisationModelFirstScreen.serializer))
.build();
When i am making an api request i am getting the response correctly but following error is thrown
failed due to: Bad state: No builder factory for BuiltList<Category>. Fix by adding one, see SerializersBuilder.addBuilderFactory.
Is this a bug in build value library itself or am i doing something wrong?
In some cases - and I do not fully understand specific reasons - my objects fail to deserialize with StandartJsonPlugin.
I had to edit my serializers.g.dart file as follows
Serializers _$serializers = (new Serializers().toBuilder()
..add(SpecialisationModelFirstScreen.serializer)
..add(Category.serializer)
..addBuilderFactory(
const FullType(
BuiltList, const [const FullType(Category)]),
() => new ListBuilder<Category>())
)
.build();
Thanks to Tensor Programming Video on Youtube
There is some bug in the builtvalue library as it is not able to generate serializers.g.dart properly in some cases. Hope It gets resolved in the future
You need to add the Category class to the list of classes that can be serialized:
#SerializersFor(const [
SpecialisationModelFirstScreen,
Category, <-- Category available for serialization
])
then regenerate your built_value classes.
More details can be found in this answer
base on JSON and serialization - Flutter and your code ,
you are missing fromJson ,
using JSON to Dart
see the fromJson function
class Autogenerated {
int status;
String msg;
String allotmentMasterID;
String allotmentInfoID;
List<Category> category;
Autogenerated(
{this.status,
this.msg,
this.allotmentMasterID,
this.allotmentInfoID,
this.category});
Autogenerated.fromJson(Map<String, dynamic> json) {
status = json['status'];
msg = json['msg'];
allotmentMasterID = json['allotmentMasterID'];
allotmentInfoID = json['allotmentInfoID'];
if (json['category'] != null) {
category = new List<Category>();
json['category'].forEach((v) {
category.add(new Category.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['status'] = this.status;
data['msg'] = this.msg;
data['allotmentMasterID'] = this.allotmentMasterID;
data['allotmentInfoID'] = this.allotmentInfoID;
if (this.category != null) {
data['category'] = this.category.map((v) => v.toJson()).toList();
}
return data;
}
}
class Category {
String categoryID;
String categoryName;
String selectedCount;
int status;
Category(
{this.categoryID, this.categoryName, this.selectedCount, this.status});
Category.fromJson(Map<String, dynamic> json) {
categoryID = json['categoryID'];
categoryName = json['categoryName'];
selectedCount = json['selectedCount'];
status = json['status'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['categoryID'] = this.categoryID;
data['categoryName'] = this.categoryName;
data['selectedCount'] = this.selectedCount;
data['status'] = this.status;
return data;
}
}

Convert a class into JSON or List

How to convert this class into JSON or List?
class cliente {
int id;
String nome;
String apelido;
String sexo;
String status;
}
Edit
I'm changed my class and works fine to my case:
class client {
Map<String, dynamic> fields => {
"id": "",
"name": "",
"nickname": "",
"sex": "",
"status": "",
}
Then I use:
client.fields["id"] = 1;
client.fields["name"] = "matheus";
sqlite.rowInsert("insert into client(id, name)", client.fields.Keys.toList(), client.fields.Values.toList());
Just create a method inside your class and return a Map<String, dynamic>
class cliente {
int id;
String nome;
String apelido;
String sexo;
String status;
Map<String, dynamic> toJson() => {
'id': id,
'nome': nome,
'apelido': apelido,
'sexo': sexo,
'status': status,
};
}
And use it for example :
final dataObject = new client();
...fill your object
final jsonData = dataObject.toJson();
Also you can try using this package to avoid writing all of your fields : https://pub.dartlang.org/packages/json_serializable

Resources