Converting dynamic JSON in flutter to models - json

Converting a JSON to model would be a straight forward process. Let's consider a simple JOSON string as seen below;
jsonData ={'id':'1','name':'modelItem'}
It can be converted to model using below model class.
class Model{
final String? id;
final String? name;
Model({this.id,this.name});
}
But what about below JSON string?
jsonData= {'NYC':{'city code':'NYC','country code':'US'}}
Or another string like below?
jsondata= {'NYC': {'NYC':'NEW YORK'}}

Following is the solution for converting first JSON string
jsonData= {
'NYC':{'cityCode':'NYC','countryCode':'US'},
'SYD':{'cityCode':'SYD','countryCode':'AU'}
}
Solution for jsonData= {'NYC':{'city code':'NYC','country code':'US'}}
No matter how nested the JSON string data is, create a model class to convert inner map first. And then, try to work on the outer layer and so on.
class CityDetails{
final String? cityCode;
final String? countryCode;
CityDetails({this. cityCode, this. countryCode});
CityDetails.fromJson(Map<String,dynamic> parsedJson) {
for(var element in parsedJson.entries){
CityDetails(cityCode:element.key, countryCode:element.value);
}
}
}
Now, let's work on the outer layer which should give a list of CityDetails. Same method can be applied. However, here city code is repeated in the outer layer and it can be ignored. So the result should look like a List<CityDetails>.
class CityDataList{
final List<CityDetails> cityDetailsList;
CityDataList({this.cityDetailsList});
factory CityDataList.fromJson(Map<String,dynamic> parsedJson){
List<CityDetails> cityDetailsList=[];
for(var element in parsedJson.entries){
cityDetailsList.add(CityDetails(cityCode:element.key,
countryCode:element.value));
}
return CityDataList(cityDetailsList: cityDetailsList);
}
}
Solution for jsondata= {'NYC': {'NYC':'NEW YORK'}}. Solution for first problem would help to convert the outer JSON here, so it is not repeated here. Following helps to convert the inner JSON into a meaningful class.
class CityData{
final String? cityCode;
final String? cityName;
CityData({this.cityCode,this.cityName});
CityData.fromJson(Map<String,dynamic> parsedJson){
for(each element in parsedJson.entries){
CityData(citycode:element.key,cityName:element.value);
}
}
}

Related

how #JsonKey(toJson: toJSON_SalesInvoiceDetail,) function works in flutter Jsonserializable

I am new to this serialization, I am facing a hard time understanding the difference between these two functionalities while serialization in dart/flutter #JsonKey(name: invoice) && #JsonKey(toJson: toJSON_SalesInvoiceDetail)
I see my friend wrote this below function outside the class for the above json key #JsonKey(toJson: toJSON_SalesInvoiceDetail) as I see this maps another class so it's kind of embedding one class into another but I do not know how this serialization is happening under the hood, could anyone guide me about this pls, Your help will be appreciated a lot, thanks in advance
The param toJson changes the value of JSON(only the method toJson), and the param name changes the key (both of the methods toJson and fromJson).
For example, I made a class like the following.
#JsonSerializable()
class Any {
const Any(this.param);
factory Any.fromJson(Map<String, dynamic> json) => _$AnyFromJson(json);
#JsonKey(name: 'json_key_of_param', toJson: paramToJson)
final int param;
Map<String, dynamic> toJson() => _$AnyToJson(this);
}
String paramToJson(int paramValue) {
return 'param value is $paramValue';
}
And if we use this like
print(const Any(100).toJson());
then printed the following.
{json_key_of_param: param value is 100}
In this case, I didn't specify the param fromJson, so we should use the method fromJson like the following.
Any.fromJson(<String, dynamic>{'json_key_of_param': 100});

How to implement an image in a JsonSerializable model class

I need to be able to retrieve and also to store an image using an API. For my model classes I'm using #JsonSerializable.
What I'm struggling with is the data type to use for the image in my model. From the API I get a base64 encoded string, the image_picker plugin gives me a File.
What's the best way to implement this in my model? I could imagine to use a String (base64 encoded) as this is what I get from the API. It should also not be to hard to get the base64 representation from the File I get from image_picker.
Would be great to also have the fromJson and toJson functions for the solution as I had issues with those implementing some of my ideas.
You can serialize/deserialize the model objects by doing something as below.
class Doughnut {
final String name;
final String filling;
final String topping;
final double price;
Doughnut(this.name, this.filling, this.topping, this.price);
Doughnut.fromJson(Map<String, dynamic> json)
: name = json['name'],
filling = json['filling'],
topping = json['topping'],
price = json['price'];
Map<String, dynamic> toJson() => {
'name' : name,
'filling' : filling,
'topping' : topping,
'price' : price
};
}
You can refer to this source for serializing and deserializing your model objects.
As far as the Image serialization is concerned, you should go with the base64 string approach. it will be easy to serialize an image this way along with other data.
Edit:
if the serialization in base64 string is not preferred, then what you can do is store the image to device storage and just store the path of the image when serializing, but in this you'll have to do two processes:
Get storage permission for the app
Check for file when deserializing, You'll need to handle resulting scenario as per your requirements.
I hope it helps.

