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.
Related
I tried two method to parse the rawData into dart objects. One using a for loop ads and it works but why _ads is not working when I use map ?
void main() {
dynamic rawData = [
{"title": "a", "id": 1}
];
List<Ad> ads = [];
for (var raw in rawData) {
Ad ad = Ad.fromJson(raw);
ads.add(ad);
}
print(ads);
List<Ad> _ads = rawData.map((e) => Ad.fromJson(e)).toList();
print(_ads);
}
class Ad {
Ad({
this.id,
this.title,
});
int id;
String title;
factory Ad.fromJson(Map<String, dynamic> json) => _$AdFromJson(json);
Map<String, dynamic> toJson() => _$AdToJson(this);
}
Ad _$AdFromJson(Map json) {
return Ad(
id: json['id'] as int,
title: json['title'] as String,
);
}
Map<String, dynamic> _$AdToJson(Ad instance) {
final val = <String, dynamic>{};
void writeNotNull(String key, dynamic value) {
if (value != null) {
val[key] = value;
}
}
writeNotNull('id', instance.id);
writeNotNull('title', instance.title);
return val;
}
The result of calling nearly any method on a dynamic defined variable are going to be dynamic since the Dart compiler are going through a difficult time guessing the type you want. So when you want the result to be saved into a variable with a specific type like List<Ad> _ads you really need to tell the compiler at each step what generic type you want and expect.
With that said, you can get you code to work by changing:
List<Ad> _ads = rawData.map((e) => Ad.fromJson(e)).toList();
Into:
List<Ad> _ads = rawData.map<Ad>((e) => Ad.fromJson(e)).toList();
And if you also want to make the analyzer happy:
List<Ad> _ads = rawData.map<Ad>((Map<String, dynamic> e) => Ad.fromJson(e)).toList() as List<Ad>;
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;
}
}
Calling API but showing error, I'm unable to parse data in the bean class.
My Response:
{
"error":"0",
"status":200,
"deliveryCharge":"14.00",
"image_base_url":"http:\/\/xxxxx.tk\/assets\/event\/image\/",
"image_logo_url":"http:\/\/xxxxx.tk\/assets\/event\/logo\/",
"eventList":[
{
"event_id":"1",
"event_name":"Syscraft Premier League",
"event_location":"12 ny valleys",
"event_type_id":"15",
"start_date":"2019-01-10 03:21:00",
"end_date":"2019-01-26 16:10:00",
"event_logo":"f4f0bfc168a3816891e2749232c5243f.jpg"
},
{
"event_id":"3",
"event_name":"Republic Day Event 2019",
"event_location":"AH-654 Villa No. 42 New Township New Township",
"event_type_id":"1",
"start_date":"2019-01-26 00:00:00",
"end_date":"2019-01-26 11:55:00",
"event_logo":"3a4a7fabbbd7ed8febf67bacda71ae48.jpg"
}
]
}
Calling Api
Future<List<EventResponse>> fetchEvent( ) async {
String url='http://xxxxxxxxxxxxxxx.tk/api/userapp/event/lists';
var headers = new Map();
headers['Auth-Key'] = 'OCDOC#2018';
headers['End-Client'] = 'OCDOC';
var body = new Map();
headers['schedule'] = 'present';
http.Response res = await http.post(url,headers: headers, body: body);
final Map<String,dynamic> parsed=json.decode(res.body); // post api call
print("Reposnce Event:---"+parsed.toString());}
My Bean class
class EventResponse{
String error;
int status;
String deliveryCharges;
String imageBaseUrl;
String imageLogoUrl;
List<Event> eventList;
EventResponse({
this.error,
this.status,
this.deliveryCharges,
this.imageBaseUrl,
this.imageLogoUrl,
this.eventList
});
factory EventResponse.convertEventResponse(Map<String,dynamic> json){
return EventResponse(
error: json['error'],
status: json['status'],
deliveryCharges: json['deliveryCharge'],
imageBaseUrl: json['image_base_url'],
imageLogoUrl: json['image_logo_url'],
eventList: json['eventList']);
}}
class Event{
String eventId;
String eventName;
String location;
String event_logo;
Event({
this.eventId,
this.eventName,
this.location,
this.event_logo,
});
factory Event.convertEvent(Map<String,dynamic> json){
return Event(
eventId: json['event_id'],
eventName: json['event_name'],
location: json['event_location'],
event_logo: json['event_logo'],
);}}
Showing Error
_InternalLinkedHashMap<dynamic, dynamic> is not a subtype of type Map<String, String>
Rewrite EventResponse like this:
class EventResponse {
String error;
int status;
String deliveryCharges;
String imageBaseUrl;
String imageLogoUrl;
List<Event> eventList;
EventResponse(
{this.error,
this.status,
this.deliveryCharges,
this.imageBaseUrl,
this.imageLogoUrl,
this.eventList});
factory EventResponse.convertEventResponse(Map<String, dynamic> json) {
List<dynamic> events = json['eventList'];
List<Event> eventList = events.map((e) => Event.convertEvent(e)).toList();
return EventResponse(
error: json['error'],
status: json['status'],
deliveryCharges: json['deliveryCharge'],
imageBaseUrl: json['image_base_url'],
imageLogoUrl: json['image_logo_url'],
eventList: eventList,
);
}
}
I have changed EventResponse as #Richard Heap did.
factory EventResponse.convertEventResponse(Map<String, dynamic> json) {
List<dynamic> events = json['eventList'];
List<Event> eventList = events.map((e) => Event.convertEvent(e)).toList();
return EventResponse(
error: json['error'],
status: json['status'],
deliveryCharges: json['deliveryCharge'],
imageBaseUrl: json['image_base_url'],
imageLogoUrl: json['image_logo_url'],
eventList: eventList,
);
}
}
One more thing I need to change is when I post parameters and headers need to define their Map() to Map<String,String>().
Future<EventResponse> fetchEvent( ) async { // here i change Future type
String url='http://xxxxxxx-oceanapparel.tk/api/userapp/event/lists';
var headers = new Map<String, String>(); //here i defined Map type
headers['Auth-Key'] = 'OCDOC#2018';
headers['End-Client'] = 'OCDOC';
var body = new Map<String, String>(); //here i defined Map type
headers['schedule'] = 'present';
http.Response res = await http.post(url,headers: headers, body: body);
print("Reposnce Event:---"+res.body);
}
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));
I asked a question before about Dart encoding/decoding to JSON, however, the libraries that were suggested were not complete and I decided to manually handle that.
The objective is to convert these objects to a map.
class Parent extends Object {
int id;
String name;
List<Child> listChild = new List<Child>();
Map toMap() => {"id":id, "name":name, "listChild":listChild};
}
class Child extends Object {
int id;
String childName;
Map toMap() => {"id":id, "childName":childName};
}
When doing
print(JSON.encode(parent.toMap()));
I am seeing it go here, any suggestion how to make this work?
if (!stringifyJsonValue(object)) {
checkCycle(object);
try {
var customJson = _toEncodable(object);
if (!stringifyJsonValue(customJson)) {
throw new JsonUnsupportedObjectError(object);
}
_removeSeen(object);
} catch (e) {
throw new JsonUnsupportedObjectError(object, cause : e);
}
}
}
Map toMap() => {"id":id, "name":name: "listChild": listChild.map((c) => c.toJson().toList())};
is valid for JSON.
import 'dart:convert' show JSON;
...
String json = JSON.encode(toMap());
You can also use the toEncodeable callback - see How to convert DateTime object to json
If your class structure does not contain's any inner class then follow
class Data{
String name;
String type;
Map<String, dynamic> toJson() => {
'name': name,
'type': type
};
}
If your class uses inner class structure
class QuestionTag {
String name;
List<SubTags> listSubTags;
Map<String, dynamic> toJson() => {
'name': name,
'listSubTags': listSubTags.map((tag) => tag.toJson()).toList()
};
}
class SubTags {
String tagName;
String tagDesc;
SubTags(this.tagName, this.tagDesc);
Map<String, dynamic> toJson() => {
'tagName': tagName,
'tagDesc': tagDesc,
};
}
Just rename Map toMap() into Map toJson() and it will work fine. =)
void encode() {
Parent p = new Parent();
Child c1 = new Child();
c1 ..id = 1 ..childName = "Alex";
Child c2 = new Child();
c2 ..id = 2 ..childName = "John";
Child c3 = new Child();
c3 ..id = 3 ..childName = "Jane";
p ..id = 1 ..name = "Lisa" ..listChild = [c1,c2,c3];
String json = JSON.encode(p);
print(json);
}
class Parent extends Object {
int id;
String name;
List<Child> listChild = new List<Child>();
Map toJson() => {"id":id, "name":name, "listChild":listChild};
}
class Child extends Object {
int id;
String childName;
Map toJson() => {"id":id, "childName":childName};
}