I am trying to parse this complex JSON data into a Flutter application. I am able to get the JSON data successfully, but not able to display the data in the application. See the code and JSON data below.
What I am doing wrong?
JSON Data
{
"response": {
"cars": [
[
{
"id": 1,
"name": "Ford Mustang GT",
"class": "Muscle Car"
},
{
"id": 2,
"name": "Dodge Challenger",
"class": "Muscle Car"
},
{
"id": 3,
"name": "Chevrolet Camaro",
"class": "Muscle Car"
},
{
"id": 4,
"name": "Pontiac Firebird",
"class": "Muscle Car"
}
]
]
}
}
Data Model
class Cars {
Cars({
this.id,
this.name,
this.carClass,
});
int id;
String name;
String carClass;
factory Cars.fromJson(Map<String, dynamic> json) => Cars(
id: json["id"],
name: json["name"],
carClass: json["class"],
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"class": carClass,
};
}
API Service getting the JSON Data
class ApiService {
Future<List<Cars>> getCars() async {
http.Response response = await http.get('http://localhost:3000/response');
var body;
if (response.statusCode == 200) {
body = jsonDecode(response.body);
List<dynamic> carList = body['response'];
print(body);
List<Cars> res =
carList.map((dynamic item) => Cars.fromJson(item)).toList();
return res;
}
}
}
Display Data
You can help in the construction of the classes with this application. (https://app.quicktype.io/)
These are the classes that you must use for the obtained object. Be sure to change the name of the classes that you think are relevant.
class Response {
Response({
this.response,
});
final ResponseClass response;
factory Response.fromJson(Map<String, dynamic> json) => Response(
response: ResponseClass.fromJson(json["response"]),
);
Map<String, dynamic> toJson() => {
"response": response.toJson(),
};
}
class ResponseClass {
ResponseClass({
this.cars,
});
final List<List<Car>> cars;
factory ResponseClass.fromJson(Map<String, dynamic> json) => ResponseClass(
cars: List<List<Car>>.from(json["cars"].map((x) => List<Car>.from(x.map((x) => Car.fromJson(x))))),
);
Map<String, dynamic> toJson() => {
"cars": List<dynamic>.from(cars.map((x) => List<dynamic>.from(x.map((x) => x.toJson())))),
};
}
class Car {
Car({
this.id,
this.name,
this.carClass,
});
final int id;
final String name;
final String carClass;
factory Car.fromJson(Map<String, dynamic> json) => Car(
id: json["id"],
name: json["name"],
carClass: json["class"],
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"class": carClass,
};
}
Finally, replace this line:
body = jsonDecode(response.body);
List<dynamic> carList = body['response'];
print(body);
List<Cars> res =
carList.map((dynamic item) => Cars.fromJson(item)).toList();
with this:
return Response.fromJson(response.body);
and replace the data type that the function returns to Response.
You can also follow the official documentation for flutter Serializtion. It's good and also saves us from the hassle of creating the conversion HashMaps.
Related
Im new on dart/flutter.
how can i use objects in lists ?
i have objects like:
{
"channelName": "sydneyfunnelaio",
"type": "",
"ChannelPic": "https://static-cdn.jtvnw.net/jtv_user_pictures/8ead1810-f82a-4dc0-a3a6-583171baff60-profile_image-300x300.jpeg",
"success": true
}
how can i create list/array with that ;
I want like:
[{
"channelName": "sydneyfunnelaio",
"type": "",
"ChannelPic": "https://static-cdn.jtvnw.net/jtv_user_pictures/8ead1810-f82a-4dc0-a3a6-583171baff60-profile_image-300x300.jpeg",
"success": true
},{
"channelName": "qweqdqaw",
"type": "",
"ChannelPic": "https://static-cdn.jtvnw.net/jtv_user_pictures/8ead1810-f82a-4dc0-a3a6-583171baff60-profile_image-300x300.jpeg",
"success": true
}]
You can try something like this :
void main() {
List<MyObject> myObjects = [];
myObjects.add(MyObject.fromJson({
"channelName": "sydneyfunnelaio",
"type": "",
"ChannelPic":
"https://static-cdn.jtvnw.net/jtv_user_pictures/8ead1810-f82a-4dc0-a3a6-583171baff60-profile_image-300x300.jpeg",
"success": true
}));
myObjects.add(MyObject.fromJson({
"channelName": "qweqdqaw",
"type": "",
"ChannelPic":
"https://static-cdn.jtvnw.net/jtv_user_pictures/8ead1810-f82a-4dc0-a3a6-583171baff60-profile_image-300x300.jpeg",
"success": true
}));
print(myObjects);
print(myObjects[0].channelName);
print(myObjects[1].channelName);
myObjects.forEach((obj)=>print(obj.toJson()));
}
class MyObject {
String channelName;
String type;
String channelPic;
bool success;
MyObject({this.channelName, this.type, this.channelPic, this.success});
MyObject.fromJson(Map<String, dynamic> json) {
channelName = json['channelName'];
type = json['type'];
channelPic = json['ChannelPic'];
success = json['success'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['channelName'] = this.channelName;
data['type'] = this.type;
data['ChannelPic'] = this.channelPic;
data['success'] = this.success;
return data;
}
}
This is the problem that I'm trying to resolve. I have a list of map that I want to convert into JSON array in Groovy.
The list is:
List<Map<String, String>> studentList = [{id=1,name=John,email=john#google.com},{id=2,name=Peter,email=peter#google.com},{id=3,name=James,email=james#google.com}]
Desired JSON output is:
{
students: [{
"id" = "1",
"name" = "John",
"contact": {
"email": "john#google.com"
}
}, {
"id" = "2",
"name" = "Peter",
"contact": {
"email": "peter#google.com"
}
}, {
"id" = "3",
"name" = "James",
"contact": {
"email": "james#google.com"
}
}
]
}
My code only generates 1 student. Can anyone help me please?
def builder = new JsonBuilder()
for (Map student: studentList) {
builder.students {
id student.id
name student.name
contact {
email student.email
}
}
}
println builder.toPrettyString()
Appreciate your time and advice. Thank you.
Pass a list to the builder
You don't need to iterate through the list, you can pass a list to the builder,
using JsonBuilder's implicit call() method.
def builder = new JsonBuilder()
builder {
students builder( studentList )
}
public Object call( List list )
A list of elements as arguments to the JSON builder creates a root JSON array
See the JsonBuilder Groovydoc page for details of the various call()
methods.
Example code
In this example I've fixed up your map, and introduced a small Student class, to
simplify the code.
import groovy.json.JsonBuilder
class Student { int id; String name; String email }
studentList = [
new Student( id:1, name:'John', email:'john#google.com' ),
new Student( id:2, name:'Peter', email:'peter#google.com' ),
new Student( id:3, name:'James', email:'james#google.com' )
]
def builder = new JsonBuilder()
builder {
students builder( studentList )
}
println builder.toPrettyString()
Resulting JSON
{
"students": [
{
"id": 1,
"email": "john#google.com",
"name": "John"
},
{
"id": 2,
"email": "peter#google.com",
"name": "Peter"
},
{
"id": 3,
"email": "james#google.com",
"name": "James"
}
]
}
I have solved it with ff code.
def students = []
def builder = new JsonBuilder()
for (Map student: studentList) {
builder {
id student.id
name student.name
contact {
email student.email
}
}
students.add(builder.toString())
}
def jsonSlurper = new JsonSlurper()
def items = jsonSlurper.parseText(students.toString())
def json = new JsonBuilder()
json "students": items
println json.toPrettyString()
This is the response I am getting from server. All the properties are String and int expect data. It is a list of objects. When serializing the response it shows error. Please explain what is wrong with my code. I am from javascript background. Serialization in flutter is different from javascript.
class ResponseModel {
String image;
int row;
int column;
int position;
List<Data> data;
ResponseModel({this.image, this.row, this.column, this.position});
factory ResponseModel.fromJson(Map<String, dynamic> parsedJson) {
return ResponseModel(
image: parsedJson['image'],
row: parsedJson['row'],
column: parsedJson['column'],
position: parsedJson['position'],
);
}
}
class Data {
String imageUrl;
Data({this.imageUrl});
factory Data.fromJson(Map<String, dynamic> parsedJson) {
return Data(imageUrl: parsedJson["imageUrl"]);
}
}
[
{
"type": "image",
"row": 1,
"column": 3,
"position":"1",
"data": [
{
"imageUrl": "https://rukminim1.flixcart.com/flap/276/294/image/6dad06016c6ab319.jpg?q=90"
},
{
"imageUrl": "https://rukminim1.flixcart.com/flap/276/294/image/9ad209b0fc3d03e4.jpg?q=90"
},
{
"imageUrl": "https://rukminim1.flixcart.com/flap/276/294/image/405e10d01fae5aa5.jpg?q=90"
}
]
},
{
"type": "image",
"row": 1,
"column": 2,
"position":"3",
"data": [
{
"imageUrl": "https://rukminim1.flixcart.com/flap/414/630/image/f186565389063212.jpg?q=90"
},
{
"imageUrl": "https://rukminim1.flixcart.com/flap/414/630/image/3eda035d946b0ebf.jpg?q=90"
}
]
},
{
"type": "image",
"row": 1,
"column": 1,
"position":"2",
"data": [
{
"imageUrl": "https://rukminim1.flixcart.com/flap/1187/636/image/4436d492e2563998.jpg?q=90"
}
]
}
]
Future<dynamic> getData() async {
final response = await http.get("https://api.myjson.com/bins/1g4o04");
final parsedJson = json.decode(response.body);
final finalResponse = ResponseModel.fromJson(parsedJson);
print(finalResponse);
setState(() {
data = parsedJson;
});
}
Error image
You can use this tool and select dart Language
Its because the response is a JSON array. Which means json.decode(response.body) returns a List<dynamic> and hence the variable parsedJson is List.
You're trying to pass this List as a parameter to the ResponseModel.fromJson(Map<String, dynamic>) method which accepts a Map as the parameter.
In simple words, you're trying to pass a List where a Map is expected.
Future<dynamic> getData() async {
final response = await http.get("https://api.myjson.com/bins/1g4o04");
final parsedJson = json.decode(response.body);
List<ResponseModel> responseList = <ResponseModel>[];
parsedJson.foreach((element) {
responseList.add(ResponseModel.fromJson(element));
})
///Response list will have your data
print(responseList);
}
Your code should be something like this
I have JSON like this
{
"status": "true",
"data": [
{
"idpekerjaan": "1",
"namapekerjaan": "Apel Pagi / Sore",
"subpekerjaan": [
{
"idsubpekerjaan": "2",
"namasubpekerjaan": "Apel Pagi/Sore",
"standarwaktu": "15"
},
{
"idsubpekerjaan": "3",
"namasubpekerjaan": "Apel Pagi/Sore",
"standarwaktu": "20"
}
]
},
{
"idpekerjaan": "2",
"namapekerjaan": "Upacara",
"subpekerjaan": [
{
"idsubpekerjaan": "10",
"namasubpekerjaan": "Upacara",
"standarwaktu": "60"
},
{
"idsubpekerjaan": "11",
"namasubpekerjaan": "Upacara",
"standarwaktu": "90"
}
]
},
}
Saya mempunyai fungsi-fungsi:
class Localization {
final List <DataPekerjaan> pekerjaan;
final List <SubPekerjaan> subpekerjaan;
Localization({this.pekerjaan, this.subpekerjaan});
factory Localization.fromJson(Map<String, dynamic> json) {
return Localization(
subpekerjaan: parseStates(json),
pekerjaan: parseProvinces(json),
);
}
static List<SubPekerjaan> parseStates(statesJson) {
List<DataPekerjaan> cari = parseProvinces(statesJson);
var slist = ???????????????????? as List;
List<SubPekerjaan> statesList =
slist.map((data) => SubPekerjaan.fromJson(data)).toList();
return statesList;
}
static List<DataPekerjaan> parseProvinces(provincesJson) {
var plist = provincesJson['data'] as List;
List<DataPekerjaan> provincesList =
plist.map((data) => DataPekerjaan.fromJson(data)).toList();
return provincesList;
}
}
class SubPekerjaan {
final String idSubPekerjaan;
final String namaSubPekerjaan;
final String standarWaktu;
SubPekerjaan({this.idSubPekerjaan, this.namaSubPekerjaan, this.standarWaktu});
factory SubPekerjaan.fromJson(Map<String, dynamic> parsedJson){
return SubPekerjaan(idSubPekerjaan: parsedJson['idsubpekerjaan'], namaSubPekerjaan: parsedJson['namasubpekerjaan'], standarWaktu: parsedJson['standarwaktu']);
}
}
class DataPekerjaan {
final String idPekerjaan;
final String namaPekerjaan;
final List<String> subPekerjaan;
DataPekerjaan({this.idPekerjaan, this.namaPekerjaan, this.subPekerjaan});
factory DataPekerjaan.fromJson(Map<String, dynamic> parsedJson) {
return DataPekerjaan(idPekerjaan: parsedJson['idpekerjaan'], namaPekerjaan: parsedJson['namapekerjaan'], subPekerjaan: parsedJson["subpekerjaan"]);
}
}
I want to retrieve the contents of an array of data and then I create a List and then I also want to take the contents of an array of subpekerjaan so that it becomes a separate data. How can I insert each of those arrays into a function that I already have, especially in the ListparseStates (statesJson). What should I fill in the question mark?
Then is it true how I declare the data type List subPekerjaan on the DataPekerjaan class?
First your json is invalid (VAlidate at https://jsonlint.com/) it should be
{
"status": "true",
"data": [
{
"idpekerjaan": "1",
"namapekerjaan": "Apel Pagi / Sore",
"subpekerjaan": [
{
"idsubpekerjaan": "2",
"namasubpekerjaan": "Apel Pagi/Sore",
"standarwaktu": "15"
},
{
"idsubpekerjaan": "3",
"namasubpekerjaan": "Apel Pagi/Sore",
"standarwaktu": "20"
}
]
},
{
"idpekerjaan": "2",
"namapekerjaan": "Upacara",
"subpekerjaan": [
{
"idsubpekerjaan": "10",
"namasubpekerjaan": "Upacara",
"standarwaktu": "60"
},
{
"idsubpekerjaan": "11",
"namasubpekerjaan": "Upacara",
"standarwaktu": "90"
}
]
}
]
}
Now try with class
// To parse this JSON data, do
//
// final myModel = myModelFromJson(jsonString);
import 'dart:convert';
MyModel myModelFromJson(String str) => MyModel.fromJson(json.decode(str));
String myModelToJson(MyModel data) => json.encode(data.toJson());
class MyModel {
String status;
List<Datum> data;
MyModel({
this.status,
this.data,
});
factory MyModel.fromJson(Map<String, dynamic> json) => MyModel(
status: json["status"],
data: List<Datum>.from(json["data"].map((x) => Datum.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"status": status,
"data": List<dynamic>.from(data.map((x) => x.toJson())),
};
}
class Datum {
String idpekerjaan;
String namapekerjaan;
List<Subpekerjaan> subpekerjaan;
Datum({
this.idpekerjaan,
this.namapekerjaan,
this.subpekerjaan,
});
factory Datum.fromJson(Map<String, dynamic> json) => Datum(
idpekerjaan: json["idpekerjaan"],
namapekerjaan: json["namapekerjaan"],
subpekerjaan: List<Subpekerjaan>.from(json["subpekerjaan"].map((x) => Subpekerjaan.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"idpekerjaan": idpekerjaan,
"namapekerjaan": namapekerjaan,
"subpekerjaan": List<dynamic>.from(subpekerjaan.map((x) => x.toJson())),
};
}
class Subpekerjaan {
String idsubpekerjaan;
String namasubpekerjaan;
String standarwaktu;
Subpekerjaan({
this.idsubpekerjaan,
this.namasubpekerjaan,
this.standarwaktu,
});
factory Subpekerjaan.fromJson(Map<String, dynamic> json) => Subpekerjaan(
idsubpekerjaan: json["idsubpekerjaan"],
namasubpekerjaan: json["namasubpekerjaan"],
standarwaktu: json["standarwaktu"],
);
Map<String, dynamic> toJson() => {
"idsubpekerjaan": idsubpekerjaan,
"namasubpekerjaan": namasubpekerjaan,
"standarwaktu": standarwaktu,
};
}
My document looks like this:
{
"data": {
"eventId": "20161029125458-df-d",
"name": "first",
"purpose": "test",
"location": "yokohama",
"dateArray": [],
"attendees": [
{
"attendeeId": "2016102973634-df",
"attendeeName": "lakshman",
"personalizedDateSelection": {}
},
{
"attendeeId": "2016102973634-tyyu",
"attendeeName": "diwaakar",
"personalizedDateSelection": {}
}
]
}
}
Say, I need to update the attendee JSON array with attendeeId: 2016102973634-df. I tried many ways ways using update and condition expression, but no success.
Here is my try:
const params = {
TableName: "event",
Key: {
"eventId": eventId
},
UpdateExpression: "SET attendees[???] = ",
ConditionExpression: attendees.attendeeId = "2016102973634-df",
ExpressionAttributeValues: {
":attendee" : attendeeList
},
ReturnValues: "ALL_NEW"
};
dynamo.update(params, (err, data) => {
if (err) {
return reject(err);
}
console.log(data.Attributes);
});
Could not find any resources for updating an Json in a array.
After #notionquest's comment:
- Have not used any JsonMarshaller. Initially I added the empty array to attendees field like this:
{
"eventId": "20161029125458-df-d",
"name": "first",
"purpose": "test",
"location": "yokohama",
"dateArray": [],
"attendees": []
}
and then When a new attendee comes I add it to the attendees property like this:
const attendee = {
"attendeeName": "user1",
"personalizedDateSelection": {"today": "free"}
}
const attendeeList = [attendee];
const eventId = "20161029125458-df-d";
const params = {
TableName: "event",
Key: {
"eventId": eventId
},
UpdateExpression: "SET attendees = list_append(attendees, :attendee)",
ExpressionAttributeValues: {
":attendee" : attendeeList
},
ReturnValues: "ALL_NEW"
};
dynamo.update(params, (err, data) => {
if (err) {
return reject(err);
}
console.log("in update dynamo");
console.log(data.Attributes);
});
As you have seen in the above snippets, initially I add empty [] array and add a new attendee using the above code. Now, How do I update a specific JSON in an array. If you say that is not possible, what else can I try?
Should I try this :
Get the Full JSON.
Manipulate the JSOn and change the things I want in my nodeJS.
And then update the new JSON to dynamoDB.
But this consumes two calls to dynamoDB which seems to be inefficient.
Would like to know If there is any round way ?
you can store the index of list. while updating the list we can use them. For example ,
{
"data": {
"eventId": "20161029125458-df-d",
"name": "first",
"purpose": "test",
"location": "yokohama",
"dateArray": [],
"attendees": [
{
"index":0,
"attendeeId": "2016102973634-df",
"attendeeName": "lakshman",
"personalizedDateSelection": {}
},
{
"index":1,
"attendeeId": "2016102973634-tyyu",
"attendeeName": "diwaakar",
"personalizedDateSelection": {}
}
]
}
}
const params = {
TableName: "event",
Key: {
"eventId": eventId
},
UpdateExpression: "SET attendees[attendee.index].attendeeName = :value",
ExpressionAttributeValues: {
":value" : {"S":"karthik"}
},
ReturnValues: "ALL_NEW"
};
dynamo.update(params, (err, data) => {
if (err) {
return reject(err);
}
console.log(data.Attributes);
});
An example of an update query:
Data structure (saved in DynamoDB)
{
tenant_id: 'tenant_1',
users: {
user1: {
_id: 'user1',
email_address: 'test_email_1#gmail.com'
},
user2: {
_id: 'user2',
email_address: 'test_email_2#gmail.com'
}
}
}
Data for update (used in the params)
var user = {
email_address: 'updated#gmail.com'
}
Params
var params = {
TableName: 'tenant-Master',
Key: {
"tenant_id": 'tenant_1'
},
UpdateExpression: "set #users.user1 = :value",
ExpressionAttributeNames: {
"#users": "users"
},
ExpressionAttributeValues: {
":value": user,
},
};
Explanation
By switching to a map of maps from an array of maps we can now use UpdateExpression: "set #users.user1 = :value" to update our nested object at the map of users with the id of user1.
NOTE: This method as is will REPLACE the entire map object at users.user1. Some changes will need to be made if you want to keep pre-existing data.
I could not find any answer to query and update the JSON-array. I think this may be AWS profitable motive to not allow those features. If you need to query on a particular ID other than primary key, you need to make a secondary index which is cost effective. This secondary index cost is additional to the dyn
amoDB table cost.
Since, I did not want to pay extra bucks on secondary index, I changed my dynamoDB schema to the following:
{
"data": {
"eventId": "20161029125458-df-d",
"name": "first",
"purpose": "test",
"location": "yokohama",
"dateArray": [],
"attendees": {
"2016102973634-df": {
"attendeeId": "2016102973634-df",
"attendeeName": "lakshman",
"personalizedDateSelection": {}
},
"2016102973777-df": {
"attendeeId": "2016102973777-df",
"attendeeName": "ffff",
"personalizedDateSelection": {}
}
}
}
}
Changing attendees from [] to {}. This allows me the flexibility to query particular attendeeId and change the entire JSON associated with that. Even though, this is a redundant step, I do not want to spend extra bucks on my hobby project.