Unhandled Exception: FormatException: Unexpected character (at character 1) | Error - json

I have a problem when logging in, it does not show me the data in the database, it seems that the problem is in the function that fetches the data, but I don't know where the problem is
This is the function that fetches data from the database:
Future<void> fetchProperties() async {
final url = Uri.https(
'aqarlibya-4d39c-default-rtdb.europe-west1.firebasedatabase.app',
'/properties.json?auth=$authToken');
try {
final response = await http.get(url);
final extractedData = json.decode(response.body) as Map<String, dynamic>?;
if (extractedData == null) {
return;
}
final List<Property> loadedProperties = [];
extractedData.forEach((propId, propData) {
loadedProperties.add(Property(
id: propId,
name: propData['name'],
description: propData['description'],
type: propData['type'],
propertySize: propData['propertySize'],
bedrooms: propData['bedrooms'],
price: propData['price'],
cityId: propData['cityId'],
imageUrl: propData['imageUrl'],
isFav: propData['isFav'],
));
});
_items = loadedProperties;
notifyListeners();
} catch (error) {
throw (error);
}
}
This is part of the code in the main file:
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider.value(
value: Auth(),
),
ChangeNotifierProxyProvider<Auth, Properties>(
create: (ctx) => Properties('', []),
update: (ctx, auth, previousProperties) => Properties(
auth.token,
previousProperties == null ? [] : previousProperties.items,
),
),
],
I tried looking for the problem but couldn't find it

As far as I can see from the documentation of Uri.https, you need to pass parameters in the optional third argument. So:
final url = Uri.https(
'aqarlibya-4d39c-default-rtdb.europe-west1.firebasedatabase.app',
'/properties.json',
{ 'auth': authToken }
);

Are you sure your url and your token is good ?
It seems like you try to json decode something that is not a json.
The value return by your call seems to be "not found".
Try to add a try {} catch(e) {} and print responseto get a better view of the error.

Related

InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'List<dynamic>'

