Flutter independent model classes - flutter

I have created a weather model class with its parameters and I'm going to get data from the API.
But I'm a bit curious If I want to get data from 2 APIs with different parameters how do I use the same model classes?
Example: API 1 -> returns 'temp' and API 2 -> returns 'temperature' and I want to use the same model class.
Is this even possible? If so how should I do it?

Include all parameters from both api response and make params which are different in both Apis nullable.

use different fromJson in your model class:
for example in one of them do this:
static Weather fromJsonOne(Map<String, Object> json) {
return Weather(
temp: json["temp"] as String
);
}
and in the other do this:
static Weather fromJsonTwo(Map<String, Object> json) {
return Weather(
temp: json["temperature"] as String
);
}

Related

Flutter, why use "static" in the fromJson method?

static TodoEntity fromJson(Map<String, Object> json) {
return TodoEntity(
json['task'] as String,
json['id'] as String,
json['note'] as String,
json['complete'] as bool,
);
}
static TodoEntity fromSnapshot(DocumentSnapshot snap) {
return TodoEntity(
snap.data()['task'],
snap.id,
snap.data()['note'],
snap.data()['complete'],
);
}
I`m studying "fromJson" method right now and
In this example, why they use "static"?
I wonder why
Because fromJson is related the class and not the object (this is the case for every static variable/method)
So from the name fromJson, You need to create TodoEntity object from your json, which means you don't have the object yet which means you can't call fromJson, So using static here is a must,
Another alternative is passing your json via constructor, but using static is must clean and common.
Example without static:
To create new object from json
var json = {...};
TodoEntity todo = TodoEntity();
TodoEntity todo2 = todo.fromJson(json);
or
var json = {...};
TodoEntity todo = TodoEntity();
todo = todo.fromJson(json);
as you can see you need always an object (todo) to call fromJson
but using static
var json = {...};
TodoEntity todo = TodoEntity.fromJson(json);
static means you can call this function without having an object
The static keyword required to implement "Static Factory Method" pattern for methods which are producing new instances of given class.
If these methods were not static, you had to have the an instance of TodoEntity to call them.
But they are static, so there's no need to create any instance to call them:
TodoEntity.fromJson(jsonMap);

auto converting json to object in dart flutter

I search google and stackoverflow but did not find some auto converting lib like in C#
I need something in dart-flutter alternative to this code in C#
string jsonTokenData = "{my token json data}";
TokenModel getTokenModel = Newtonsoft.Json.JsonConvert.DeserializeObject<GetTokenModel>(jsonTokenData);
Update
I read the Documentation and I know how to map models with json
this question to who know how Newtonsoft lib work on C#
if you do not know Newtonsoft: the Idea is to convert json data to a model automatically without writing map for each model. Also I know there is a tool to create that map with json for each model automatically but still make code ridiculous.
Update2: as I get a suggestion from community for a similar question that not answer my question. so this is a another explanation:
I have a lot of models these models are updated by time as clients requested or adding new features to some models.
so when an update happen I just need to add the extra properties that has been added to these models, I do not need to warry every time about mapping, spell mistaken or using some tools again to regenerate these codes.
so I'm asking for a function that take two parameters
first one is the type of the model
second one the json string that hold the data
[then in return is an object instance of the passed type]
for simple example if I have this class:
class Car {
String name;
String type;
}
Then I could keep it clean this way without getting it dart with other methods:
Car({
this.name,
this.type,
});
factory Car.fromJson(Map<String, dynamic> json) => Car(
name: json["name"],
type: json["type"],
);
Map<String, dynamic> toJson() => {
"name": name,
"type": type,
};
by the way lib in C# is also take care about arrays, lists and nested classes
I hope this time it explained well
I've added a new Dart package to Jsonize custom classes within any data structure.
This is how your Car example would look like:
import 'package:jsonize/jsonize.dart';
class Car implements Jsonizable<Car> {
final String name;
final String type;
Car({required this.name, required this.type});
// Jsonizable implementation
factory Car.empty() => Car(name: "", type: "");
#override
String get jsonClassCode => "car";
#override
Map<String, dynamic> toJson() => {"name": name, "type": type};
#override
Car? fromJson(value) => Car(name: value["name"], type: value["type"]);
}
void main() {
// Register classes
Jsonize.registerClass(Car.empty());
// Now you can jsonize it wherever
Map<String, dynamic> myMap = {
"my_car": Car(name: "Jessie", type: "Tesla"),
"purchase_dt": DateTime.now(),
};
var jsonRep = Jsonize.toJson(myMap);
var hereIsMyMap = Jsonize.fromJson(jsonRep);
print(hereIsMyMap);
List<dynamic> myList = [
Car(name: "Jessie", type: "Tesla"),
Car(name: "Bob", type: "Ford"),
];
jsonRep = Jsonize.toJson(myList);
var hereIsMyList = Jsonize.fromJson(jsonRep);
print(hereIsMyList);
}
just import dart:convert library like this :
import 'dart:convert';
Then use this code :
json.decode(json)
Take a look at this link : dart:convert library
Doing some research would allow you to not ask here on SO.
JSON decoding is well documented on the flutter site. It points to using the jsonDecode function, which parses the String and returns the resulting JSON object.
String jsonTokenData = "{my token json data}";
dynamic json = jsonDecode(jsonTokenData);
You can pass the decoded object to a custom constructor of your object like .fromJson, which accepts a Map/List depending on your JSON data.
If for some reason creating a constructor to accept JSON data would be too much work/typing or if you're having trouble doing it yourself, you can use a JSON to Dart service like this.

Flutter / Inject.dart - Is it possible to simplify or generate code for a 'provided' class instantiation?

Been doing some research on Flutter Dependency Injection,and I kinda settled on Inject.dart
However, I am having some trouble using inject.
Is there any way to simplify instantitation of a injected class?
I have this MyClass, which I need to instantiate passing a HomeStore, however, how can I instatiate it without calling global acessors? (such as the ones made on the Injector file).
It seems I could just use the Get_It package otherwise, which would get me the same results, and without code generation, but I don't quite like the whole global access thing.
My sample:
// current code
class MyClass(){
store = HomeStore(AppInjector().globalHudStore, AppInjector().globalErrorStore);
}
// desired code
class MyClass(){
#instance ?
store = HomeStore();
store = HomeStore.instanciate?();
}
class HomeStore {
#provide
HomeStore(this._globalHudStore, this._globalErrorStore);
final GlobalHudStore _globalHudStore;
final ErrorStore _globalErrorStore;
}
If you are willing to work with json, you might want to consider this package json_serializable. Just search for it at pub.dev.
I can give a little example. Let's say you have a User class/model.
part 'user.g.dart';
#JsonSerializable()
class User {
int id;
#JsonKey(name: 'user_type_id')
int userTypeId;
String email;
#JsonKey(name: 'user_detail')
UserDetail userDetail;
#JsonKey(name: 'user_type')
UserType userType;
#JsonKey(name: 'user_location')
UserLocation userLocation;
User();
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
Map<String, dynamic> toJson() => _$UserToJson(this);
}
and you fetched a User data via API, and want to create a User variable and fill it with data without having to do that manually.
You can actually do that with just this line of code
User user = User.fromJson(jsonUser);
These even automatically json serializes classes in your User class, as long as those classes are also json serializable, which is defined with #JsonSerializable()
So even with just that single line of code, if the jsonUser which came from the API also has values for UserDetail, UserType, and UserLocation, you can also access them.

Need help understand interfaces and/or abstract classes in angular2

I am new to the angular2 world. I am trying to create interfaces for certain components and then implement these interfaces in my models so I can make sure they will be able to work properly.
One thing I have noticed is that if I create new instances of these objects they work fine but when I pull data from a restful call, I use the type casting to turn the data into the type of object I expect. The following code is a pseudo example.
I come from a Java/C++ background so I am hoping someone can see what I'm trying to do and explain to me how to get this working correctly.
Thanks In Advance!
Doesn't work ---
private vehicles: Vehicle[];
this._vehicleService.loadVehicles().subscribe(
vehicles => this.vehicles = <Vehicle[]>vehicles);
Does Work ---
vehicles : Vehicle[];
vehicles.push(new Vehicle(1, 'Old Junker'));
vehicles.push(new Vehicle(2, 'Old Junker2'));
Example class/interface setup.
#Component
export class SelectableComponent {
options : Selectable[]
// Access options.label and options.value
}
export interface Selectable {
label(): string;
value(): any;
}
export class Vehicle implements Selectable {
constructor (
public id: number,
public description: string,
){}
get label() : any {
return this.description;
}
get value() : any {
return this.id;
}
}
What happens here is that the object retrieved from the backend is just a plain Javascript object that gets cast to a Vehicle:
this._vehicleService.loadVehicles().subscribe(
vehicles => this.vehicles = <Vehicle[]>vehicles);
Objects in this array will have all the data of a Vehicle, but none of the behavior of an instance of the Vehicle class, which can be quite confusing as you mention.
The simplest is instead of casting them, calling new and creating an instance of Vehicle immediately while retrieving them from the backend.
But using a long constructor call can be cumbersome, especially if Vehicle has a lot of properties and you need to pass them all to the constructor one by one.
A way to fix this is to create an auxiliary method in the Vehicle class:
class Vehicle {
constructor(private name, private year) {
}
static fromJson({name,year}) {
return new Vehicle(name, year);
}
}
And then use it in return from the backend to create an array of Vehicles, instead of casting them:
this._vehicleService.loadVehicles().subscribe(
vehicles => this.vehicles = vehicles.map(Vehicle.fromJson));
This way the vehicles in the result will have not only all the data of a vehicle, but also the behavior of the Vehicle class, because they are instances on Vehicle.
The main difference between classes and interfaces in TypeScript is that interfaces don't exist at runtime. They are "only" there for compilation and type checking.
Casting an element to an interface / class "only" tells TypeScript that the object follows the structure of it but it's not actually an instance of the type. It's a bit disturbing at a first sight. The main consequence (in the case of a class) is that casting doesn't allow you to use methods of the class.
I already casted this way:
private vehicles: Vehicle[];
this._vehicleService.loadVehicles().subscribe(
vehicles => this.vehicles = <Vehicle[]>vehicles);
What is the exact compilation error you have?

AndroidAnnotations, REST and custom response

I'm using AndroidAnnotations in my project. This works fine so far...
But now I try to access a given Webservice with a custom response like this:
{
success: true,
total: 100,
items: [],
}
This response format is the same for every GET request. The items property holds the response objects I'm interested in and the items contains different object type(like user, product etc)
I'm using "MappingJackson2HttpMessageConverter"...
How can I access them?
Thanks,
Stefan
You have to create the response class, which can be deserialized from the JSON response:
public class CustomResponse {
boolean success;
int total;
List<Integer> items;
}
This is just an example, because it is ambigous from your JSON snippet, what exact types you are using.
Then you can use this response class in your REST client:
#Get("/getsomething")
public CustomResponse getSomething();
It is not necessary to use MappingJackson2HttpMessageConverter, you could use any converter which can convert your JSON response (like a GSON converter).