Flutter Firestore fromJson Return Null? - json

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;

Related

Dart/Flutter : convert BigInt to json

I have an object with a bigint property i want to encode to json string:
class Token {
Token(
{
this.name,
this.supply,
});
String? name;
BigInt? supply;
factory Token.fromJson(Map<String, dynamic> json) {
return Token(
name: json['name'],
supply: json['supply'] == null ? null : BigInt.parse(json['supply']),
);
}
Map<String, dynamic> toJson() => <String, dynamic>{
'name': name,
'supply': supply == null ? null : supply!.toString(),
};
}
I create a method to encode json to string...
String tokenToJson(Token data) => jsonEncode(data.toJson())
... but the format is not correct because i need a bigint in the format json and not a string:
the result i want:
{"name":"Token","supply":100000000000000,}
the result i obtain:
{"name":"Token","supply":"100000000000000",}
jsonEncode doesn't manage bigint type and i found on internet only solutions with a conversion of the bigint to a string type.
NB: Same issue with jsonDecode
Thx
use this simple method instead of BigInt use just "num"
import 'dart:convert';
void main() {
String data = '''{"name":"Token","supply":100000000000000}''';
print("supply: ${Token.fromJson(jsonDecode(data)).supply}");
}
class Token {
Token({
required this.name,
required this.supply,
});
late final String name;
late final num supply;
Token.fromJson(Map<String, dynamic> json){
name = json['name'];
supply = json['supply'];
}
Map<String, dynamic> toJson() {
final _data = <String, dynamic>{};
_data['name'] = name;
_data['supply'] = supply;
return _data;
}
}
Please check the following answer, instead of calling toString method on supply just call toInt method which will prevents the quotations and you will get the formatted json as expected
import 'dart:convert';
class Token {
Token(
{
this.name,
this.supply,
});
String? name;
BigInt? supply;
factory Token.fromJson(Map<String, dynamic> json) {
return Token(
name: json['name'],
supply: json['supply'] == null ? null :BigInt.from(json['supply']) ,
);
}
Map<String, dynamic> toJson() => <String, dynamic>{
'name': name,
'supply': supply == null ? null : supply!.toInt(),
};
String tokenToJson(Token data) => json.encode(data.toJson());
}
void main() {
Token token = Token(name: "token_one",supply : BigInt.parse("10000061234567"));
print(token.tokenToJson(token));
}
Output
{"name":"token_one","supply":10000061234567}
You don't need to parse, you can use from for convert int to BigInt
import 'dart:convert';
void main() {
String data = '''{"name":"Token","supply":100000000000000}''';
print(Token.fromJson(jsonDecode(data)).toJson());
}
class Token {
String? name;
double? supply;
Token({this.name, this.supply});
Token.fromJson(Map<String, dynamic> json) {
name = json['name'];
supply = json['supply'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['name'] = name;
data['supply'] = supply;
return data;
}
}

how to convert json to model class in dart like following image. It have digits of keyvalue header

the app.quicktype.io cannot convert.
they are converting and skip the digit class name
class ScoreCardModel {
bool? status;
String? msg;
Data? data;
ScoreCardModel({this.status, this.msg, this.data});
ScoreCardModel.fromJson(Map<String, dynamic> json) {
status = json['status'];
msg = json['msg'];
data = json['data'] = Data.fromJson(json['data']);
}
}
class Data {
String? result;
Scorecard? scorecard;
Data({this.result, this.scorecard});
Data.fromJson(Map<String, dynamic> json) {
result = json['result'];
scorecard = json['scorecard'] != null
? Scorecard.fromJson(json['scorecard'])
: null;
}
}
the quicktype cannot work with digits, I don't know why is this. I think they are in the developing stage. I Have the answer. I'm looking for the correct answer.
You can use https://jsontodart.com/, They are just including digit as model(Class) name. But You have to rename the model name like follows,
class 1 {
String score;
String wicket;
String ball;
1({this.score, this.wicket, this.ball});
1.fromJson(Map<String, dynamic> json) {
score = json['score'];
wicket = json['wicket'];
ball = json['ball'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['score'] = this.score;
data['wicket'] = this.wicket;
data['ball'] = this.ball;
return data;
}
}
to
class teamA {
String score;
String wicket;
String ball;
teamA({this.score, this.wicket, this.ball});
teamA.fromJson(Map<String, dynamic> json) {
score = json['score'];
wicket = json['wicket'];
ball = json['ball'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['score'] = this.score;
data['wicket'] = this.wicket;
data['ball'] = this.ball;
return data;
}
}

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

From json method in subclasses

I have a base class like:
class TransportationVehicle {
String name;
TransportationVehicle(this.name);
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['name'] = name;
return data;
}
}
And multiple sub-classes like:
class Bike extends TransportationVehicle {
int pedals;
Bike(String name, this.pedals) : super(name);
#override
Map<String, dynamic> toJson() {
final data = super.toJson();
data['pedals'] = pedals;
return data;
}
}
With that, I can transform a list of different types into a json string. But how would that work with fromJson functionality?
You can use the same idea from the toJson() method by using the base class.
import 'dart:convert';
class TransportationVehicle {
final String? name;
TransportationVehicle({
this.name,
});
factory TransportationVehicle.fromRawJson(String str) =>
TransportationVehicle.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory TransportationVehicle.fromJson(dynamic json) => TransportationVehicle(
name: json['name'] == null ? null : json['name'] as String,
);
Map<String, dynamic> toJson() => {
'name': name == null ? null : name,
};
}
class Bike extends TransportationVehicle {
final int? pedals;
Bike({
String? name,
this.pedals,
}) : super(name: name);
factory Bike.fromRawJson(String str) => Bike.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory Bike.fromJson(dynamic json) {
TransportationVehicle vehicle = TransportationVehicle.fromJson(json);
return Bike(
name: vehicle.name == null ? null : vehicle.name,
pedals: json['pedals'] == null ? null : json['pedals'] as int,
);
}
Map<String, dynamic> toJson() {
final data = super.toJson();
data['pedals'] = pedals == null ? null : pedals;
return data;
}
}

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;
}
}