can't parse json to object in flutter - arrays

Seeking your help.
Actually, I've created an object model class. However, when I tried to parse the JSON response to the object model but error as below :
JSON Response
"value": [
{
"CardCode": "C20000",
"CardName": "Maxi Teq",
"DocCur": "AUD",
"DocEntry": 793,
"DocNum": 793,
"DocTotal": 99.0,
"DocType": "I",
"U_Driver": "addon",
"U_GLINK": "https://goo.gl/maps/tQJh7Zj9fpUzQqcv9"
},
{
"CardCode": "C20000",
"CardName": "Maxi Teq",
"DocCur": "AUD",
"DocEntry": 795,
"DocNum": 795,
"DocTotal": 99.0,
"DocType": "I",
"U_Driver": "addon",
"U_GLINK": "https://goo.gl/maps/tQJh7Zj9fpUzQqcv9"
}
]
Model
All the variables are string, but the JSON response includes int.
import 'package:json_annotation/json_annotation.dart';
part 'order.g.dart';
#JsonSerializable(explicitToJson: true)
class order {
String? cardCode;
String? cardName;
String? docCur;
String? docEntry;
String? docNum;
String? docTotal;
String? docType;
String? uDriver;
String? uGLINK;
order({this.cardCode, this.cardName, this.docCur, this.docEntry, this.docNum, this.docTotal, this.docType, this.uDriver, this.uGLINK});
factory order.fromJson(Map<String,dynamic> data) => _$orderFromJson(data);
Map<String,dynamic> toJson() => _$orderToJson(this);
}
Main Class
Map<String, dynamic> orderMap = json.decode(orderJson);
List<dynamic> orderList = orderMap["value"];
print("Method-------------$orderList");
List<order> list = orderList.map((val) => order.fromJson(val)).toList();
print(list.toString());
Error Response
I/flutter (26244): [Instance of 'order', Instance of 'order', Instance of 'order', Instance of 'order', Instance of 'order']
Thank you

That is not an error. That is the result of: print(list.toString());
What you are lacking is a toString() method on the class order, so it just prints that you have a list of instances of type order.
Add something like this to your order class:
#override
String toString() {
return 'order(cardCode: $cardCode, cardName: $cardName, docCur: $docCur, docEntry: $docEntry, docNum: $docNum, docTotal: $docTotal, docType: $docType, uDriver: $uDriver, uGLINK: $uGLINK)';
}

Use orderList.elementAt(0) to get a map of value.

Related

Kotlin Gson parsing Json Object and Array

