Save json data (multiple items) into a map - dart

i Have a json file that is fetched from my server, i'd like to save the data into a map using a model, what's the proper way to do it?
I've created a model to decode the json data. My json file has some "[ ]" if i use another json file (single item) without "[ ]" it works but not with the bracket.
Here is my model
class RestoModel {
// int id;
String name;
RestoModel(this.name);
RestoModel.fromJson(Map<String, dynamic> data) {
name = data['name'];
}
}
My fetch function
List<RestoModel> restaurantList = [];
void fetchRestaurants() async {
var response = await get('https://link/get_list.php');
var data = RestoModel.fromJson(json.decode(response.body));
setState(() {
restaurantList.add(data);
print(response.body);
});
}
i get this error
Unhandled Exception: type 'List<dynamic>' is not a subtype of type 'Map<String, dynamic>'
Here is my json data
[{"id":"1","name":"Resto 1"},{"id":"3","name":"Resto 2\r\n"}]
but my code works with this json data
{
"name": "beatae et provident et ut vel",
}
I want the json file to be saved in the List but i get this error
Unhandled Exception: type 'List<dynamic>' is not a subtype of type 'Map<String, dynamic>'

{"id":"1","name":"Resto 1"} is a map, [{"id":"1","name":"Resto 1"},{"id":"3","name":"Resto 2\r\n"}] is a List of Map. So basically when you're decoding your json, you've ended up with list of model, id:1 and id:2. You're trying to give List of dynamics to your named constructor which takes a single Map as a parameter, not list of them.
Try this:
Iterable i = json.decode(response.body);
List<RestoModel> restaurantList = i.map((model) => RestoModel.fromJson(model)).toList();
In this code, I have an iterable, and for each restaurant data in that iterable I'm creating restomodel from json.

Related

Fetching Value From Json Object Stored as String for a Key in Response payload

How do I read a value from below response payload. From the second property in this JSON object, how do I fetch the value for the 'status' i.e "Active" or any other value for response key.
{
"signature": "1hdj12493039282849922",
"response": "{'UsersList':[{'userName':'Madan Jones','mobileNumber':'767780987','status':'Active','statusCode':null}],'status':0,'messageCode':null,'message':null,'errorMap':null}"
}
Any help is greatly appreciated!! Thanks in advance!!
Your response contains just a text that only looks like another json. So in order to do a check you have to fetch that value, parse it and hope that it would be a valid json too.
public static void main(String[] args) throws JsonProcessingException {
String str = RestAssured
.get("http://demo1954881.mockable.io/textjson")
.jsonPath().get("response");
JsonPath jsonPath = new JsonPath(str.replace("'", "\""));
String status = jsonPath.get("UsersList.find{u -> u.userName = 'Madan Jones'}.status");
MatcherAssert.assertThat(status, Matchers.equalTo("Active2"));
}
In your particular example JsonPath does not like that your field names are wrapped with ' so I change them to be proper double-quotes.

Value type error in a map that is <String, dynamic>

I'm trying to construct a https Uri that looks like this:
static Uri accountGetFavoriteMovies(int accountId, LoginInformation loginInfo,
{int page = 1}) {
final url = '/account/$accountId/favorite/movies';
final uri = _resolveUri(
url,
query: {
'api_key': _apiKey,
'session_id': loginInfo.sessionId,
'page': page,
},
);
return uri;
}
And what _resolveUri does simply a wrapper to Uri.https constructor:
Uri _resolveUri(String path, {Map<String, dynamic>? query}) {
return Uri.https(
_authority,
_basePath + path,
query,
);
}
Theoretically this should be working fine, but when I tested it, and I got this message:
type 'int' is not a subtype of type Iterable<dynamic>
Where's the problem?
I am convinced the problem is in the query parameter because of this stack:
_resolveUri
_AccountUrls.accountGetFavoriteMovies
_AccountRequest.favoriteMoviesRequest
Although the type for queryParameters is Map<String, dynamic>, the value expected by Uri.https is actually String or Iterable<String>.
I found this comment in the source code of the Uri library on github while trying to debug your question.
A value in the map must be either a String, or an Iterable of strings,
where the latter corresponds to multiple values for the same key.
Source of the Quote
Other Comment of Importance

flutter type error while parsing json data using json serialisable

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

Map one field value to other field using Gson on condition like if first one is null or having value zero

I am trying to map one field value to other if that is null or zero. I am using Gson library to parse Json. Is there any way to map values on condition base. I tried using JsonAdapter where I can put condition for that field but unable to find out solution how to get other field value there to put in that.
Write your own deserializer implementing JsonDeserializer<Element> something like below according json response-
class CustomDeserializer implements JsonDeserializer<Element> {
#Override
public Element deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context) throws JsonParseException {
JsonObject jobject = json.getAsJsonObject();
JsonObject object = jobject.get("key").getAsJsonObject();
if(object == null){
}
return null;
}
}
Usage -
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Element.class, new CustomDeserializer());
Gson gson = gsonBuilder.create();

Flutter MethodChannel nested values: 'List<dynamic>' is not a subtype of type 'FutureOr<List<Map<String, double>>>'

I'm writing a Flutter Plugin that sends a List of Maps (List<Map<String, double>>) from the Platform specific side. On the Platform specific side, I'm sending these Objects using the Default Message Codec.
// (example: Android side)
List<Map<String, Double>> out = new ArrayList<>();
... fill the map ...
result.success(out);
I'm receiving these values as follows on the Dart side:
static Future<List<Map<String, double>>> getListOfMaps() async {
var traces = await _channel.invokeMethod('getListOfMaps');
print(traces); // works
return traces;
}
Printing the values gives the correct values. However, on the Function Return, I'm getting the following Error type 'List<dynamic>' is not a subtype of type 'FutureOr<List<Map<String, double>>>' on run-time, indicating that the cast from the dynamic value to the specific Map<String, double> didn't work.
How do I cast nested values coming from MethodChannels correctly in Dart?
As pointed out in the comments, I have to cast every value with unknown runtime type individually to the expected type.
static Future<List<Map<String, double>>> getListOfMaps() async {
List<dynamic> traces = await _channel.invokeMethod(...);
return traces
.cast<Map<dynamic, dynamic>>()
.map((trace) => trace.cast<String, double>())
.toList();
}
You can now use invokeListMethod:
Since invokeMethod can only return dynamic maps, we instead create a new typed list using List.cast.
var channel = MethodChannel('foo_channel');
var list = await channel.invokeListMethod<Map<String, double>>('methodInJava');

Resources