NoSuchMethodError: Class 'int' has no instance method '[]' - json

I'm trying to get mysql data using laravel api and passing to a list, but it is returning "NoSuchMethodError: Class 'int' has no instance method '[]'."
=========
Error
I/flutter ( 8481): NoSuchMethodError: Class 'int' has no instance method '[]'.
I/flutter ( 8481): Receiver: 1
I/flutter ( 8481): Tried calling: []("idAnunFr")
This is the error
Provider (where the ForEach is)
import 'package:bicos_app/model/anuncio_Freelancer.dart';
import 'package:bicos_app/model/freelancer.dart';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:intl/intl.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../utils/freelancer_preferences.dart';
import '../utils/user_preferences.dart';
class AnunFreelancerProvider with ChangeNotifier {
late Freelancer freelancer;
List<AnuncioFreelancer> _anunciosMyFreelancer = [];
List<AnuncioFreelancer> getAnunciosMyFreelancer() => _anunciosMyFreelancer;
Future<dynamic> loadAnunMyFreelancer(int id) async {
try {
_anunciosMyFreelancer.clear();
var response = await Dio()
.get('http://10.0.2.2:8000/api/getAnunFreelancerByFreelancer/$id');
if (response.data['status'] == '200') {
response.data['anuncios'].forEach(
(k, e) {
AnuncioFreelancer anuncio = AnuncioFreelancer(
idAnunFr: e['idAnunFr'],
TituloAnunFr: e['TituloAnunFr'],
DescAnunFr: e['DescAnunFr'],
PrecoAnunFr: e['PrecoAnunFr'],
ImgAnunFr: e['ImgAnunFr'],
StatusAnunFr: e['StatusAnunFr'],
DataAnunFr: e['DataAnunFr'],
idFrAnunFr: e['idFrAnunFr'],
idTipoServAnunFr: e['idTipoServAnunFr'],
);
if (anuncio.StatusAnunFr == '1') {
if (_anunciosMyFreelancer
.any((element) => element.idAnunFr == anuncio.idAnunFr)) {
print('_');
} else {
_anunciosMyFreelancer.add(anuncio);
}
}
},
);
} else {
print(response.data['message'].toString());
}
notifyListeners();
} catch (e) {
print(e);
}
}
}
I tried to get all the 'anuncios' data and pass to a list
=========
Model
class AnuncioFreelancer {
final int idAnunFr;
final String TituloAnunFr;
final String DescAnunFr;
final double PrecoAnunFr;
final String ImgAnunFr;
final String StatusAnunFr;
final String DataAnunFr;
final int idFrAnunFr;
final int idTipoServAnunFr;
const AnuncioFreelancer({
required this.idAnunFr,
required this.TituloAnunFr,
required this.DescAnunFr,
required this.PrecoAnunFr,
required this.ImgAnunFr,
required this.StatusAnunFr,
required this.DataAnunFr,
required this.idFrAnunFr,
required this.idTipoServAnunFr,
});
}
========
Laravel Api Controller
this is the function that Dio.get is calling
public function getAnunFreelancerByFreelancer($idFrAnunFr)
{
if(TblAnunFreelancer::where('idFrAnunFr', $idFrAnunFr)->exists())
{
$anunfr = TblAnunFreelancer::find($idFrAnunFr);
return response()->json([
'status'=>'200',
'anuncios'=>$anunfr,
]);
} else {
return response()->json([
'status'=>'400',
'message'=>'Você não possui anúncios',
]);
}
}
==========
response.data sample:
idAnunFr: 1,
TituloAnunFr: 'Title',
DescAnunFr: 'Description',
PrecoAnunFr: 200.00,
ImgAnunFr: 'assets/images/testeImagemAnun.png',
StatusAnunFr: '1',
DataAnunFr: '2022-11-27',
idFrAnunFr: 1,
idTipoServAnunFr: 1,
it was supposed to get something like this
================
response variable debug

Your issue is in this logic:
response.data['anuncios'].forEach( ... )
Your API is only returning a single Record, not an array or multiple records, so there is no need for the forEach() at all:
if (response.data['status'] == '200') {
AnuncioFreelancer anuncio = AnuncioFreelancer(
idAnunFr: response.data['anuncios']['idAnunFr'],
TituloAnunFr: response.data['anuncios']['TituloAnunFr'],
DescAnunFr: response.data['anuncios']['DescAnunFr'],
PrecoAnunFr: response.data['anuncios']['PrecoAnunFr'],
ImgAnunFr: response.data['anuncios']['ImgAnunFr'],
StatusAnunFr: response.data['anuncios']['StatusAnunFr'],
DataAnunFr: response.data['anuncios']['DataAnunFr'],
idFrAnunFr: response.data['anuncios']['idFrAnunFr'],
idTipoServAnunFr: response.data['anuncios']['idTipoServAnunFr'],
);
}
If, for some reason you want to keep the .forEach(), then you'd need to change your API to return an array:
$anunfr = TblAnunFreelancer::where('id', $idFrAnunFr)->get();
return response()->json([
'status' => '200',
'anuncios' => $anunfr
]);
// OR
$anunfr = TblAnunFreelancer::find($idFrAnunFr);
return response()->json([
'status' => '200',
'anuncios' => [$anunfr]
]);
You can either use where('id', $idFrAnunFr)->get() to make $anunfr a Collection (array), or use ::find($idFrAnunFr) and return this single record as an array via 'anuncios' => [$anunfr]

