The method 'map' was called on null

Bonjour à tous,
Lorsque j’essaie de récupérer mon utilisateur Directus pour me Login sur l’application j’obtiens certaines erreurs que je n’arrive pas à comprendre :

  • contributors = List.from(
    json[« contributors »].map((x) => PermutationsUser.fromJson(x))),
    ==>

" Une exception s’est produite.
NoSuchMethodError (NoSuchMethodError: The method ‹ map › was called on null. Receiver: null Tried calling: map(Closure: (dynamic) => PermutationsUser))"

ou

la ou je bug c’est que les erreurs ne se produisent pas pour tous mes objets que j’essaie de récupérer alors que je procède de la même manière, et que certains bugs ne se produisent pas lorsque je suis en debug (pas à pas donc peut être un problème d’asynchrone).

Ma function de log :

Future<Token?> loginUser(String email, String password) async {
    loading = true;
    Token? token;
    final response = await http.post(
      Uri.parse('https://serveur.test.fr/auth/login'),
      headers: <String, String>{
        'Content-Type': 'application/json; charset=UTF-8',
      },
      body: jsonEncode(<String, String>{'email': email, 'password': password}),
    );
    if (response.statusCode >= 200 && response.statusCode < 300) {
      final data = TokenJson.fromJson(jsonDecode(response.body)).data;
      token = data;
      expirationToken = DateTime.now().add(const Duration(seconds: 850));
      currentUser = await getCurrentUser(token: token);
      userIsConnected = true;
      await verifyIsPayantUser();
      print("current User chargé : $currentUser");
      loading = false;
    } else {
      loading = false;
      hasErrorLogin = true;
      // ignore: avoid_print
      print("Error loading");
    }
    return token;
  }
 Future<CurrentUser?> getCurrentUser({required Token token}) async {
    final accessToken = token.accessToken;
    CurrentUser? currentuser;
    final response = await http.get(
      Uri.parse(
          "https://serveur.test.fr/users/me?fields=*,station.*,alerts.id,alerts.alertStation,alerts.alertDepartment,alerts.alertCity,permutations.id,permutations.user_created.id,permutations.user_created.first_name,permutations.user_created.last_name,permutations.user_created.avatar,permutations.user_created.station.id,permutations.user_created.station.service,permutations.user_created.station.department,permutations.user_created.grade,permutations.user_created.deviceToken,permutations.user_created.iosOrAndroid,permutations.user_created.location"),
      headers: <String, String>{
        'Content-Type': 'application/json; charset=UTF-8',
        HttpHeaders.authorizationHeader: 'Bearer $accessToken'
      },
      // body: jsonEncode(<String, String>{'email': email, 'password': password}),
    );

    if (response.statusCode >= 200 && response.statusCode < 300) {
      final data = CurrentUserJson.fromJson(jsonDecode(response.body)).data;
      currentuser = data;
      String? devicToken;
      // final deviceToken = UserSettings.getDeviceToken().then((value) {
      //   devicToken = value;
      // });
      if (devicToken == "" || devicToken != currentuser.deviceToken) {
        await updateCurrentUser(token: token, deviceToken: devicToken);
      }
      if (currentuser.iosOrAndroid == null ||
          currentuser.iosOrAndroid != "Android") {
        await updateCurrentUser(
            token: token, iosOrAndroid: 'Android', deviceToken: devicToken);
        currentUser?.iosOrAndroid = 'Android';
      }
      print('Utilisateur chargé');
      return currentuser;
    } else {
      print('Impossible de charger lutilisateur');
      return null;
    }
  }

ps : qui n’a rien à voir mais j’ai également une alert dans mon android/app/build.gradle
« throw new GradleException(« Flutter SDK not found. Define location with flutter.sdk in the local.properties file. ») »

alors qu’en vérifiant mon chemin est correct :

sdk.dir=/Users/rm/Library/Android/sdk
flutter.sdk=/Users/rm/flutter
flutter.buildMode=debug
flutter.versionName=1.0.0
flutter.versionCode=1

Salut @PapaRoack,

si json["contributors"].map((x) => PermutationsUser.fromJson(x)) génère NoSuchMethodError (NoSuchMethodError: The method ‹ map › was called on null. Receiver: null Tried calling: map(Closure: (dynamic) => PermutationsUser))"

Alors ça veut dire que json["contributors"] est null.

  • soit tu n’as pas de clé dans ton json qui correspond à la clé contributors,
  • soit tu n’es pas au bon niveau du json quand tu l’appelles (par exemple tu es à la racine, et tu as un premier objet JSON dans lequel tu dois entrer avant de pouvoir accéder à a propriété contributors).

Oui c’est ce que j’avais compris, mais étant donné que la variable est optionnelle cela ne devrait pas poser de problème si? Surtout que pour d’autre variable a peu près au même niveau je procède de la même manière et cela se passe sans accrocs…

Je poste ma logique pour mieux éclairer :

Je veux récupérer mon utilisateur :

