Database Exception Error SQLLITE and FLUTTER - mysql

Can I get some help with this please...I am getting error like
1) near "VALUES": syntax error
I/flutter ( 6415): DatabaseException(near "VALUES": syntax error (code 1 SQLITE_ERROR): , while compiling: INSERT INTO words (
here is my dart model code..it says something is wrong here
[Here][1]
Wordtable is my SQLite model where I'm saving the data and Word is my backend model where I'm fetching the data to save into SQLite one
I tried to make it short and precise as possible so please do let me know if any further clarification is needed.
Thank you and happy new year
class WordList {
List<Word>? words;
WordList({this.words});
factory WordList.fromJson(List<dynamic> json, String lang) {
List<Word> words = json.map((i) => Word.fromJson(i, lang)).toList();
return new WordList(
words: words,
);
}
}
class WordTableList {
final List<WordTable>? words;
WordTableList({this.words});
factory WordTableList.fromJson(List<dynamic> json) {
List<WordTable> words = json.map((e) => WordTable.fromMap(e)).toList();
return new WordTableList(
words: words,
);
}
}
////////////////////WordTable SQLLITE/////////////////////
class WordTable {
static String table = 'words';
int? WORD_ID;
String? TINA;
String? LETTER;
String? NABA;
String? ITAVI;
String? LOMANIBAI;
String? DEWA;
String? IVAKAMACALA;
String? COKE;
String? IDUSIDUSI;
// String? LINKED_SYN;
String? IVOSAVOSA;
String? ITAKATAKA;
String? VOSA_VAKALATINA;
String? WORDIMG;
String? MAIN_AUDIO;
String? STORY_AUDIO;
WordTable.fromJson(Map<String, dynamic> json) {
this.WORD_ID = json['word_id'];
this.TINA = json['tina'];
this.LETTER = json['letter'];
this.NABA = json['naba'];
this.ITAVI = json['itavi'];
this.LOMANIBAI = json['lomanibai'];
this.DEWA = json['dewa'];
this.IVAKAMACALA = json['ivakamacala'];
this.COKE = json['coke'];
this.IDUSIDUSI = json['idusidusi'];
//this.LINKED_SYN = json['ivosavosa'];
this.IVOSAVOSA = json['ivosavosa'];
this.ITAKATAKA = json['itakataka'];
this.VOSA_VAKALATINA = json['vosa_vakalatina'];
this.WORDIMG = json['word_main_image'];
this.MAIN_AUDIO = json['word_main_audio'];
this.STORY_AUDIO = json['story_audio'];
// if (json['family'] != null) {
// this.plantFamily = PlantFamily.fromJson(json['family']);
// }
}
WordTable.fromMap(Map<String, dynamic> json) {
this.WORD_ID = json['word_id'] == null ? 0 : json['word_id'];
this.TINA =
json['tina'] == null ? "No Scientific Name Available" : json['tina'];
this.LETTER =
json['letter'] == null ? "No Local Name Available" : json['letter'];
this.NABA = json['naba'] == null
? "storage/images/13293205681610263850.png"
: json['naba'];
this.ITAVI =
json['itavi'] == null ? "No Description Available" : json['itavi'];
this.LOMANIBAI = json['lomanibai'] == null
? "No Description Available"
: json['lomanibai'];
this.DEWA =
json['dewa'] == null ? "No Distribution Available" : json['dewa'];
this.IVAKAMACALA = json['ivakamacala'] == null
? "No Distribution Available"
: json['ivakamacala'];
this.COKE =
json['coke'] == null ? "No Distribution Available" : json['coke'];
this.IDUSIDUSI = json['idusidusi'] == null
? "No Description Available"
: json['idusidusi'];
this.IVOSAVOSA = json['ivosavosa'] == null
? "No Description Available"
: json['ivosavosa'];
this.ITAKATAKA = json['itakataka'] == null
? "No Description Available"
: json['itakataka'];
this.VOSA_VAKALATINA = json['vosa_vakalatina'] == null
? "No Description Available"
: json['vosa_vakalatina'];
this.WORDIMG = json['word_main_image'] == null
? "No Description Available"
: json['word_main_image'];
this.MAIN_AUDIO = json['word_main_audio'] == null
? "No Description Available"
: json['word_main_audio'];
this.STORY_AUDIO = json['story_audio'] == null
? "No Description Available"
: json['story_audio'];
// this.hpfMedicalUseOtherFj = json['hpf_medical_use_other_fj'] == null
// ? "No Description Available"
// : json['hpf_medical_use_other_fj'];
// if (json['plant_family'] != null) {
// print('family is not null');
// this.plantFamily = new PlantFamily(
// bookChapterId: 0,
// hpfBotanicalCat: json['plant_botanical_category'],
// hpfBotanicalSubCat: json['plant_sub_botanical_category'],
// hpfFamilyName: json['plant_family'],
// id: 0);
//}
}
static String plantTableQuery(WordTable words) {
return ''' INSERT INTO words (
word_id,
tina,
letter,
naba,
itavi,
lomanibai,
dewa,
ivakamacala,
coke,
idusidusi,
ivosavosa,
itakataka,
vosa_vakalatina,
word_main_image,
word_main_audio,
story_audio,
VALUES (
'${words.WORD_ID}',
'${words.TINA}',
'${words.LETTER}',
'${words.NABA}',
'${words.ITAVI}',
'${words.LOMANIBAI}',
'${words.DEWA}',
'${words.IVAKAMACALA}',
'${words.COKE}',
'${words.IDUSIDUSI}',
'${words.IVOSAVOSA}',
'${words.ITAKATAKA}',
'${words.VOSA_VAKALATINA}',
'${words.WORDIMG}',
'${words.MAIN_AUDIO}',
'${words.STORY_AUDIO}'
)''';
}
static const String CREATE_TABLE = '''CREATE TABLE IF NOT EXISTS words (
word_id INTEGER PRIMARY KEY,
tina TEXT,
letter TEXT,
naba TEXT,
itavi TEXT,
lomanibai TEXT,
dewa TEXT,
ivakamacala TEXT,
coke TEXT,
idusidusi TEXT,
ivosavosa TEXT,
itakataka TEXT,
vosa_vakalatina TEXT,
word_main_image TEXT,
word_main_audio TEXT,
story_audio TEXT,
)''';
static const String DELETE_TABLE = 'DROP TABLE IF EXISTS words';
}
//////////////////////////////WordTable SQLLITE END////////////////////////////////
class Word {
static String table = 'words';
int? WORD_ID;
String? TINA;
String? LETTER;
String? NABA;
String? ITAVI;
String? LOMANIBAI;
String? DEWA;
String? IVAKAMACALA;
String? COKE;
String? IDUSIDUSI;
String? LINKED_SYN;
String? IVOSAVOSA;
String? ITAKATAKA;
String? VOSA_VAKALATINA;
String? WORDIMG;
String? MAIN_AUDIO;
String? STORY_AUDIO;
Word(
{this.WORD_ID,
this.TINA,
this.LETTER,
this.NABA,
this.ITAVI,
this.LOMANIBAI,
this.DEWA,
this.IVAKAMACALA,
this.COKE,
this.IDUSIDUSI,
this.LINKED_SYN,
this.IVOSAVOSA,
this.ITAKATAKA,
this.VOSA_VAKALATINA,
this.WORDIMG,
this.MAIN_AUDIO,
this.STORY_AUDIO});
factory Word.fromJson(Map<String, dynamic> json, String lang) {
return Word(
WORD_ID: json['word_id'] ?? "0",
TINA: json['tina'] ?? "",
LETTER: json['letter'] ?? "",
NABA: json['naba'] ?? "0",
ITAVI: json['itavi'] ?? "0",
LOMANIBAI: json['lomanibai'] ?? "",
DEWA: json['dewa'] ?? "",
IVAKAMACALA: json['ivakamacala'] ?? "No Description Provided",
COKE: json['coke'] ?? "",
IDUSIDUSI: json['idusidusi'] ?? "",
IVOSAVOSA: json['ivosavosa'] ?? "",
ITAKATAKA: json['itakataka'] ?? "",
VOSA_VAKALATINA: json['vosa_vakalatina'] ?? "",
WORDIMG: json['word_main_image'] ?? "",
MAIN_AUDIO: json['word_main_audio'] ?? "",
STORY_AUDIO: json['story_audio'] ?? "");
}
}

The query in plantTableQuery is incomplete:
INSERT INTO words (
...
word_main_audio,
story_audio,
VALUES (
'${words.WORD_ID}',
'${words.TINA}',
... ```
SQLite has diagrams on their website that show the syntax of commands. They show you that in a CREATE TABLE query:
the column-names should be enclosed in brackets (you don't have a closing bracket ))
there are commas between column-names, but there can't be one before the closing bracket ).
The CREATE TABLE diagram shows you that the query in variable CREATE_TABLE may not have a comma before the closing bracket ) that encloses the column-defs, either:
...
word_main_audio TEXT,
story_audio TEXT,
)

You have a syntax error in your INSERT query near values.
Insert should be in this format
INSERT INTO table (column1,column2 ,..)
VALUES( value1, value2 ,...);
You are missing closing brackets just after column story_audio.
static String plantTableQuery(WordTable words) {
return ''' INSERT INTO words (
word_id,
tina,
letter,
naba,
itavi,
lomanibai,
dewa,
ivakamacala,
coke,
idusidusi,
ivosavosa,
itakataka,
vosa_vakalatina,
word_main_image,
word_main_audio,
story_audio)
VALUES(
'${words.WORD_ID}',
'${words.TINA}',
'${words.LETTER}',
'${words.NABA}',
'${words.ITAVI}',
'${words.LOMANIBAI}',
'${words.DEWA}',
'${words.IVAKAMACALA}',
'${words.COKE}',
'${words.IDUSIDUSI}',
'${words.IVOSAVOSA}',
'${words.ITAKATAKA}',
'${words.VOSA_VAKALATINA}',
'${words.WORDIMG}',
'${words.MAIN_AUDIO}',
'${words.STORY_AUDIO}'
)''';
}

Related

NoSuchMethodError : The method 'map' was called on null. Plz Provide the Solution

I am trying to parse data from a Rest API inside a Dart/Flutter application.
The JSON contains a field called data at the root, which contains a list of Words.
I want to get a List<ArticalList> from this JSON giving json["data"].map((x) => ArticalList.fromJson(x))
I already have the following code:
import 'dart:convert';
Welcome welcomeFromJson(String str) => Welcome.fromJson(json.decode(str));
String welcomeToJson(Welcome data) => json.encode(data.toJson());
class Welcome {
Welcome({
required this.code,
required this.status,
required this.message,
required this.data,
});
final int code;
final String status;
final String message;
final List<ArticalList> data;
factory Welcome.fromJson(Map<String, dynamic> json) => Welcome(
code: json["code"] ?? 0,
status: json["status"] ?? '',
message: json["message"] ?? '',
data: List<ArticalList>.from(json["data"].map((x) => ArticalList.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"code": code,
"status": status,
"message": message,
"data": List<dynamic>.from(data.map((x) => x.toJson())),
};
}
class ArticalList {
ArticalList({
required this.id,
required this.title,
required this.detail,
required this.image,
});
int id;
String title;
String detail;
String image;
factory ArticalList.fromJson(Map<String, dynamic> json) => ArticalList(
id: json["id"] == null ? 0 : json["id"],
title: json["title"] == null ? '' : json["title"],
detail: json["detail"] == null ? '' : json["detail"],
image: json["image"] ?? 'http://eduteksolutions.in/images/logo.jpeg',
);
Map<String, dynamic> toJson() => {
"id": id == null ? null : id,
"title": title == null ? null : title,
"detail": detail == null ? null : detail,
"image": image,
};
}
I think your getting error at
data: List<ArticalList>.from(json["data"].map((x) => ArticalList.fromJson(x))),
I create a function with null safety which accept map and return object list
static List<ArticalList> toListFormMap({
Map? map,
}) {
if (map?.isEmpty ?? true) return [];
List<ArticalList> items = [];
map?.forEach((key, data) {
final ArticalList item = ArticalList.fromJson(data);
items.add(item);
});
return items;
}
and same method which convert map to Map
static Map toMapList(List<ArticalList>? items) {
Map map = {};
items?.forEach((element) {
map[element.id] = element.toJson();
});
return map;
}
for both case it handle null data error and also convert Object List to Map list and Map list to Object list.
I hope it will be helpful.

How to parse dynamic JSON keys in dart

I have an API that returns JSON with dynamic keys, i.e. the key value changes on every GET request.
Ex: This is the format of the JSON.
I have a book model in dart,
class Book {
String id = "";
String title = "";
Book();
Book.fromJson(Map<String, dynamic> json) {
id = json['id'];
title = json['title'];
}
static List<Book> listFromJson(List<dynamic> json) {
return json.map((val) => Book.fromJson(val)).toList();
}
}
and JSON response,
{
"Recommended For You" : [
{
"id" : "001",
"title" : "title001"
},
...
],
"Thrillers" : [
{
"id" : "005",
"title" : "title005"
},
...
]
}
How to parse this into lists of books according to the genre, given that genres (like Thrillers) can change(i.e. it is dynamic and may change for each user)?
Edit 1
Thrillers and Recommended For You aren't constant, some times it may change to Horror and Romantic or something else. It is dynamic
Edit 2 : The solution
Thanks to #lrn's solution, I came up with a new Class
class Recommendations {
String recommendationType;
List<Book> recommendations;
#override
String toString() {
return 'Recomendations[title: $recommendationType]';
}
Recommendations.fromJson(MapEntry<String, dynamic> json) {
if (json == null) return;
this.recommendationType = json.key;
this.recommendations = Book.listFromJson(json.value);
}
static List<Recommendations> listFromJson(Map<String, dynamic> json) {
return json == null
? List<Recommendations>.empty()
: json.entries
.map((value) => new Recommendations.fromJson(value))
.toList();
}
}
If you don't know the keys, but do know that it's a JSON map where the values are the book lists you're looking for, I'd write:
List<Book> parseCategorizedBooksJson(Map<String, dynamic> json) =>
[for (var books in json.values) ...Book.listFromJson(books)];
or
List<Book> parseCategorizedBooksJson(Map<String, dynamic> json) =>
[for (var books in json.values)
for (var book in books) Book.fromJson(book)];
(which avoids building intermediate lists of books).
With this you simply iterate the values of the outer map, and ignore the keys. JSON maps are just plain Dart Maps and you can access the keys as .keys (and then go trough them without needing to known them ahead of time) and access the values as .values (and completely ignore the keys).
Each value is a list of books, which you can parse using your existing static functions.
To include the genre, you have to say how you want the genre remembered. The simplest is to retain the data as a map:
var categoriedBooks = {for (var genre in json)
genre: Book.listFromJson(json[genre])
};
This builds a map with the same keys (the genres), but where the values are now lists of Books.
Your response model contains two different arrays, recommendedForYou and thrillers. So, you can handle it like this:
// To parse this JSON data, do
//
// final responseModel = responseModelFromJson(jsonString);
import 'dart:convert';
ResponseModel responseModelFromJson(String str) => ResponseModel.fromJson(json.decode(str));
String responseModelToJson(ResponseModel data) => json.encode(data.toJson());
class ResponseModel {
ResponseModel({
this.recommendedForYou,
this.thrillers,
});
List<Book> recommendedForYou;
List<Book> thrillers;
factory ResponseModel.fromJson(Map<String, dynamic> json) => ResponseModel(
recommendedForYou: json["Recommended For You"] == null ? null : List<Book>.from(json["Recommended For You"].map((x) => Book.fromJson(x))),
thrillers: json["Thrillers"] == null ? null : List<Book>.from(json["Thrillers"].map((x) => Book.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"Recommended For You": recommendedForYou == null ? null : List<dynamic>.from(recommendedForYou.map((x) => x.toJson())),
"Thrillers": thrillers == null ? null : List<dynamic>.from(thrillers.map((x) => x.toJson())),
};
}
class Book {
Book({
this.id,
this.title,
});
String id;
String title;
factory Book.fromJson(Map<String, dynamic> json) => Book(
id: json["id"] == null ? null : json["id"],
title: json["title"] == null ? null : json["title"],
);
Map<String, dynamic> toJson() => {
"id": id == null ? null : id,
"title": title == null ? null : title,
};
}
You can use this site to convert your json to any dart model.

Get data from JSON in flutter

I am using the following code to verify stock data:
Future<Stock> verifyIfStockSymbolIsValid(String symbol) async {
final response =
await http.get('https://cloud.iexapis.com/stable/stock/$symbol/quote?token=my-token');
if (response.statusCode == 200) {
// Get Map from JSON.
Map data = json.decode(response.body);
print(data); // here the data (output below) is printed!
Map quoteData = data['quote'];
Stock stockQuote = Stock.fromJson(quoteData); // here should be the problem
return stockQuote;
} else {
return null;
}
}
The output looks like this:
I/flutter ( 9290): {symbol: XOM, companyName: Exxon Mobil Corp., primaryExchange: NEW YORK STOCK EXCHANGE, INC., calculationPrice: tops, open: null, openTime: null, openSource: official, close: null, closeTime: null, closeSource: official, high: null, highTime: 1608044090030, highSource: 15 minute delayed price, low: null, lowTime: 1608044281245, lowSource: IEX real time price, latestPrice: 42.52, latestSource: IEX real time price, latestTime: 10:09:34 AM, latestUpdate: 1608044974460, latestVolume: null, iexRealtimePrice: 42.52, iexRealtimeSize: 100, iexLastUpdated: 1608044974460, delayedPrice: null, delayedPriceTime: null, oddLotDelayedPrice: null, oddLotDelayedPriceTime: null, extendedPrice: null, extendedChange: null, extendedChangePercent: null, extendedPriceTime: null, previousClose: 42.22, previousVolume: 30595042, change: 0.3, changePercent: 0.00711, volume: null, iexMarketPercent: 0.01788127392568208, iexVolume: 65063, avgTotalVolume: 30683847, iexBidPrice: 41.99, iexBidSize: 100, iexAskPrice: 42.51, iexAskSize: 400, iexOpen: 42.475, iexOpenTime: 1608052428625, iexClose: 42.475, iexCloseTime: 1608052428625, marketCap: 179594243992, peRatio: 54.63, week52High: 65.66, week52Low: 29.54, ytdChange: -0.3405948289133432, lastTradeTime: 1608052428625, isUSMarketOpen: true}
E/flutter ( 9290): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: NoSuchMethodError: The method '[]' was called on null.
E/flutter ( 9290): Receiver: null
E/flutter ( 9290): Tried calling:
And my stock class is looking like that:
class Stock {
final String companyName;
final String symbol;
// The following are dynamic as using double generates an error
// when the API returns values with no decimal (e.g. 12 vs 12.0).
final dynamic latestPrice;
final dynamic low;
final dynamic high;
final dynamic week52High;
final dynamic change;
final dynamic changePercent;
final dynamic peRatio;
final dynamic previousClose;
// Default constructor.
Stock(this.companyName, this.symbol, this.latestPrice,
this.low, this.high, this.week52High, this.change,
this.changePercent, this.peRatio, this.previousClose);
// Named constructor, create object from JSON.
Stock.fromJson(Map<String, dynamic> json)
: companyName = (json['companyName'] != null ? json['companyName'] : ""),
symbol = (json['symbol'] != null ? json['symbol'] : ""),
latestPrice = (json['latestPrice'] != null ? json['latestPrice'] : 0.0),
low = (json['low'] != null ? json['low'] : 0.0),
high = (json['high'] != null ? json['high'] : 0.0),
week52High = (json['week52High'] != null ? json['week52High'] : 0.0),
change = (json['change'] != null ? json['change'] : 0.0),
changePercent = (json['changePercent'] != null ? json['changePercent'] : 0.0),
peRatio = (json['peRatio'] != null ? json['peRatio'] : 0.0),
previousClose = (json['previousClose'] != null ? json['previousClose'] : 0.0);
}
How can I solve this?
final data = json.decode(response.body) as Map;
print(data); // here the data (output below) is printed!
final quoteData = data['quote'] as Map;
Casting is imp , try this and let me know too..
replace only 3 lines above

How to define a model with a property that can be both null or another model in Dart

I am building a Flutter app and have some trouble defining a model. I have model which has some properties. One of those properties can be both null or another model.
import 'package:proef/models/worked_time.dart';
class Shift {
String uuid;
DateTime start_at;
DateTime end_at;
String title;
String comment;
WorkedTime worked_time;
Shift(
{this.uuid,
this.start_at,
this.end_at,
this.title,
this.comment,
this.worked_time});
factory Shift.fromData(Map<String, dynamic> parsedJson) {
print(parsedJson);
return Shift(
uuid: parsedJson['uuid'],
start_at: DateTime.parse(parsedJson['start_at']).toLocal(),
end_at: DateTime.parse(parsedJson['end_at']).toLocal(),
title: parsedJson['title'],
comment: parsedJson['comment'],
worked_time: parsedJson['worked_time'] == null
? null
: parsedJson['worked_time']);
}
}
This does not work. When I use this model it throws me the following error:
Unhandled Exception: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'WorkedTime'
I am not sure how to fix this, since I am quite new to Dart and Flutter.
The WorkedTime model:
class WorkedTime {
String uuid;
String comment;
int status;
int took_break;
DateTime start_at;
DateTime end_at;
WorkedTime({
this.uuid,
this.comment,
this.status,
this.took_break,
this.start_at,
this.end_at,
});
factory WorkedTime.fromData(Map<String, dynamic> parsedJson) {
print(parsedJson);
return WorkedTime(
uuid: parsedJson['uuid'],
comment: parsedJson['comment'],
status: parsedJson['status'],
took_break: parsedJson['took_break'],
start_at: DateTime.parse(parsedJson['start_at']),
end_at: DateTime.parse(parsedJson['end_at']));
}
}
The JSON with worked_time
[
{
"uuid": "706f40e7-d57c-470c-9023-b0c58e2c7c3a",
"start_at": "2020-09-01T08:00:00.000000Z",
"end_at": "2020-09-01T16:00:00.000000Z",
"title": "Test",
"comment": "Test",
"worked_time": {
"uuid": "6e73b4aa-d6e1-41f7-86cb-09745d2db033",
"comment": "Test",
"status": 0,
"break": 0,
"start_at": "2020-09-01T08:00:00.000000Z",
"end_at": "2020-09-01T16:00:00.000000Z",
"took_break": 0
}
}
]
The JSON without worked_time
[
{
"uuid": "706f40e7-d57c-470c-9023-b0c58e2c7c3a",
"start_at": "2020-09-01T08:00:00.000000Z",
"end_at": "2020-09-01T16:00:00.000000Z",
"title": "Test",
"comment": "Test",
"worked_time": null
}
]
Can you try this model
// To parse this JSON data, do
//
// final shift = shiftFromJson(jsonString);
import 'dart:convert';
List<Shift> shiftFromJson(String str) => List<Shift>.from(json.decode(str).map((x) => Shift.fromJson(x)));
String shiftToJson(List<Shift> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Shift {
Shift({
this.uuid,
this.startAt,
this.endAt,
this.title,
this.comment,
this.workedTime,
});
String uuid;
DateTime startAt;
DateTime endAt;
String title;
String comment;
WorkedTime workedTime;
factory Shift.fromJson(Map<String, dynamic> json) => Shift(
uuid: json["uuid"] == null ? null : json["uuid"],
startAt: json["start_at"] == null ? null : DateTime.parse(json["start_at"]),
endAt: json["end_at"] == null ? null : DateTime.parse(json["end_at"]),
title: json["title"] == null ? null : json["title"],
comment: json["comment"] == null ? null : json["comment"],
workedTime: json["worked_time"] == null ? null : WorkedTime.fromJson(json["worked_time"]),
);
Map<String, dynamic> toJson() => {
"uuid": uuid == null ? null : uuid,
"start_at": startAt == null ? null : startAt.toIso8601String(),
"end_at": endAt == null ? null : endAt.toIso8601String(),
"title": title == null ? null : title,
"comment": comment == null ? null : comment,
"worked_time": workedTime == null ? null : workedTime.toJson(),
};
}
class WorkedTime {
WorkedTime({
this.uuid,
this.comment,
this.status,
this.workedTimeBreak,
this.startAt,
this.endAt,
this.tookBreak,
});
String uuid;
String comment;
int status;
int workedTimeBreak;
DateTime startAt;
DateTime endAt;
int tookBreak;
factory WorkedTime.fromJson(Map<String, dynamic> json) => WorkedTime(
uuid: json["uuid"] == null ? null : json["uuid"],
comment: json["comment"] == null ? null : json["comment"],
status: json["status"] == null ? null : json["status"],
workedTimeBreak: json["break"] == null ? null : json["break"],
startAt: json["start_at"] == null ? null : DateTime.parse(json["start_at"]),
endAt: json["end_at"] == null ? null : DateTime.parse(json["end_at"]),
tookBreak: json["took_break"] == null ? null : json["took_break"],
);
Map<String, dynamic> toJson() => {
"uuid": uuid == null ? null : uuid,
"comment": comment == null ? null : comment,
"status": status == null ? null : status,
"break": workedTimeBreak == null ? null : workedTimeBreak,
"start_at": startAt == null ? null : startAt.toIso8601String(),
"end_at": endAt == null ? null : endAt.toIso8601String(),
"took_break": tookBreak == null ? null : tookBreak,
};
}
The compiler does not complain about assigning a dynamic variable to a typed variable because the check is done at runtime. Therefore, you can write:
void main() {
dynamic value = "something";
String string = value; // ok, value holds a String; runtime is fine
WorkedTime time = value; // evaluated at runtime; exception
}
This issue is present in Shift's factory constructor:
worked_time: parsedJson['worked_time'] == null
? null // true: can assign null to WorkedTime
: parsedJson['worked_time']); // false: assign dynamic to WorkedTime
You are attempting to assign a dynamic type with a value of parsedJson['worked_time'] to your WorkedTime type. These are incompatible types. Instead, you must use WorkedTime's constructor to construct the instance from the JSON map. Here is a minified example of your issue:
class WorkedTime {
String comment;
WorkedTime.fromData(Map<String, dynamic> json) : comment = json['comment'];
}
class Shift {
String uuid;
WorkedTime worked_time;
Shift.fromData(Map<String, dynamic> json)
: uuid = json['uuid'],
// next line causes the exception; cannot assign dynamic to WorkedTime
// fix: use WorkedTime.fromData(json['worked_time'])
worked_time = json['worked_time'];
}
In order to fix this, use WorkedTime.fromData(...)'s constructor.
class Shift {
String uuid;
WorkedTime worked_time;
Shift.fromData(Map<String, dynamic> json)
: uuid = json['uuid'],
worked_time = json['worked_time'] != null
? WorkedTime.fromData(json['worked_time']) // parse WorkedTime's json
: null;
}
void main() {
const json = <String, dynamic>{
'uuid': '706f40e7-d57c-470c-9023-b0c58e2c7c3a',
'worked_time': <String, dynamic>{'comment': 'on break'}
};
final shift = Shift.fromData(json);
// check that shift.worked_time is not null, etc.
print(shift.worked_time.comment);
}

How to create json encodable classes in dart

This question is related to this post.
I tried the following code:
import 'dart:convert';
/*server side Post class */
class Post {
int post_id;
String title;
String description;
DateTime posted_at;
DateTime last_edited;
String user;
String editor;
int up_votes;
int down_votes;
int total_votes;
String links_to;
List<String> tags = new List();
Post.fromSQL(List sql_post) {
//initialization code, unrelated.
}
Map toJson(){
Map fromObject = {
'post_id' : post_id,
'title' : title,
'description' : description,
'posted_at' : posted_at,
'last_edited' : last_edited,
'user' : user,
'editor' : editor,
'up_votes' : up_votes,
'dwon_votes' : down_votes,
'total_votes' : total_votes,
'links_to' : links_to,
'tags' : tags
};
return fromObject;
//I use the code below as a temporary solution
//JSON.encode(fromObject, toEncodable: (date)=>date.toString());
}
}
I have a temporary solution, but I would really like to be able to do the following.
JSON.encode(posts, toEncodable: (date)=>date.toString())
where posts is a list of Post objects. I would expect this to convert into a json list of json representations of the Post class. What I get is a list of "Instance of 'Post'" strings.
So the question is, is this syntax no longer supported, or should I do something differently?
It seems you can only use toEncodable: OR the toJson() fallback.
If you wrap your Date in a class which provides toJson() you don't need to use toEncodable::
class JsonDateTime {
final DateTime value;
JsonDateTime(this.value);
String toJson() => value != null ? value.toIso8601String() : null;
}
class Post {
...
Map toJson() => {
'post_id' : post_id,
'title' : title,
'description' : description,
'posted_at' : new JsonDateTime(posted_at),
'last_edited' : new JsonDateTime(last_edited),
'user' : user,
'editor' : editor,
'up_votes' : up_votes,
'dwon_votes' : down_votes,
'total_votes' : total_votes,
'links_to' : links_to,
'tags' : tags
};
}
or alternatively ensure that your toEncodeable: handles every not supported type:
print(JSON.encode(data, toEncodable: (value) {
if (value is DateTime) {
return value.toIso8601String();
} else {
return value.toJson();
}
}));