Related

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

Mapping type error from JSON to Flutter entity: '(dynamic) => 'News' is not a subtype of type '(String, dynamic) => MapEntry<dynamic, dynamic>'

I am trying to read JSON file then assign the values into my flutter entity, using riverpod, statenotifier, and freezed for simple API test.
Currently, I get error like this when I parse JSON file and mapping into the entity
I/flutter ( 7083): type '(dynamic) => 'News' is not a subtype of type '(String, dynamic) => MapEntry<dynamic, dynamic>' of 'transform'
Here is my entity that has fromJson method with freezed.
#freezed
abstract class News with _$News {
const factory News({
bool? ok,
#Default(null) dynamic error,
Data? data,
}) = _News;
factory News.fromJson(Map<String, dynamic> json) =>
_$NewsFromJson(json);
}
This is my part of repository that trying to parse but received error.
my_data is correctly parsed and stored, but mapping into my entity News has some confilct
as above.
final NewsRepositoryProvider = Provider<NewsRepository>((ref) {
return NewsRepository();
});
class NewsRepository {
Future<List<News>> getNews() async {
// parse my local json file
final my_data =
json.decode(await rootBundle.loadString('temp.json'));
try {
return my_data
.map((dynamic item) =>
News.fromJson(item as Map<String, dynamic>))
.toList();
} on Exception catch (error) {
throw Exception('JSON failed: $error');
}
}
}
when I try to write like below, it returns NoSuchMethodError: Class _InternalLinkedHashMap<String, dynamic> has no instance method cast with matching arguments. and obviously it doesn't have a casting method... `
final my_data = json
.decode(await rootBundle.loadString('temp.json'))
.cast<Map<String, dynamic>>();
I am calling all methods from here which is part of my viewmodel.
final LatestFeedRepository _newsRepository;
final LatestFeedStateNotifier _newsManager;
Future<void> fetchLatestNews() async {
try {
final List<News> newList = await _newsRepository.getNews();
_newsManager.setNews(newList);
state = state.copyWith(isLoading: false);
} catch (e) {
print(e);
}
Here is my StateNotifierProvider, I want to call setNews with List<News> object that should be from parsing operation but currently I do have error I cannot pass the parameter.
#freezed
abstract class NewsState with _$NewsState {
const factory NewsState({
List<News>? news,
}) = _NewsState;
}
final newsProvider =
StateNotifierProvider<NewsStateNotifier, dynamic>(
(_) => NewsStateNotifier());
class NewsStateNotifier extends StateNotifier<NewsState>
with LocatorMixin {
NewsStateNotifier() : super(const NewsState());
void setNews(List<News> news) {
state = state.copyWith(news: news);
}
}

Why am I getting an error when trying to call a method with flutter chopper and built value?

I'm getting The below ERROR,I believe it's because of null safety, this means that no data has been received or getSignedInUser() method is incorrect or class BuiltValueConverter is the cause.
(I tested the token with Postman and retrieved the data)
E/flutter (21792): [ERROR:flutter/lib/ui/ui_dart_state.cc(186)]
Unhandled Exception: Unhandled error Null check operator used on a
null value occurred in Instance of 'AuthBloc'. E/flutter (21792): #0
BuiltValueConverter._deserialize
package:todo_list_app/…/auth/built_value_converter.dart:51 E/flutter
(21792): #1 BuiltValueConverter._convertToCustomObject
package:todo_list_app/…/auth/built_value_converter.dart:36 E/flutter
(21792): #2 BuiltValueConverter.convertResponse
package:todo_list_app/…/auth/built_value_converter.dart:25
I'm using chopper with built_value Pubs. i'm trying to convert the coming json to object.
Example:
{
"userName": "Jack",
"email": "jack2066#gmail.com",
"userRole": "USER",
"created_at": "2021-07-03T16:49:56.774Z",
"updated_at": "2021-07-03T16:49:56.774Z" }
the below code where the error start also explained in this Tutorial Converters & Built Value Integration
import 'package:built_collection/built_collection.dart';
import 'package:chopper/chopper.dart';
import 'package:todo_list_app/infrastructure/remote/auth/models/serializers.dart';
class BuiltValueConverter extends JsonConverter {
#override
Request convertRequest(Request request) {
return super.convertRequest(
request.copyWith(
body: serializers.serializeWith(
serializers.serializerForType(request.body.runtimeType)!,
request.body,
),
),
);
}
#override
Response<BodyType> convertResponse<BodyType, SingleItemType>(
Response response,
) {
final Response dynamicResponse = super.convertResponse(response);
final BodyType customBody =
_convertToCustomObject<SingleItemType>(dynamicResponse.body);//
return dynamicResponse.copyWith<BodyType>(body: customBody);
}
dynamic _convertToCustomObject<SingleItemType>(dynamic element) {
if (element is SingleItemType) return element;
if (element is List)
return _deserializeListOf<SingleItemType>(element);
else
return _deserialize<SingleItemType>(element);
}
BuiltList<SingleItemType> _deserializeListOf<SingleItemType>(
List dynamicList,
) {
// Make a BuiltList holding individual custom objects
return BuiltList<SingleItemType>(
dynamicList.map((element) => _deserialize<SingleItemType>(element)),
);
}
SingleItemType _deserialize<SingleItemType>(Map<String, dynamic> value,) {
// We have a type parameter for the BuiltValue type, which should be returned after deserialization.
return serializers.deserializeWith(
serializers.serializerForType(SingleItemType)!, // Error Start
value,
);
}
}
Here is my Chopper service code, getSignedInUser throw the error.
I don't know if the implementation of the getSignedInUser method is correct or not.
import 'package:chopper/chopper.dart';
import 'package:injectable/injectable.dart';
import 'package:todo_list_app/infrastructure/remote/auth/built_value_converter.dart';
import 'package:todo_list_app/infrastructure/remote/auth/models/auth_built_model.dart';
import 'package:todo_list_app/infrastructure/remote/core/constants.dart';
part 'auth_service.chopper.dart';
#singleton
#ChopperApi()
abstract class AuthService extends ChopperService {
#factoryMethod
static AuthService create() {
final client = ChopperClient(
baseUrl: AUTH_BASE_URL_External,
services: [
_$AuthService(),
],
converter: BuiltValueConverter(),
errorConverter: JsonConverter(),
interceptors: [
HttpLoggingInterceptor()
],
);
return _$AuthService(client);
}
#Post(path: '/signup')
Future<Response> signUp(#Body() RegisterRequestModel body);
#Post(path: '/signin')
Future<Response<LoginResponseModel>> singIn(#Body() LoginRequestModel body);
//headers: {AUTH_HEADER:BEARER+'authValue'}
#Get(path: '/auth', )//authValue='Bearer Token'
Future<Response<UserResponseModel>> getSignedInUser(#Header("Authorization") String authValue);//error Unhandled error Null check operator used on a null value
}
Any idea how to solve this Error?
also Is there a good documentation for Chopper or alternative pub with a good documentation?
Thanks
I think you are missing values in your "serielizers.dart" file it should be as followed :
#SerializersFor(const[RegisterRequestModel,LoginRequestModel,UserResponseModel])
final Serializers serializers =
(_$serializers.toBuilder()..addPlugin(StandardJsonPlugin())).build();
Yeah, as you said it's because of null safety. Your _deserialize returns a non-null value whereas the serializers.deserializeWith can return a null value. Either you can change the return type to be nullable, or handle the null case for serializers.deserializeWith. If you want you can use the below BuiltValueConverter. It is from the example which they have given which is generic, with minor changes.
import 'package:built_collection/built_collection.dart';
import 'package:built_value/serializer.dart';
import 'package:chopper/chopper.dart';
import 'package:graphical_representation/app/serializers.dart';
class BuiltValueConverter extends JsonConverter {
T? _deserialize<T>(dynamic value) => serializers.deserializeWith<T>(
(serializers.serializerForType(T) as Serializer<T>),
value,
);
BuiltList<T> _deserializeListOf<T>(Iterable value) => BuiltList(
value.map((value) => _deserialize<T>(value)).toList(growable: false),
);
dynamic _decode<T>(entity) {
/// handle case when we want to access to Map<String, dynamic> directly
/// getResource or getMapResource
/// Avoid dynamic or unconverted value, this could lead to several issues
if (entity is T) return entity;
try {
if (entity is List) return _deserializeListOf<T>(entity);
return _deserialize<T>(entity);
} catch (e) {
print(e);
return null;
}
}
#override
Response<ResultType> convertResponse<ResultType, Item>(Response response) {
// use [JsonConverter] to decode json
final jsonRes = super.convertResponse(response);
final body = _decode<Item>(jsonRes.body);
return jsonRes.copyWith<ResultType>(body: body);
}
#override
Request convertRequest(Request request) => super.convertRequest(
request.copyWith(
body: serializers.serialize(request.body),
),
);
}

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