class CurrentUser {
  String id;
  String? firstName;
  String? lastName;
  String? email;
  String? role;
  String? location;
  String? description;
  String? status;
  String? avatar;
  String? professionalEmail;
  StationUser? station;
  String? grade;
  bool? isPayantUser;
  String? deviceToken;
  String? iosOrAndroid;
  List<AlertDirectus>? alerts;
  bool? userValidateAccount;
  String? passwordFirstConnection;
  List<Permutation>? permutations;
  CurrentUser(this.id);
  CurrentUser.fromJson(Map<String, dynamic> objectData)
      : id = objectData["id"],
        firstName = objectData["first_name"],
        lastName = objectData["last_name"],
        email = objectData["email"],
        role = objectData["role"],
        location = objectData["location"],
        description = objectData["description"],
        status = objectData["status"],
        avatar = objectData["avatar"],
        professionalEmail = objectData["professional_email"],
        station = StationUser.fromJson(objectData["station"]),
        grade = objectData["grade"],
        isPayantUser = objectData["isPayantUser"],
        deviceToken = objectData["deviceToken"],
        iosOrAndroid = objectData["iosOrAndroid"],
        alerts = List<AlertDirectus>.from(
            objectData["alerts"].map((x) => AlertDirectus.fromJson(x))),
        userValidateAccount = objectData["userValidateAccount"],
        passwordFirstConnection = objectData["passwordFirstConnection"],
        permutations = List<Permutation>.from(
            objectData["permutations"].map((x) => Permutation.fromJson(x)));
}

ensuite je passe par permutation :

class Permutation {
  final String id;
  final UserConversation userCreated;
  final String? dateCreated;
  final String? status;
  final String? content;
  final List<PermutationsUser>? contributors;
  final StationPermutation? station;
  final String? destinationStation;
  final String? departure;
  final String? intermediate;
  final String? destinationDepartments;
  final String? logement;
  final String? title;
  final String? destinationCity;
  final String? dateRegister;
  Permutation(
      {required this.id,
      required this.userCreated,
      this.dateCreated,
      this.status,
      this.content,
      this.contributors,
      this.station,
      this.destinationStation,
      this.departure,
      this.intermediate,
      this.destinationDepartments,
      this.logement,
      this.title,
      this.destinationCity,
      this.dateRegister});
  Permutation.fromJson(Map<String, dynamic> json)
      : id = json["id"],
        userCreated = UserConversation.fromJson(json["user_created"]),
        dateCreated = json["date_created"],
        status = json["status"],
        content = json["content"],
        contributors = List<PermutationsUser>.from(
            json["contributors"].map((x) => PermutationsUser.fromJson(x))),
        station = StationPermutation.fromJson(json["station"]),
        destinationStation = json["destinationStation"],
        departure = json["departure"],
        intermediate = json["intermediate"],
        destinationDepartments = json["destinationDepartment"],
        logement = json["logement"],
        title = json["title"],
        destinationCity = json["destinationCity"],
        dateRegister = json["date_register"];
}

et dans contributor je passe à :

class PermutationsUser {
  final UserConversation? directusUsersId;
  PermutationsUser({this.directusUsersId});
  PermutationsUser.fromJson(Map<String, dynamic> json)
      : directusUsersId = UserConversation.fromJson(json["directus_users_id"]);
}

je ne vois pas ou est le soucis surtout que juste avant je passe par la liste d’Alerts qui est exactement pareil et pas de soucis

Il faudrait que tu nous mettes un extrait du JSON dans lequel on voit les permutations qui provoquent le crash. Possible qu’elles n’aient pas la clé contributors ou que la valeur soit nulle

Mon Json pour les permutations :

{
      "id": "111111111111",
      "status": "published",
      "user_created": "11111111111111",
      "date_created": "2022-10-12T11:31:50.000Z",
      "content": "partir ",
      "destinationStation": null,
      "departure": "Toulon",
      "intermediate": null,
      "destinationDepartments": "83",
      "logement": "",
      "title": "Partir",
      "destinationCity": "La garde",
      "date_register": "12 Oct 2022",
      "station": "092555bb-7958-4c31-ad18-944672aa62a2",
      "contributors": []
    },

Le contributor est simplement vide, mais je me pose quand même la question, même si la valeur dans mon json est nulle, étant donné que les variables de mon objet son optionnelles cela ne devrait pas poser de problème non?

Et tu me garantis qu’il s’agit bien de ce JSON qui provoque le crash :

NoSuchMethodError (NoSuchMethodError: The method ‹ map › was called on null. Receiver: null Tried calling: map(Closure: (dynamic) => PermutationsUser))"

Si tu fais un test auto dans lequel tu passes ce JSON à ta fonction de parsing tu as bien le crash ?

Tu n’as pas certaines lignes du JSON qui fonctionnent et d’autres qui ne fonctionnent pas ?

Oui c’est bien celui la qui provoque le crash, je passe par le json de mon currentUser qui essaye de récupérer ce Json des permutations, toutes les lignes sont ok, juste quand j’arrive à « contributors » ca crash.
Pour les tests je ne sais pas je ne les utilisent pas encore (je sais que c’est dommage mais je n’ai pas encore eu le temps de m’y pencher, j’ai finis la version swiftUI de mon app et j’essaye de sortir la version android au plus vite, je prendrai le temps après).

Le message dit que la propriété contient une valeur nulle, c’est forcément ce qui s’est passé.
Est-ce que ce bug arrive tout le temps et tu peux le reproduire systématiquement ? Si oui alors, je te conseille d’utiliser le deboggeur et d’avancer pas à pas pour comprendre pourquoi cette propriété « contributors » est nulle.

Dans le JSON que tu m’as envoyé ça n’est pas le cas mais peut être que dans ta liste, un ou plusieurs de tes utilisateurs a sa liste de contributeurs qui est nulle (ou alors que la propriété « contributors » soit absente du JSON pour ces utilisateurs), ce qui provoque le crash.

Oui c’est ce que je me suis dis pour la liste des contributeurs.
Le bug se reproduit systématiquement, du coup pour palier au problème j’ai légèrement modifié mon appel, histoire de passer outre.
Cela ne résout pas le problème, mais au moins s il ne se présente plus.
Il faudra quand même que j’essaye de voir ce qui ne marchait pas.