I am pretty new to Kotlin and Json and on my work I use GSON to parse the Json.
I need to parse the following Json file into a Class by using GSON.
{
"apiKey": "blablabla",
"baseUrl": "blablabla",
"requestData": [
{
"lng": "6.971",
"lat": "50.942",
"rad": "1.5",
"type": [
"diesel",
"super"
]
},
{
"lng": "6.442",
"lat": "51.180",
"rad": "1.5",
"type": [
"diesel",
"super"
]
},{
"lng": "7.136",
"lat": "50.991",
"rad": "1.5",
"type": [
"diesel",
"super"
]
}
]
}
Now I tried to make a data class like this:
data class ApiParameterData(
var apiKey: String? = null,
var baseUrl: String? = null,
var requestData: String? = null) {
}
I also made another class to store the Json informations in it like this:
class Tankstelle: JsonDeserializer<ApiParameterData> {
override fun deserialize(json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext?
): ApiParameterData {
json as JsonObject
val apiKey = json.get("apiKey").asString
val baseUrl = json.get("baseUrl").asString
val requestDataJson = json.get("requestData")
val requestData = if (requestDataJson.isJsonObject) requestDataJson.asJsonObject.toString() else requestDataJson.toString()
return ApiParameterData(apiKey, baseUrl, requestData)
}
}
I tried to call it like that:
val gsonConfig = GsonBuilder().registerTypeAdapter(ApiParameterData::class.java, Tankstelle()).create()
val tanke = gsonConfig.fromJson(readJson, ApiParameterData::class.java)
println(tanke.requestData?.get(0))
But of course the output I get is "[" . I think because I get back a String or something and this is the first symbol of it?
I need to loop trough the requestData list and store it as a instance of a class and need to access each different value.
The thing is that I want to give the Json file different places and ranges it should look for gasstations. By reading the Json it should take all the pieces and create a link for each place I write in the requestData list. So in this case I would need 3 different links at the end. But this is another part I can do myself. I just don't know how to parse it so I can access and store every value in this Json.
Thank you already and have a great weekend!
If you need more informations just let me know
First you need to define two types that map to your JSON structure
class ApiParameterData(
val apiKey: String,
val baseUrl: String,
val requestData: List<RequestObject>
)
class RequestObject(
val lng: String,
val lat: String,
val rad: String,
val type: List<String>
)
Now simply parse it as
val apiData = Gson().fromJson(readJson, ApiParameterData::class.java) // No need to add TypeAdapter
// To get requestData
val requestData = apiData.requestData
requestData.forEach {
print("${it.lng}, ${it.lat}, ${it.rad}, ${it.type})
}

Flutter - Sembast Database insert List of Objects

I'm about to use the database "Sembast" in Flutter.
Simple objects with data types like string and int are working properly. However, it becomes problematic when using Lists.
I have created an example and oriented myself on the following tutorial: https://resocoder.com/2019/04/06/flutter-nosql-database-sembast-tutorial-w-bloc/
In my example, there are fruits and leaves as objects. A fruit contains a list of leaves.
class Fruit {
final String id;
final String name;
final bool isSweet;
final List<Leaves> leaves;
...
}
class Leaves {
final String id;
final String name;
...
}
//Create a sample object
var leaveOne = Leaves(id: "1", name: "leaveOne");
var leaveTwo = Leaves(id: "2", name: "leaveTwo");
var leaveThree = Leaves(id: "3", name: "leaveThree");
var leavesList = List<Leaves>();
leavesList.add(leaveOne);
leavesList.add(leaveTwo);
leavesList.add(leaveThree);
var fruit = Fruit(id: "1", name: "Apple", isSweet: true, leaves: leavesList);
_fruitDao.insert(fruit);
// The fruitDao.insert makes following
Future insert(Fruit fruit) async {
await _fruitStore.add(await _db, fruit.toJson());
}
The JSON looks like that: {id: 1, name: Apple, isSweet: true, leaves: [Instance of 'Leaves', Instance of 'Leaves', Instance of 'Leaves']}
The ERROR is following:
[ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: Invalid argument(s): value Instance of 'Leaves' unsupported type Leaves
As pointed at, Instance of 'Leaves' is not a valid type so each Leave must be converted as well. Hard to guess what you are doing without seeing your toJson() but something like this should work (could be largely optimized):
class Fruit {
final String id;
final String name;
final bool isSweet;
final List<Leaves> leaves;
Fruit({this.id, this.name, this.isSweet, this.leaves});
Map<String, dynamic> toJson() => <String, dynamic>{
'id': id,
'name': name,
'isSweet': isSweet,
'leaves': leaves?.map((leave) => leave.toJson())?.toList(growable: false)
};
}
class Leaves {
final String id;
final String name;
Leaves({this.id, this.name});
Map<String, dynamic> toJson() => <String, dynamic>{'id': id, 'name': name};
}
and your json should look like something this this:
{
"id": "1",
"name": "Apple",
"isSweet": true,
"leaves": [
{
"id": "1",
"name": "leaveOne"
},
{
"id": "2",
"name": "leaveTwo"
},
{
"id": "3",
"name": "leaveThree"
}
]
}
Here is an example in addition to #alextk answer with converting to and from without any code generation or library's.
class Fruit {
final String id;
final String name;
final bool isSweet;
final List<Leaves> leaves;
Fruit({this.id, this.name, this.isSweet, this.leaves});
Map<String, dynamic> toMap() {
return {
'id': id,
'name': name,
'isSweet': isSweet,
'leaves': leaves.map((leave) => leave.toMap()).toList(growable: false)
};
}
static Fruit fromMap(Map<String, dynamic> map) {
return Fruit(
id: map['id'],
name: map['name'],
isSweet: map['isSweet'],
leaves: map['leaves'].map((mapping) => Leaves.fromMap(mapping)).toList().cast<Leaves>(),
);
}
}
class Leaves {
final String id;
final String name;
Leaves({this.id, this.name});
Map<String, dynamic> toMap() {
return {
'id': id,
'name': name,
};
}
static Leaves fromMap(Map<String, dynamic> map) {
return Leaves(
id: map['id'],
name: map['name'],
);
}
}
For cases when you use freezed, I found this solution:
...
...
#freezed
class Fruit with _$Fruit {
//add this line
#JsonSerializable(explicitToJson: true)
const factory Fruit({...}) = _Fruit;
factory Fruit.fromJson(Map<String, dynamic> json) => _$FruitFromJson(json);
}

How to convert a List<Map<String, dynamic>> inside a Map<String, dynamic> to JSON in Dart?

I'm trying to send a Map<String, dynamic>, and one of the dynamic is actually a List<Map<String, dynamic>>.
I assemble it like that :
Packet packet = Packet(
datas: stocks.map((stock) => stock.toJson()).toList(),
);
String json = jsonEncode(packet);
The problem is what's being sent is actually this :
{
"datas": {
"rows": "[{NoArticle: 051131626638, Description: Ruban pour tapis, qty: 5}]"
}
}
The expected output is this :
{
"datas": {
"rows": [{
"NoArticle": "051131626638",
"Description": "Ruban pour tapis",
"qty": 5,
}]
}
}
I want to send a List<Map<String, dynamic>>, not a String. How do I do that?
Answer : I am a dumbass.
I passed the parameter trough a function, like this :
Server.send("sendInventoryBatch", {
"rows": "${stocks.map((stock) => stock.toJson()).toList()}",
});
Of course it would return a String.
Question is invalid. If you have a similar problem, please open a different question. Sorry for the inconvenience.
Now if anyone actually has this question and stumbles upon this thread, here's how to do it :
Assemble your object, and make sure you didn't stringify it along the way
Use jsonEncode
In case of doubt, make everything a Map<String, dynamic>, a List<dynamic>, or a sub-class of those two first.
Packet packet = Packet(
appType: "inventoryManager",
module: "",
action: action,
datas: data,
deviceID: Globals.map["UUID"],
cbackid: cback,
);
You can generate classes like my custom Packet from JSON using multiple online resources because jsonEncode will use the auto-generated Map<String, dynamic> toJson().
https://app.quicktype.io/ - Was recommended to me on Discord by Miyoyo#5957
https://javiercbk.github.io/json_to_dart/ - I used this one before
http://json2dart.com/
String json = jsonEncode(packet);
And voilĂ , you're done.
Did you look at packages json_serializable?
Here's an example of a Person that has many Orders : example
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:json_annotation/json_annotation.dart';
part 'example.g.dart';
#JsonSerializable()
class Person {
final String firstName;
#JsonKey(includeIfNull: false)
final String middleName;
final String lastName;
#JsonKey(name: 'date-of-birth', nullable: false)
final DateTime dateOfBirth;
#JsonKey(name: 'last-order')
final DateTime lastOrder;
#JsonKey(nullable: false)
List<Order> orders;
Person(this.firstName, this.lastName, this.dateOfBirth,
{this.middleName, this.lastOrder, List<Order> orders})
: orders = orders ?? <Order>[];
factory Person.fromJson(Map<String, dynamic> json) => _$PersonFromJson(json);
Map<String, dynamic> toJson() => _$PersonToJson(this);
}
#JsonSerializable(includeIfNull: false)
class Order {
int count;
int itemNumber;
bool isRushed;
Item item;
#JsonKey(
name: 'prep-time',
fromJson: _durationFromMilliseconds,
toJson: _durationToMilliseconds)
Duration prepTime;
#JsonKey(fromJson: _dateTimeFromEpochUs, toJson: _dateTimeToEpochUs)
final DateTime date;
Order(this.date);
factory Order.fromJson(Map<String, dynamic> json) => _$OrderFromJson(json);
Map<String, dynamic> toJson() => _$OrderToJson(this);
static Duration _durationFromMilliseconds(int milliseconds) =>
Duration(milliseconds: milliseconds);
static int _durationToMilliseconds(Duration duration) =>
duration.inMilliseconds;
static DateTime _dateTimeFromEpochUs(int us) =>
DateTime.fromMicrosecondsSinceEpoch(us);
static int _dateTimeToEpochUs(DateTime dateTime) =>
dateTime.microsecondsSinceEpoch;
}
#JsonSerializable()
class Item {
int count;
int itemNumber;
bool isRushed;
Item();
factory Item.fromJson(Map<String, dynamic> json) => _$ItemFromJson(json);
Map<String, dynamic> toJson() => _$ItemToJson(this);
}
#JsonLiteral('data.json')
Map get glossaryData => _$glossaryDataJsonLiteral;

Convert array of custom object to String in swift4

I am new to Swift and have an issue converting an array of custom object, to String.
This is my response class Tickets
public struct Tickets: Codable {
public let name: String!
public let status: String!
public let department: String!
}
After the webservice call i get following response and it would be mapped to Tickets class. Now, I have an array of "Tickets" as [Tickets] described below.
"tickets": [
{
"name": "d5b5d618-8a74-4e5f",
"status": "VALID",
"department": "IT"
},
{
"name": "a58f54b5-9420-49b6",
"status": "INVALID",
"department": "Travel"
}
]
Now, can I convert an array of [Tickets] to String? If so, how? Also, how to get it back as [Tickets] from a class of String.
I want to store it into UserDefaults after converting it to String, and retrieve it later
First of all:
Never declare properties or members in a struct or class as implicit unwrapped optional if they are supposed to be initialized in an init method. If they could be nil declare them as regular optional (?) otherwise as non-optional (Yes, the compiler won't complain if there is no question or exclamation mark).
Just decode and encode the JSON with JSONDecoder() and JSONEncoder()
let jsonTickets = """
{"tickets":[{"name":"d5b5d618-8a74-4e5f","status":"VALID","department":"IT"},{"name":"a58f54b5-9420-49b6","status":"INVALID","department":"Travel"}]}
"""
public struct Ticket: Codable {
public let name: String
public let status: String
public let department: String
}
do {
let data = Data(jsonTickets.utf8)
let tickets = try JSONDecoder().decode([String:[Ticket]].self, from: data)
print(tickets)
let jsonTicketsEncodeBack = try JSONEncoder().encode(tickets)
jsonTickets == String(data: jsonTicketsEncodeBack, encoding: .utf8) // true
} catch {
print(error)
}

Json Parsing in Angular2

I have a array of jsons that I want to parse to my class Tournament.
The class Tournament looks like this:
export class Tournament { constructor (public id: number,
public name: string,
public date: string,
public pointsWin: string,
public pointsDraw: string,
public groupSize: string,
public groupPhase: string,
public system: string,
public teams: Team[]
){ }
}
The class Team looks like this:
export class Team { constructor (public id: number,
public name: string,
public rank: number,
public occupied: boolean,
public group: string
){ }
}
And the JSON that i receive looks like this:
[{"id":1,
"name":"Schulcup1",
"date":
{"year":2017,"month":"MARCH","era":"CE","dayOfYear":83,"dayOfWeek":"FRIDAY","leapYear":false,"dayOfMonth":24,"monthValue":3,"chronology":{"calendarType":"iso8601","id":"ISO"}},
"pointsWin":0,
"pointsDraw":0,
"groupSize":0,
"groupPhase":null,
"system":null,
"teams":[
{"id":1,"name":"Team1","rank":8,"occupied":false,"group":"A"},
{"id":2,"name":"Team2","rank":1,"occupied":false,"group":"A"},
{"id":3,"name":"Team3","rank":4,"occupied":false,"group":"A"},
{"id":4,"name":"Team4","rank":16,"occupied":false,"group":"A"},
{"id":5,"name":"Team5","rank":2,"occupied":false,"group":"B"},
{"id":6,"name":"Team6","rank":16,"occupied":false,"group":"B"},
{"id":7,"name":"Team7","rank":8,"occupied":false,"group":"B"},
{"id":8,"name":"Team8","rank":4,"occupied":false,"group":"B"}],
"active":true},
{"id":2,
"name":"Schulcup2",
"date":
{"year":2017,"month":"MARCH","era":"CE","dayOfYear":82,"dayOfWeek":"THURSDAY","leapYear":false,"dayOfMonth":23,"monthValue":3,"chronology":{"calendarType":"iso8601","id":"ISO"}},
"pointsWin":0,
"pointsDraw":0,
"groupSize":0,
"groupPhase":null,
"system":null,
"teams":[
{"id":48,"name":"Team1","rank":16,"occupied":false,"group":"A"},
{"id":49,"name":"Team2","rank":2,"occupied":false,"group":"A"},
{"id":50,"name":"Team3","rank":4,"occupied":false,"group":"A"},
{"id":51,"name":"Team4","rank":1,"occupied":false,"group":"A"},
{"id":52,"name":"Team5","rank":16,"occupied":false,"group":"B"},
{"id":53,"name":"Team6","rank":8,"occupied":false,"group":"B"},
{"id":54,"name":"Team7","rank":16,"occupied":false,"group":"B"},
{"id":55,"name":"Team8","rank":16,"occupied":false,"group":"B"}],
"active":true}]
If I try to parse the JSON with JSON.parse() I get an error that there is an unexpected token in JSON at position 0 most likely because of the [ since it is an array of JSON but how can I iterate through it?
And also how can I iterate through the teams in the JSON to create an array of teams?
It is already parsed. Just use it as an object!
No need to use classes here, simply cast your JSON to interfaces, if you really do not need classes. Casting to interfaces is easy and painless ;) And no need of using JSON.parse here.
So use interfaces if you can, here is Tournament:
export interface Tournament {
public id: number,
public name: string,
public date: string,
public pointsWin: string,
public pointsDraw: string,
public groupSize: string,
public groupPhase: string,
public system: string,
public teams: Team[]
}
Service:
getTournaments(): Observable<Tournament[]> {
return this.http.get('src/data.json')
.map(res => res.json() as Tournament[])
}
TS:
tournaments: Tournament[] = [];
getTournaments() {
this.service.getTournaments()
.subscribe(data => {
this.tournaments = data;
})
}
DEMO

Resources