How to customize json_serializable library code generation? - json

I use json_serializable library and firebase for database. I need to serialize and deserialize my data class to/from JSON. But firebase json format looks like this
{
'some_id_here': {
'title': 'some_title',
'content': 'some_content',
'timestamp': 'some_timestamp'
}, ...
}
Here's my class
import 'package:json_annotation/json_annotation.dart';
part 'update.g.dart';
#JsonSerializable()
class Update {
final String id, title, content, timestamp;
Update({this.id, this.title, this.content, this.timestamp});
factory Update.fromJson(Map<String, dynamic> json) => _$UpdateFromJson(json);
Map<String, dynamic> toJson() {
return _$UpdateToJson(this);
}
}
So how to customize the toJson() function so I can deserialize from
Update('ID', 'TITLE', 'CONTENT', 'TIMESTAMP');
to
{
'ID': {
'title': 'TITLE',
'content': 'CONTENT',
'timestamp': 'TIMESTAMP'
}
}

Try this
class ID {
String title;
String content;
String timestamp;
Map<String, dynamic> toJson() {
final Map<String, dynamic> ID = new Map<String, dynamic>();
ID['title'] = this.title;
ID['content'] = this.content;
ID['timestamp'] = this.timestamp;
return ID;
}
}

Related

Flutter Firestore fromJson Return Null?

I've been trying this but it keeps returning null where am I doing wrong?
class UserData {
final String? name;
UserData(
{this.name});
Map<String, dynamic> toJson() {
return {
'name': name,
};
}
UserData.fromJson(Map<String, dynamic> doc)
: this(name: doc['name']! as String);
factory UserData.fromDocument(DocumentSnapshot doc) {
return UserData.fromJson(doc.data() as Map<String, dynamic>);
}
}
and im trying like that
factory UserData.fromDocument(DocumentSnapshot doc) {
Map<String, dynamic> data = doc.data() as Map<String, dynamic>;
print(data['name']); // data is retuning correct
UserData user = UserData.fromJson(doc.data() as Map<String, dynamic>);
print(user.name); // data is returning null
return UserData.fromJson(doc.data() as Map<String, dynamic>);
}
Change this:
UserData.fromJson(Map<String, dynamic> doc)
: this(name: doc['name']! as String);
to, because this() would return a completely new class instance:
UserData.fromJson(Map<String, dynamic> doc)
: name = doc['name']! as String;

Parsing json array response / flutter