Hoping for some help on this error please. I am getting an Error when I try to run my Autofill suggestions. I have three print statements to check how far the code is getting. I get the 'working?222' print but it doesn't make it to the 'did I get here' print statement. I receive the following error. The Error I'm getting is a Type Error which I haven't been able to fix. Error: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'List'. I know it's a type mismatch but I have been unsuccessful in fixing it. Here is my code where it fails.
import 'dart:convert';
import 'package:http/http.dart' as http;
class SugCompound {
final String compound;
const SugCompound({
required this.compound,
});
static SugCompound fromJson(Map<String, dynamic> json) => SugCompound(
compound: json['compound'],
);
}
class SugCompoundApi {
static Future<List<SugCompound>> getSugCompoundSuggestions(String query) async {
// print('working?');
final url = Uri.parse(
'https://website.com/rest/autocomplete/compound/$query/json?limit=6');
final response = await http.get(url);
print('working?222');
if (response.statusCode == 200) {
final List sugCompounds = json.decode(response.body);
print('did I get here');
return sugCompounds.map((json) =>
SugCompound.fromJson(json)).where((sugCompound) {
final compoundLower = sugCompound.compound.toLowerCase();
final queryLower = query.toLowerCase();
return compoundLower.contains(queryLower);
}).toList();
} else {
throw Exception();
// }
}
}
}
json looks like this:
{
"status": {
"code": 0
},
"total": 6,
"dictionary_terms": {
"compound": [
"aspirin",
"Aspirina",
"AspirinTest2",
"ASPIRIN (MART.)",
"ASPIRIN COMPONENT OF AXOTAL",
"ASPIRIN COMPONENT OF AZDONE"
]
}
}
error is where you are assigning a map to list:
final List sugCompounds = json.decode(response.body);
which is now allowed, you can Change your class like:
class SugCompound {
final List<String> compound;
const SugCompound({
required this.compound,
});
static SugCompound fromJson(Map<String, dynamic> json) => SugCompound(
compound: json['dictionary_terms']['compound'],
);
}
And your future will be like:
Future<List> getSugCompoundSuggestions(String query) async {
// print('working?');
final url = Uri.parse(
'https://website.com/rest/autocomplete/compound/$query/json?limit=6');
final response = await http.get(url);
if (response.statusCode == 200) {
SugCompound loadedSugCompound = SugCompound.fromJson(response.body);
List<String> compoundList = loadedSugCompound.compound;
compoundList = compoundList
.where((element) => element.toLowerCase().contains(query.toLowerCase()))
.toList();
return compoundList;
} else {
throw Exception();
// }
}
Now the future returns a list of what you searched, put this in FutureBuilder and show it into screen

How do I map a JSON map of list of map from API for HTTP get request

I keep getting this error:
NoSuchMethodError (NoSuchMethodError: The method 'map' was called on null.
Receiver: null
Tried calling: map(Closure: (dynamic) => Name1Name2))
I am trying very hard to solve this error. I am certain I am not mapping the data properly.
My fake REST API from which I'm fetching and sending the data to
"messagesBetweenTwoUsers": {
"Name1Name2": [
{
"senderName": "John",
"message": "How are you doing?"
}
]
}
This is my get messages file
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'messages_model.dart';
Future<List<MessageModel>> getMessages() async {
try {
var getResponse = await http.get(
Uri.parse("http://127.0.0.1:3000/messagesBetweenTwoUsers"),
);
if (getResponse.statusCode == 200) {
String getData = getResponse.body;
var jsonData =
jsonDecode(getData);
var getResult = jsonData["Name1Name2"].map(
(e) => Name1Name2.fromJson(e),
);
//here it throws me an error, in getResult, right when I am using map()
//NoSuchMethodError (NoSuchMethodError: The method 'map' was called on null.
//Receiver: null
//Tried calling: map(Closure: (dynamic) => Name1Name2))
return getResult;
} else {
return [];
}
} catch (error) {
debugPrint("ERROR IN FETCHING FROM GET-MESSAGE-API: $error");
}
return [];
}
My model class
import 'package:meta/meta.dart';
import 'dart:convert';
class MessageModel {
MessageModel({
required this.name1Name2,
});
final List<Name1Name2> name1Name2;
factory MessageModel.fromRawJson(String str) => MessageModel.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory MessageModel.fromJson(Map<String, dynamic> json) => MessageModel(
name1Name2: List<Name1Name2>.from(json["name1name2"].map((x) => Name1Name2.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"name1name2": List<dynamic>.from(name1Name2.map((x) => x.toJson())),
};
}
class Name1Name2 {
Name1Name2({
required this.senderName,
required this.message,
});
final String senderName;
final String message;
factory Name1Name2.fromRawJson(String str) => Name1Name2.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory Name1Name2.fromJson(Map<String, dynamic> json) => Name1Name2(
senderName: json["senderName"],
message: json["message"],
);
Map<String, dynamic> toJson() => {
"senderName": senderName,
"message": message,
};
}
You need to learn null safety but let me tell you how to fix your current code. It is simple!
Put a question mark ? before calling .map(). You should do that everywhere. For example, this should be
jsonData["Name1Name2"].map( ......
like this
jsonData["Name1Name2"]?.map( ......
The question mark ? simply check if the value before it is null and return null if it is or process the rest if it isn't.
try it like this
if (getResponse.statusCode == 200) {
String getData = getResponse.body;
var jsonData =
await json.decode(getData);
var getResult = jsonData["Name1Name2"].map(
(e) => Name1Name2.fromJson(e),
);
return getResult;
} else {
return [];
}
dont forget to import 'dart:convert';
This error says you are accessing a key which is not found directly into the JSON data. Looking into your JSON data, you have the key Name1Name2 nested into the messagesBetweenTwoUsers key value. Therefore, in order to access the value of the Name1Name2 key you should call first the messagesBetweenTwoUsers key, like this:
var getResult = jsonData["messagesBetweenTwoUsers"]["Name1Name2"].map(
(e) => Name1Name2.fromJson(e),
);
EDITED:
Use this JSON model instead:
{
"participants": [
{
"senderName": "John",
"receiverName": "Jakiro",
"message": "How are you doing?"
}
]
}
And decode the JSON data like this:
var getResult = (jsonData['participants'] as List).map(
(e) => Name1Name2.fromJson(e),
).toList();
As you are looking/decoding the json is not right, so the following website will help you do it - quicktype. I highly encourage you to explore the website with different options.
As #Mayo Win said. You do need to learn Null Safety feature. Otherwise it make your code prone to error.
From your method getMessages() just call the following -
CustomDataModel customDataModel = customDataModelFromJson(response.bodyString ?? '');

Error: Expected a value of type 'String', but got one of type '_MapStream<dynamic, Iterable<Post>>'

I have wrote the following code on server.
server code:
import 'dart:convert';
import 'package:mongo_dart/mongo_dart.dart';
import 'package:shelf/shelf.dart';
import 'package:shelf_web_socket/shelf_web_socket.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
class PostsSocketApi {
PostsSocketApi(this.store);
final List<WebSocketChannel> _sockets = [];
final DbCollection store;
Handler get router {
return webSocketHandler((WebSocketChannel socket) {
socket.stream.listen((message) async {
final data = json.decode(message);
print(data);
if (data['action'] == 'LOGIN') {
final user = await store.findOne(
where.eq('name', data['name']).eq('password', data['password']));
if (user != null) {
for (final ws in _sockets) {
ws.sink.add(json.encode('name'));
// probably there must be .toString() ^^^
}
}
if (user == null) {
for (final ws in _sockets) {
ws.sink.addError('NOSUCHUSER');
}
}
}
});
_sockets.add(socket);
});
}
}
And now I want to get the 'name' field into my variable tmp_name to compare it with name on login field, like that:
login code:
void loginUser() async {
final name = emailController.text;
final password = passwordController.text;
widget.api.send(
json.encode({'action': 'LOGIN', 'name': name, 'password': password}));
String tmp_name = widget.api.getName;
// method from API ^^^^^^^
if (tmp_name == name) {
SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
prefs.setString('name', name);
});
Navigator.of(context)
.pushReplacement(MaterialPageRoute(builder: (context) => Home()));
} else {
print('error: no such user');
}
}
API code in App:
class PostsSocketApi {
PostsSocketApi()
: _api = WebSocketChannel.connect(
Uri.parse('ws://localhost:8082/posts-ws/'));
final WebSocketChannel _api;
Stream<List<Post>> get stream => _api.stream.map<List<Post>>((data) {
final decoded = json.decode(data);
return (decoded as List)
.map<Post>(
(json) => Post.fromJson(json),
)
.toList();
});
ValueChanged<String> get send => _api.sink.add;
get getName => _api.stream.map((data) {
final decoded = json.decode(data['name']);
return (decoded as List).map<Post>(
(json) => Post.fromJson(json),
);
});
}
However, I got the following error in APP code and don't know how to solve it.
Error: Expected a value of type 'String', but got one of type '_MapStream<dynamic, Iterable<Post>>'
Server code works fine (compare data and print if it's wrong user)
Server response on register:
{action: ADDUSER, name: 6, password: 6, id: 6}
Server response on login as existing user:
{action: LOGIN, name: 6, password: 6}
Server response on login as NOT-existing user:
{action: LOGIN, name: fqfqfq, password: qfqfqfq}
NOSUCHUSER
ERROR - 2022-03-21 11:55:27.183011
Asynchronous error
type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'String'
PostsSocketApi.router.<fn>.<fn>
package:io/api/socket_api.dart:79
For Ruchit:
userID type is String. If I write like that, the same error thrown.
get getName => _api.stream.map((data) {
final decoded = json.decode(data['name']);
return (decoded as List)
.map<String>((json) => Post.fromJson(json).userID);
});
But, if I write like that, I get the type error:
error: The return type 'String' isn't a 'Post', as required by the closure's context.
Code:
get getName => _api.stream.map((data) {
final decoded = json.decode(data['name']);
return (decoded as List)
.map<Post>((json) => Post.fromJson(json).userID );
});
Any ideas? (Even about refactoring other code)
I'm tried to find some explanations in documentation, but... Write if u need some more code or explanations. Or if you can give me advice about how to make login by another way - tell me.
Please help me if you can <3
Here you are returning whole post object and you are getting as String which mismatches thus it is showing error.
get getName => _api.stream.map((data) {
final decoded = json.decode(data['name']);
return (decoded as List).map<Post>(
(json) => Post.fromJson(json).field, //here field is the field you want from Post object and you are getting string so this field should have type string.
//eg. Post.fromJson(json).name
);
});

Flutter compute method and filter results in json

I'm a really fresh new dev in flutter, I'm trying to filter results in a json response based on the title.
And i would like to use the compute method. This method only allow 2 arguments, so it's why i think i need to use a map to get the response.body and the query for filtering.
This is my HttpService :
class HttpService {
static List<Post> _parsePosts(Map map) {
print(map);
return map["body"].map((json) => Post.fromJson(json)).where((post) {
final titleLower = post.title.toLowerCase();
final queryLower = map["query"].toLowerCase();
return titleLower.contains(queryLower);
}).toList();
}
static Future<List<Post>> fetchPosts(String query) async {
final uri = Uri.parse('https://jsonplaceholder.typicode.com/posts');
final response = await retry(
() => http.get(uri).timeout(Duration(seconds: 10)),
retryIf: (e) => e is SocketException || e is TimeoutException,
);
Map posts = new Map();
posts["body"] = json.decode(response.body);
posts["query"] = query;
if (response.statusCode == 200) {
return compute(_parsePosts, posts);
} else {
throw Exception("Failed to load posts ${response.statusCode}");
}
}
}
The print(map); contains the map with values -> https://prnt.sc/131ldey
But the problem is reported on : return map["body"].map((json) => Post.fromJson(json)).where((post) {
with : _TypeError (type '(dynamic) => dynamic' is not a subtype of type '(dynamic) => bool' of 'test')
I really don't understand what is the reason of this error..
Your titleLower is not casted into a String type! So the contains method returns a dynamic value since it does not appear as the contains method of the String type for the VM !
final String myValue = ...;
return myValue.contains(‘a’);

How to fix Error type 'List<dynamic>' is not a subtype of type 'Map<String, dynamic>'

Hello I'm new to Dart programming and JSON. I'm using Flutter to develop my app. It needs to fetch data from an API. When I go to the URL on the page in Flutter to fetch data it shows me an error. How can I solve this error?
Rav class
class detalisRav {
int id;
String nameravs;
String date_from;
String detalis;
detalisRav({
this.id,
this.nameravs,
this.date_from,
this.detalis,
});
factory detalisRav.fromjson(Map<String, dynamic> json){
return detalisRav(
id: json['id'],
nameravs: json['nameravs'],
date_from: json['date_from'],
detalis: json['detalis'],
);
}
}
Function call API
Future<detalisRav> Showdetalis(int id ) async{
var token = await read();
final String url= 'showdetalis/$id';
String FullURL = Serveurl+url;
var response =await http.post(FullURL,
headers: {HttpHeaders.contentTypeHeader: "application/json", HttpHeaders.authorizationHeader: "Bearer $token"}
);
print('Token : ${token}');
print(response);
if (response.statusCode==200) {
print('data:${response.body}');
return detalisRav.fromjson(json.decode(response.body));
}
else{
throw Exception('Failed to load data from Server.');
}
}
Showing the data
return FutureBuilder<detalisRav>(
future:helper.Showdetalis(int.parse(widget.id)),
builder: (context,snaphost){
if (snaphost.hasData)
return Center(
child: Text(snaphost.data.nameravs),
);
else if (snaphost.hasError){
print('error:${snaphost.error}');
return Text("${snaphost.error}");
}
return CircularProgressIndicator();
},
);
}
The JSON used
[
{
"id": 72,
"nameravs": "ahmed ali ",
"image": "https://fathomless-brushlands-95996.herokuapp.com/images_ravs/1584134167.jpg",
"Captenname": "eng.ali",
"detalis": "Sentence"
}
]
The error
Error error.type 'List' is not a subtype of type 'Map'