Use JSON.decode() in dart to instantiate class from json string

By browsing around I did successfully manage to create a class that can "opt in" dat:convert by exposing a Map toJson() method and can be json-ified with JSON.encode(myClass), more or less like the following:
//My dummy class
class MyClass{
String p1;
String p2;
Map toJson{
return {
'p1':this.p1,
'p2':this.p2
}
}
}
//so I can do
String jsonString = JSON.encode(myClass)
However I'd like to do this even the other way around, like:
String jsonString = '{"p1":"value","p2":"value"}'
MyClass instance = JSON.decode(jsonString)
But so far I've failed to find a way.
I know I can build a constructor for my class that initialises it from a map, something like:
String jsonString = '{"p1":"value","p2":"value"}'
MyClass instance = MyClass.fromMap(JSON.decode(jsonString))
However I was looking for a more "symmetric" way using just JSON.encode() and JSON.decode(), is it somehow doable? Am I missing something?
There is no standard way to encode the class in JSON. {"p1":"value","p2":"value"} doesn't contain any information about what class to instantiate. There is also no standard way to create a new class from as string (what library should be used when several contain a class with the same name, ...
As far as I know a reviver can be used for that purpose
reviver(var key, var value) {
// decode manually
}
final jsonDecoder = new JsonDecoder(reviver);
but the reviver would need to have some hardcoded logic how to recognize what JSON should result in what Dart class and how it should instantiate it and initialize the properties from the JSON.

Dart - How to get Json object from Complex object Hierarchy

On Continuation to following SO Question/Answer :-
How to get JSON serialized string using Dart Serialization
I want to serialize complex object values in JSON, how can I achieve that using:-
Map toJson() { }
My class heirarchy is :-
class Container {
Containerthis.DPC_ID);
String get Id => DPC_ID;
String get LSDetailUrl => "http://www.indiavotes.com/pc/detail/$DPC_ID/$DB_STATEID/15";
List<GoogleMaps.LatLng> Coordinates;
List<LSElectionResult> ElectionData;
var DPC_ID;
// how to extend following method to serialize complex inner objects too?
Map toJson() {
return {"id": DPC_ID, "ElecData2009": ElectionData};
}
}
class LSElectionResult {
String get WinnerName => DWIN_NM;
String get WinnerParty => DWIN_PRT;
}
Here the first collection - GoogleMaps.LatLng is external class, but I want to serialize it too. But second collection member ElectionData is of my own class LSElectionResult, If I write Map toJson() implementation for LSElectionResult, will it be called automatically if I call Container.toJson() ?
I am going to compile this to JS.

Jackson Serialize and Deserialize String property as JSON

I have a model that looks like this (Play 2.1.1 java ebean)
#Entity
public class Link extends Model {
#Id
public Long id;
#Lob
public String points;
}
where points is a raw json string that contains x, y coordinates in an array.
I don't want to have to deserialize it to an array of Points, because it's only going to be used for the UI. and thus, I would like to save it to a text field in the database
I want the property points to get serialized as a json array when sent over the wire to the frontend and I want the frontend to be able to send an json array and make it into a string again.
In the controller:
// Serialize
List<Link> links = Link.findAll();
return ok(Json.toJson(links));
// Deserialize
Link link = Json.fromJson(request().body().asJson(), Link.class);
How should I do this?
Custom serializer, deserializer?
#JsonRawValue?
Any other annotation?
The answer was a lot simpler than you would suspect.
#Lob
public String points;
public JsonNode getPoints() {
return Json.parse(StringUtils.isBlank(points) ? "[]" : points);
}
#JsonSetter
public void setPoints(JsonNode json) {
points = json.toString();
}
Though I'm not that fond of getter's and setter's it works.
If anyone has a better solution that is more generic, feel free to post another answer :)