Did this according to this manual
https://www.bezkoder.com/dart-flutter-parse-json-string-array-to-object-list/
Dart/Flutter parse array of JSON objects into List
JSON that comes from the server
{"myChannels":[{"id":"2","name":"channel2test","imageUrl":"image1.png"},{"id":"2","name":"channel2test","imageUrl":"image2.png"}]}
Model Class
class ChannelModel {
String channelID;
String channelName;
String imageUrl;
ChannelModel(this.channelID, this.channelName, this.imageUrl);
factory ChannelModel.parsingChannels(dynamic json) {
return ChannelModel(json['channelID'] as String,
json['channelName'] as String, json['imageUrl'] as String);
}
#override
String toString() {
return '{ ${this.channelID}, ${this.channelName}, ${this.imageUrl} }';
}
}
Main block
try {
final response = await http.post(
url,
body: json.encode({
'action': 'getMyChannels',
'userID': userID,
'returnSecureToken': true,
}),
);
// print(jsonDecode(response.body));
var extractedData =
jsonDecode(response.body)['myChannels'] as List<dynamic>;
List<ChannelModel> channelObjects = extractedData
.map((cJson) => ChannelModel.parsingChannels(cJson))
.toList();
print(channelObjects);
channelObjects.forEach((Data) {
print('test');
});
the results is the following...
print(channelObjects) > outputs > []
print('test') > not working , channelObjects not looping
I would suggest serializing your response to dart classes. It would be much easier to access the data you want.
class ApiResponse {
ApiResponse({
required this.myChannels,
});
List<MyChannel> myChannels;
factory ApiResponse.fromJson(Map<String, dynamic> json) => ApiResponse(
myChannels: List<MyChannel>.from(
json["myChannels"].map((x) => MyChannel.fromJson(x)),
),
);
}
class MyChannel {
MyChannel({
required this.id,
required this.name,
required this.imageUrl,
});
String id;
String name;
String imageUrl;
factory MyChannel.fromJson(Map<String, dynamic> json) => MyChannel(
id: json["id"],
name: json["name"],
imageUrl: json["imageUrl"],
);
}
Then you can use it this way :
final extractedData = ApiResponse.fromJson(json.decode(response.body) as Map<String, dynamic>);
And access the data you want
extractedData.myChannels[0].id
extractedData.myChannels[0].name
extractedData.myChannels[0].imageUrl
for (var ch in extractedData.myChannels){
print(ch.id);
print(ch.name);
print(ch.imageUrl);
}
part 'example.g.dart';
#JsonSerializable()
class Channel{
final String id;
final String name;
final String? imageUrl;
Channel({required this.id, required this.name, this.imageUrl});
factory Channel.fromJson(Map<String, dynamic> json) => _$ChannelFromJson(json);
Map<String, dynamic> toJson() => _$ChannelToJson(this);
}
#JsonSerializable()
class ChannelList{
final List<Channel> myChannels;
ChannelList({required this.myChannels});
factory ChannelList.fromJson(Map<String, dynamic> json) => _$ChannelListFromJson(json);
Map<String, dynamic> toJson() => _$ChannelListToJson(this);
}
final extractedData = ChannelList.fromJson(json.decode(response.body));
https://pub.dev/packages/json_serializable
Using JsonSerializable more useful and understandable. You can read documentation of that package

Flutter error: the argument type 'dynamic' can't be assigned to the parameter type 'Iterable<dynamic>'

Kindly assist.
I am attempting to create a model using the JSON to Dart tool https://app.quicktype.io/
The aim is to retrieve a list of all companies (with their properties) from a JSON API.
I am getting the below errors:
the argument type 'dynamic' can't be assigned to the parameter type Map<String, dynamic>
the argument type 'dynamic' can't be assigned to the parameter type Iterable
the argument type 'dynamic' can't be assigned to the parameter type Int
Please refer to the image below.
the argument type 'dynamic' can't be assigned to the parameter type...
Thank you.
I have tested this class and it works without errors
import 'dart:convert';
CompanyModel companyModelFromJson(String str) => CompanyModel.fromJson(json.decode(str));
String companyModelToJson(CompanyModel data) => json.encode(data.toJson());
class CompanyModel {
CompanyModel({
this.companies,
});
List<Company> companies;
factory CompanyModel.fromJson(Map<String, dynamic> json) => CompanyModel(
companies: List<Company>.from(json["companies"].map((x) => Company.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"companies": List<dynamic>.from(companies.map((x) => x.toJson())),
};
}
class Company {
Company({
this.id,
this.name,
});
int id;
String name;
factory Company.fromJson(Map<String, dynamic> json) => Company(
id: json["id"],
name: json["name"],
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
};
}
As alternative you can use this code from JsonToDart
class CompanyModel {
List<Companies> companies;
CompanyModel({this.companies});
CompanyModel.fromJson(Map<String, dynamic> json) {
if (json['companies'] != null) {
companies = new List<Companies>();
json['companies'].forEach((v) {
companies.add(new Companies.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.companies != null) {
data['companies'] = this.companies.map((v) => v.toJson()).toList();
}
return data;
}
}
class Companies {
int id;
String name;
Companies({this.id, this.name});
Companies.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['name'] = this.name;
return data;
}
}

JSON Encode/Decode List with json_serializable

I'm using the packages: https://pub.dev/packages/json_annotation, https://pub.dev/packages/json_serializable
I want to encode/decode a list of objects in my flutter app. The class which is in the list is as follows:
#JsonSerializable()
class Trial {
final ProtocolType type;
List<List<double>> data;
#JsonKey()
final DateTime date;
Trial({this.type, this.data, this.date});
Map<String, dynamic> toMap() {
return {'type': this.type, 'data': this.data, 'date': this.date};
}
factory Trial.fromJson(Map<String, dynamic> json) => _$TrialFromJson(json);
Map<String, dynamic> toJson() => _$TrialToJson(this);
}
I want to decode/encode a list of these items, and I couldn't figure out how else to do it so I made a new class:
#JsonSerializable()
class TrialList {
final List<Trial> trials;
TrialList({this.trials});
factory TrialList.fromJson(List json) => _$TrialListFromJson(json);
List toJson() => _$TrialListToJson(this);
}
Notice the List toJson() in this new class. It seems Json_serializable only wants me to decode/encode maps, is there any way to support lists?
Solution:
#JsonSerializable()
class TrialList {
final List<Trial> trials;
TrialList({this.trials});
factory TrialList.fromJson(json) => _$TrialListFromJson({'trials': json});
List toJson() => _$TrialListToJson(this)['trials'];
}
credit to Null from the /r/FlutterDev discord

Dart: converting _InternalLinkedHashMap<dynamic, dynamic> in constructor fails

I am new to Dart and trying to deserialize some json, but I can't quite figure out the trick.
I am able to cast the Map in main as shown, but the commented code does not work and I can't figure out why. I feel like there must be an easier way to do this (outside of using a package for code generation), but I'm not sure what that is.
import 'dart:convert';
import 'dart:io';
class Book {
final String title;
final String path;
Book(this.title, this.path);
Book.fromJson(Map<String, dynamic> content)
: title = content['title'],
path = content['path'];
Map<String, dynamic> toJson() =>
{
'title': title,
'path': path,
};
String toString() {
return '{ title: $title, path: $path }';
}
}
class Books {
final Map<String, Book> bookList;
Books(this.bookList);
// Books.fromJson(Map<String, dynamic> content)
// : bookList = Map<String, Book>.from(jsonDecode(jsonDecode(content)['books']).map((k,v) => MapEntry(k as String, Book.fromJson(v))));
Map<String, dynamic> toJson() =>
{
'books': jsonEncode(bookList),
};
String toString() {
return bookList.toString();
}
}
void main() {
Map<String, Book> bookList = {
"foo": Book("Foo", "/foo"),
"bar": Book("Bar", "/bar"),
};
Books books = Books(bookList);
print(books);
String content = jsonEncode(books);
print(content);
// print(Books.fromJson(jsonDecode(content)));
Map<String, Book> m = Map<String, Book>.from(jsonDecode(jsonDecode(content)['books']).map((k,v) => MapEntry(k as String, Book.fromJson(v))));
print(m);
}
Oops, I needed to remove an invocation of jsonDecode from Books.fromJson...
Books.fromJson(Map<String, dynamic> content)
: bookList = Map<String, Book>.from(jsonDecode((content)['books']).map((k,v) => MapEntry(k as String, Book.fromJson(v))));