I'm having trouble converting HTTP response body to a Flutter list. In a debugger, the output of jsonDecode(response.body)['data']['logsread'] looks exactly like
[
{
"id": "9fd66092-1f7c-4e60-ab8f-5cf7e7a2dd3b",
"email": "email#gmail.com"
}
]
Yet, this returns false.
print((jsonDecode(response.body)['data']['logsread']) ==
[{
"id": "9fd66092-1f7c-4e60-ab8f-5cf7e7a2dd3b",
"email": "email#gmail.com"
}]); // This returns false.
FYI. response.body =>
"{"data":{"logsread":[{"id":"9fd66092-1f7c-4e60-ab8f-5cf7e7a2dd3b","email":"email#gmail.com"}]}}"
JsonDecode returns List<dynamic> but your another list is of type List<Map<String,String>>. So convert it to same type of list by creating to any Model and overriding == and hashcode.
and to compare two list you need ListEquality function.
example :
Function eq = const ListEquality().equals;
print(eq(list1,list2));
I tried your code and done my way, check if this okay.
Model class:
class Model {
String id;
String email;
Model({
this.id,
this.email,
});
factory Model.fromJson(Map<String, dynamic> json) => new Model(
id: json["id"],
email: json["email"],
);
Map<String, dynamic> toJson() => {
"id": id,
"email": email,
};
#override
bool operator ==(Object other) =>
identical(this, other) ||
other is Model &&
runtimeType == other.runtimeType &&
id == other.id &&
email == other.email;
#override
int get hashCode =>
id.hashCode ^
email.hashCode;
}
main.dart
import 'package:collection/collection.dart';
var body =
'{"data":{"logsread":[{"id":"9fd66092-1f7c-4e60-ab8f-5cf7e7a2dd3b","email":"email#gmail.com"}]}}';
var test1 = (jsonDecode(body)['data']['logsread'] as List)
.map((value) => Model.fromJson(value))
.toList();
var test2 = ([
{"id": "9fd66092-1f7c-4e60-ab8f-5cf7e7a2dd3b", "email": "email#gmail.com"}
]).map((value)=>Model.fromJson(value)).toList();
Function eq = const ListEquality().equals;
print(eq(test1,test2));
I hope this is what you are looking for.
You should also provide position of the object you want to retrieve id from. Did you try doing this?
Example:
var id = ['data']['logsread'][0]['id'];
var email= ['data']['logsread'][0]['email'];
I mostly do this.
Your parse is correct, but I think that's not the right way to compare list of maps.
I think that doing == you're simply comparing the objects and not their content.
I suggest you to check here for map compare and here for list compare.
This way you would be checking the contents, and not roughly the objects (which are two different instances, so yeah technically they're different even if they have the same contents).
Try to first convert into the map and then use
import 'dart:convert';
//Decode response string to map
Map<String, dynamic> map = json.decode("jsonString");
xyz = map['data']['logsread'];
Related
I have a JSON response which I want to parse and extract the data from. Here is the JSON response
[
{
"od_pair":"7015400:8727100",
"buckets":[
{
"bucket":"C00",
"original":2,
"available":2
},
{
"bucket":"A01",
"original":76,
"available":0
},
{
"bucket":"B01",
"original":672,
"available":480
}
]
},
{
"od_pair":"7015400:8814001",
"buckets":[
{
"bucket":"C00",
"original":2,
"available":2
},
{
"bucket":"A01",
"original":40,
"available":40
},
{
"bucket":"B01",
"original":672,
"available":672
},
{
"bucket":"B03",
"original":632,
"available":632
},
{
"bucket":"B05",
"original":558,
"available":558
}
]
}
]
I want to extract each od_pair and the values of of bucket and available within them.
#Fenio's solution in Accessing jsonpath elements with nested objects has the best approaches. The code snippet that I have refactored looks like this:
List<HashMap<String, Object>> LegList = jsonPath.getList("$");
for (HashMap<String, Object> singleLeg : LegList) {
String OD_pair = (String) singleLeg.get("od_pair");
//List<HashMap<String, Object>> bucketsList = jsonPath.param("j", j).getList("[j].buckets");
List<HashMap<String, Object>> bucketsList = jsonPath.getList("singleLeg.buckets");
for (HashMap<String, Object> singleBucket : bucketsList) {
String BucketCode = (String) singleBucket.get("bucket");
String Available = (String)
singleBucket.get("available");
I want to verify if the bucketsList that I am extracting is correct. Earlier I used a for loop with the parameter j. But with this approach which is lot more cleaner and nicer, I wish to understand if I am right in the way am extracting the bucketsList
I managed to resolve this. I understood where I was going wrong. Replacing
List<HashMap<String, Object>> bucketsList = jsonPath.getList("singleLeg.buckets");
with this
List<HashMap<String, Object>> bucketsList = (List<HashMap<String, Object>>) singleLeg.get("buckets");
Has resolved my issue and now things work as expected.
Since I was already within singleLeg loop, all I needed to call was the buckets object within the loop rather than trying to access the buckets from the rootpath.
Big shoutout to #Fenio who advised the best approaches in Accessing jsonpath elements with nested objects
I am trying to parse data from a json. I think this image will help you to understand the problem.
I am getting
Exception has occurred.
_TypeError (type '(dynamic) => MainRank' is not a subtype of type '(String, dynamic) => MapEntry<dynamic, dynamic>' of 'transform')
If you hover over the body, you will see the black pop up with the data. ranks is a list and there are two extra properties there as well.
My MainRank class is like this
class MainRank{
String divisionName;
String tournamentName;
final List<Ranks> ranks;
MainRank(this.divisionName, this.tournamentName, this.ranks);
factory MainRank.fromJson(Map<String, dynamic> json) =>
_$MainRankFromJson(json);
Map<String, dynamic> toJson() => _$MainRankToJson(this);
}
Please help me with a little bit explanation how it works in dart. I am from php/js background so data types seems giving me hard time :) Thank you,
EDIT
Response from my api is
{
ranks: [....],
divisionName: "Division 2",
tournamentName: "Season 4"
}
And code I am using to parse the json is
Future _getData() async{
var res = await CallApi().getData('standings/${widget.id}');
final body = json.decode(res.body);
// final matches = body['matches'];
var data;
if(body!=null){
data = body.map((el) => MainRank.fromJson(el));
}
print(data);
return null;
}
You want to get the MainRank from your json data, so :
Change this :
var data;
if(body!=null){
data = body.map((el) => MainRank.fromJson(el));
}
To this:
MainRank data;
if(body!=null){
data = MainRank.fromJson(body);
}
List returnMovies = [];
Future<List> _getData() async {
final response = await http.get("https:../getTodayMovies",
headers: {HttpHeaders.AUTHORIZATION: Acess_Token.access_token});
if (response.body != null) {
returnMovies = json.decode(response.body);
.....
setState(() {});
} else {
final responseUpcoming = await http.get("/upcoming",
headers: {HttpHeaders.AUTHORIZATION: Acess_Token.access_token});
returnMovies = json.decode(responseUpcoming.body);
}
The response.body looks like:
[{"id":394470548,"host_group_name":"heyab redda","movie_image":"..png","type":"horror","code":"X123","name":"Lovely","start_time":1554364800,"end_time":1554393600,"}]
The responseUpcoming.body looks like:
{"id":394470545,"host_group_name":"foo redda","movie_image":".png","type":"horror","code":"X123","name":"Lovely","start_time":1554364800,"end_time":1554393600,"}, {"id":394470548,"host_group_name":"foo1 redda","movie_image":"..png","type":"comic","code":"X125","name":"Lovely1","start_time":1554364800,"end_time":1554393600,"}
The error I get is: String, dynamic is not a subtype of type List<dynamic>.
In the first API call that I am doing I normally get in return an array of objects, however, when this is empty, the second API call returns a list of objects that I want to push into the array called returnMovies, how can I achieve this?? Is there any way to .push these objects in the array?? So then I want to use this array to build dynamically a Listview.builder.
Also is it correct the way I am declaring it? I am quite new on Dart. Thank you
Sounds like you are looking for addAll
returnMovies.addAll(json.decode(returnUpcoming.body))
I will suggest to use
returnMovies.addAll({your object here})
When you do this json.decode(response.body) you are getting a List of Map you should use List<dynamic> movieListData and get the items like this:
movieListData = json.decode(response.body);
returnMovies = movieListData.map((dynamic movieData) {
String id = movieData['_id'];
String host_group_name = movieData['host_group_name'];
String duration = movieData['duration'];
return new Movie(id,title, duration);
}).toList();
I have this method, which compiles with no problems in Dart 2. However at run-time I get the following error
type 'List<dynamic>' is not a subtype of type 'List<ExchangeRate>'
As you see in the code I create and return new ExchangeRate objects within .map() and then after that I return a rateEntries.toList() which I expect to be of type List<ExchangeRate>, however it seems to be inferred as type List<dynamic>!!!
#override
Future<List<ExchangeRate>> getExchangeRatesAt(DateTime time, Currency baseCurrency) async {
final http.Client client = http.Client();
final String uri = "some uri ...";
return await client
.get(uri)
.then((response) {
var jsonEntries = json.decode(response.body) as Map<String, dynamic>;
var rateJsonEntries = jsonEntries["rates"].entries.toList();
var rateEntries = rateJsonEntries.map((x) {
return new ExchangeRate(x.value.toDouble());
});
return rateEntries.toList(); // WHY IS IT RETURNING A List<dynamic> here?
})
.catchError((e) => print(e))
.whenComplete(() => client.close());
}
However if I cast it specifically to ExchangeRate it would be fine.
return rateEntries.toList().cast<ExchangeRate>();
This casting at the end seems redundant to me, why should I need it?
Well, it seems that the cast is necessary to fully define the type.
But, you can avoid the cast if you add any of the following snippets:
Give the correct type to the rateJsonEntries variable
List<dynamic> rateJsonEntries = jsonEntries["rates"].entries.toList();
For whatever reason this works in my case.
Add the parameter type to the map() method
var rateEntries = rateJsonEntries.map<ExchangeRate>((x) {
return new ExchangeRate(x.value.toDouble());
});
Is there a way to implement GraphQL in flutter?
I was trying making the API call with the query and variables objects in a JSON object.
type '_InternalLinkedHashMap' is not a subtype of type 'String' in type cast
I have been using graphql_flutter package for a few weeks now and it seems to work well enough. Here is an example:
import 'package:graphql_flutter/graphql_flutter.dart' show Client, InMemoryCache;
...
Future<dynamic> post(
String body, {
Map<String, dynamic> variables,
}) async {
final Client client = Client(
endPoint: endpoint,
cache: new InMemoryCache(),
);
final Future<Map<String, dynamic>> result =
client.query(query: body, variables: variables);
return result;
}
To use just give it the graphql and any variables. i.e. a delete mutation may look like
String deleteMutation =
'''mutation deleteItem(\$itemId: ID!) {
deleteItem(input: { itemId: \$itemId}) {
itemId
}
}'''.replaceAll('\n', ' ');
await post(deleteMutation , variables: <String, dynamic>{'itemId': itemId});
This is updated and working solution of #aqwert
import 'package:graphql_flutter/graphql_flutter.dart';
...
HttpLink link = HttpLink(uri: /*your url here*/); // you can also use headers for authorization etc.
GraphQLClient client = GraphQLClient(link: link as Link, cache: InMemoryCache());
QueryOptions query = QueryOptions(
document:
r'''
mutation deleteItem($id: String!) {
deleteItem(callId: $id)
}
''',
variables: {'id' : id}
);
var result = await client.query(query);