Ошибка типа: тип «String» не является подтипом типа «Map<String, Dynamic>»

Я пытаюсь получить данные из локального хранилища и отобразить их на экране с помощью flutter_bloc, но получаю сообщение об ошибке «тип «String» не является подтипом типа «Map<String, Dynamic>». Я проверил, но не могу найти решение.

Кто-нибудь помогите мне решить эту ошибку...

Ниже мой код...

И я добавил BlockProvider в файл main.dart.

void main() async {
  runApp(
    MultiBlocProvider(
      providers: [
        BlocProvider<ResumeTemplatePreviewBloc>(
            create: (context) => ResumeTemplatePreviewBloc()),
      ],
      child: const MaterialApp(
        home: ResumeTempletePreview(isstart: true),
      ),
    ),
  );
}

резюме_templete_preview_bloc.dart

class ResumeTemplatePreviewBloc
    extends Bloc<ResumeTemplatePreviewEvent, ResumeTemplatePreviewState> {
  ResumeTemplatePreviewBloc() : super(ResumeTemplatePreviewInitial()) {
    on<LoadResumeData>(_onLoadResumeData);
  }

  void _onLoadResumeData(
      LoadResumeData event, Emitter<ResumeTemplatePreviewState> emit) async {
    emit(ResumeTemplatePreviewLoading());
    try {
      final jsonString = window.localStorage['RESUMEDATA'];
      if (jsonString == null || jsonString.isEmpty) {
        throw Exception('No resume data found in local storage');
      }

      final Map<String, dynamic> resumeData = json.decode(jsonString);
      log("Decoded resume data: $resumeData");

      emit(ResumeTemplatePreviewLoaded(resumeData));
    } catch (e) {
      log(e.toString());
      emit(ResumeTemplatePreviewError(e.toString()));
    }
  }
}

резюме_templete_preview_event.dart

import 'dart:typed_data';

import 'package:equatable/equatable.dart';

abstract class ResumeTemplatePreviewEvent extends Equatable {
  const ResumeTemplatePreviewEvent();

  @override
  List<Object> get props => [];
}

class LoadResumeData extends ResumeTemplatePreviewEvent {}

class DownloadResume extends ResumeTemplatePreviewEvent {
  final Uint8List capturedImage;

  const DownloadResume(this.capturedImage);

  @override
  List<Object> get props => [capturedImage];
}

резюме_templete_preview_state.dart

import 'package:equatable/equatable.dart';

abstract class ResumeTemplatePreviewState extends Equatable {
  const ResumeTemplatePreviewState();

  @override
  List<Object> get props => [];
}

class ResumeTemplatePreviewInitial extends ResumeTemplatePreviewState {}

class ResumeTemplatePreviewLoading extends ResumeTemplatePreviewState {}

class ResumeTemplatePreviewLoaded extends ResumeTemplatePreviewState {
  final Map<String, dynamic> resumeData;

  const ResumeTemplatePreviewLoaded(this.resumeData);

  @override
  List<Object> get props => [resumeData];
}

class ResumeTemplatePreviewError extends ResumeTemplatePreviewState {
  final String message;

  const ResumeTemplatePreviewError(this.message);

  @override
  List<Object> get props => [message];
}

class ResumeDownloading extends ResumeTemplatePreviewState {}

class ResumeDownloaded extends ResumeTemplatePreviewState {}

class ResumeDownloadError extends ResumeTemplatePreviewState {
  final String message;

  const ResumeDownloadError(this.message);

  @override
  List<Object> get props => [message];
}

резюме_templete_preview.dart

import 'dart:convert';
import 'dart:developer';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'dart:html';

import 'package:flutter/material.dart';
import 'package:quick_resume_creator/core/colors/app_colors.dart';
import 'package:quick_resume_creator/core/constants/dimens.dart';
import 'package:quick_resume_creator/models/education.dart';
import 'package:quick_resume_creator/models/employment.dart';
import 'package:quick_resume_creator/models/personal_skill.dart';
import 'package:quick_resume_creator/models/professional_skill.dart';
import 'package:quick_resume_creator/models/skill.dart';
import 'package:quick_resume_creator/screens/home_screen/home_screen.dart';
import 'package:quick_resume_creator/screens/resume_template/resume_template1.dart';
import 'package:quick_resume_creator/screens/resume_template/resume_template2.dart';
import 'package:quick_resume_creator/screens/resume_templete_preview/resume_templete_preview_bloc/resume_templete_preview_bloc.dart';
import 'package:quick_resume_creator/screens/resume_templete_preview/resume_templete_preview_bloc/resume_templete_preview_event.dart';
import 'package:quick_resume_creator/screens/resume_templete_preview/resume_templete_preview_bloc/resume_templete_preview_state.dart';

class ResumeTempletePreview extends StatefulWidget {
  final dynamic extra;
  final bool isstart;
  const ResumeTempletePreview({super.key, this.extra, required this.isstart});

  @override
  State<ResumeTempletePreview> createState() => _ResumeTempletePreviewState();
}

class _ResumeTempletePreviewState extends State<ResumeTempletePreview> {
  String resumeIndex = "";

  late ScrollController _scrollController;

  @override
  void initState() {
    _scrollController = ScrollController();
    _scrollController.addListener(() {
      setState(() {
        if (_scrollController.offset >= 300) {
          showBackToTopButton = true;
        } else {
          showBackToTopButton = false;
        }
      });
    });

    super.initState();

    context.read<ResumeTemplatePreviewBloc>().add(LoadResumeData());
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        backgroundColor: AppColors.authBgcolor,
        appBar: _buildappbar(),
        body: ListView(
          children: [
            Divider(color: AppColors.dividercolor, height: 1),
            buildSizedBoxH(50),
            BlocBuilder<ResumeTemplatePreviewBloc, ResumeTemplatePreviewState>(
              builder: (context, state) {
                if (state is ResumeTemplatePreviewLoading) {
                  log("state is ResumeTemplatePreviewLoading");
                  return const Center(child: CircularProgressIndicator());
                } else if (state is ResumeTemplatePreviewLoaded) {
                  log("state is ResumeTemplatePreviewLoaded");
                  resumeIndex = state.resumeData['id'] != null &&
                          state.resumeData['id'] != ""
                      ? state.resumeData['id'].toString()
                      : "1";
                } else if (state is ResumeTemplatePreviewError) {
                  log("state is ResumeTemplatePreviewError");
                  return Center(child: Text(state.message));
                }
                return getResumeTemplate(resumeIndex);
              },
            ),
          ],
        ));
  }

  Widget getResumeTemplate(String status) {
    switch (status) {
      case '1':
        return ResumeTemplate1(
          customerFirstNametext:
              window.localStorage['CUSTOMERFIRSTNAME'].toString(),
          customerLastNametext:
              window.localStorage['CUSTOMERLASTNAME'].toString(),
          customerProfileImageURL:
              window.localStorage['CUSTOMERPROFILEIMAGE'].toString(),
          customerProfessiontext:
              window.localStorage['CUSTOMERPROFESSION'].toString(),
          customerLocationtext:
              window.localStorage['CUSTOMERLOCATION'].toString(),
          customerWebsitetext:
              window.localStorage['CUSTOMERWEBSITE'].toString(),
          customerPhoneNotext:
              window.localStorage['CUSTOMERPHONENO'].toString(),
          customerEmailIDtext:
              window.localStorage['CUSTOMEREMAILID'].toString(),
          customerProfessionalSummarytext:
              window.localStorage['CUSTOMERPROFESSIONALSUMMARY'].toString(),
          customerEducationList:
              (jsonDecode(window.localStorage['CUSTOMEREDUCATIONLIST']!)
                      as List<dynamic>)
                  .map<Education>((item) => Education.fromJson(item))
                  .toList(),
          customerEmploymentList:
              (jsonDecode(window.localStorage['CUSTOMEREMPLOYMENTLIST']!)
                      as List<dynamic>)
                  .map<Employment>((item) => Employment.fromJson(item))
                  .toList(),
          customerProfessionalSkillList:
              (jsonDecode(window.localStorage['CUSTOMERPROFESSIONALSKILLLIST']!)
                      as List<dynamic>)
                  .map<ProfessionalSkill>(
                      (item) => ProfessionalSkill.fromJson(item))
                  .toList(),
          customerPersonalSkillList:
              (jsonDecode(window.localStorage['CUSTOMERPERSONALSKILLLIST']!)
                      as List<dynamic>)
                  .map<PersonalSkill>((item) => PersonalSkill.fromJson(item))
                  .toList(),
        );
      case '2':
        return ResumeTemplate2(
          customerFirstNametext:
              window.localStorage['CUSTOMERFIRSTNAME'].toString(),
          customerLastNametext:
              window.localStorage['CUSTOMERLASTNAME'].toString(),
          customerProfileImageURL:
              window.localStorage['CUSTOMERPROFILEIMAGE'].toString(),
          customerProfessiontext:
              window.localStorage['CUSTOMERPROFESSION'].toString(),
          customerLocationtext:
              window.localStorage['CUSTOMERLOCATION'].toString(),
          customerWebsitetext:
              window.localStorage['CUSTOMERWEBSITE'].toString(),
          customerPhoneNotext:
              window.localStorage['CUSTOMERPHONENO'].toString(),
          customerEmailIDtext:
              window.localStorage['CUSTOMEREMAILID'].toString(),
          customerProfessionalSummarytext:
              window.localStorage['CUSTOMERPROFESSIONALSUMMARY'].toString(),
          customerEducationList:
              (jsonDecode(window.localStorage['CUSTOMEREDUCATIONLIST']!)
                      as List<dynamic>)
                  .map<Education>((item) => Education.fromJson(item))
                  .toList(),
          customerEmploymentList:
              (jsonDecode(window.localStorage['CUSTOMEREMPLOYMENTLIST']!)
                      as List<dynamic>)
                  .map<Employment>((item) => Employment.fromJson(item))
                  .toList(),
          customerSkillList:
              (jsonDecode(window.localStorage['CUSTOMERSKILLLIST']!)
                      as List<dynamic>)
                  .map<Skill>((item) => Skill.fromJson(item))
                  .toList(),
        );
      default:
        return ResumeTemplate1(
          customerFirstNametext:
              window.localStorage['CUSTOMERFIRSTNAME'].toString(),
          customerLastNametext:
              window.localStorage['CUSTOMERLASTNAME'].toString(),
          customerProfileImageURL:
              window.localStorage['CUSTOMERPROFILEIMAGE'].toString(),
          customerProfessiontext:
              window.localStorage['CUSTOMERPROFESSION'].toString(),
          customerLocationtext:
              window.localStorage['CUSTOMERLOCATION'].toString(),
          customerWebsitetext:
              window.localStorage['CUSTOMERWEBSITE'].toString(),
          customerPhoneNotext:
              window.localStorage['CUSTOMERPHONENO'].toString(),
          customerEmailIDtext:
              window.localStorage['CUSTOMEREMAILID'].toString(),
          customerProfessionalSummarytext:
              window.localStorage['CUSTOMERPROFESSIONALSUMMARY'].toString(),
          customerEducationList:
              (jsonDecode(window.localStorage['CUSTOMEREDUCATIONLIST']!)
                      as List<dynamic>)
                  .map<Education>((item) => Education.fromJson(item))
                  .toList(),
          customerEmploymentList:
              (jsonDecode(window.localStorage['CUSTOMEREMPLOYMENTLIST']!)
                      as List<dynamic>)
                  .map<Employment>((item) => Employment.fromJson(item))
                  .toList(),
          customerProfessionalSkillList:
              (jsonDecode(window.localStorage['CUSTOMERPROFESSIONALSKILLLIST']!)
                      as List<dynamic>)
                  .map<ProfessionalSkill>(
                      (item) => ProfessionalSkill.fromJson(item))
                  .toList(),
          customerPersonalSkillList:
              (jsonDecode(window.localStorage['CUSTOMERPERSONALSKILLLIST']!)
                      as List<dynamic>)
                  .map<PersonalSkill>((item) => PersonalSkill.fromJson(item))
                  .toList(),
        );
    }
  }
}

Это моя консоль отладки...

Restarted application in 244ms.
[log] TypeError: "{\"uid\":\"ryln8SHS9fg7cTE7sTdwS4dzmeH2\",\"id\":\"6\",\"resumeid\":\"fXFhqH02zX8iv8THRVB1\",\"customerFirstNametext\":\"Testing\",\"customerLastNametext\":\"Testing\",\"customerProfileImage\":\"https://firebasestorage.googleapis.com/v0/b/quick-resume-creator.appspot.com/o/profile_images%2Fryln8SHS9fg7cTE7sTdwS4dzmeH2%2FfXFhqH02zX8iv8THRVB1%2F1720696073185.jpg?alt=media&token=8c803ce4-4a98-43f2-b630-ccec214a317f\",\"customerProfessiontext\":\"Testing\",\"customerLocationtext\":\"Testing\",\"customerWebsitetext\":\"www.testing.com\",\"customerPhoneNotext\":\"7894561230\",\"customerEmailIDtext\":\"[email protected]\",\"customerProfessionalSummarytext\":\"TestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTestingTesting.\",\"customerEducationList\":[{\"university\":\"Testing\",\"degree\":\"Testing\",\"startDate\":\"Jul 2023\",\"endDate\":\"Jul 2033\"}],\"customerEmploymentList\":[{\"jobTitle\":\"Testing\",\"companyName\":\"Testing\",\"startDate\":\"Jul 2023\",\"endDate\":\"Jul 2025\",\"address\":\"Testing\"}],\"customerProfessionalSkillList\":[],\"customerPersonalSkillList\":[],\"customerSkillList\":[{\"skill\":\"Testing\",\"level\":60},{\"skill\":\"Testing\",\"level\":40},{\"skill\":\"Testing\",\"level\":40}],\"customerSkillLavel\":0}": type 'String' is not a subtype of type 'Map<String, dynamic>'
[log] state is ResumeTemplatePreviewError

Помогите пожалуйста решить эту ошибку...

ваш jsonString начинается (и заканчивается) на ", поэтому он декодируется как String, а не Map

pskink 15.07.2024 08:22

Можете ли вы напечатать jsonString перед вызовом json.decode(jsonString), чтобы увидеть фактические данные?

Alex Sunder Singh 15.07.2024 08:30

@AlexSunderSingh это напечатано в журналах

pskink 15.07.2024 08:39

[журнал] QuickResumeData (uid: ryln8SHS9fg7cTE7sTdwS4dzmeH2, id: 6, summaryid: fXFhqH02zX8iv8THRVB1, customerFirstNametext: Testing, customerLastNametext: Testing,.....) это журнал перед вызовом 'json.decode(jsonString)' @AlexSunderSingh

Meet Bhanderi 15.07.2024 08:44

Как сказал @pskink, у вашего jsonString есть " в начале и конце, возможно, нам придется обрезать его из строки.

Alex Sunder Singh 15.07.2024 08:45

ваш jsonString начинается с " - он декодируется как String, а не Map - вы можете увидеть, как это работает, запустив: import 'dart:convert'; void main() { final d0 = jsonDecode('""'); final d1 = jsonDecode('{}'); final d2 = jsonDecode('"{}"'); print('d0 is String: ${d0 is String}'); print('d1 is Map: ${d1 is Map}'); print('d2 is Map: ${d2 is Map}'); print('d2 is String: ${d2 is String}'); } в dartpad.dev

pskink 15.07.2024 08:47

и, конечно, вам не следует исправлять это, удаляя начало и конец " (потому что вам также придется заменить каждый \" на "), а вместо этого пытаться выяснить, почему window.localStorage['RESUMEDATA'] содержит такие ошибочные данные - это ваша настоящая основная проблема

pskink 15.07.2024 09:12

Готово, я удалил косые черты и кавычки и передал их значения. Стал работать нормально. Спасибо за советы AlexSunderSingh и pskink изображение кода

Meet Bhanderi 15.07.2024 11:58

нет, это не то, как вам следует это делать, вместо этого вы должны убедиться, что ваши сохраненные данные представляют собой действительную строку json - я имею в виду, что window.localStorage['RESUMEDATA'] должен содержать действительную строку json

pskink 15.07.2024 12:21

Вы имеете в виду, проверьте, откуда в строке json берутся косые черты и кавычки? @pskink

Meet Bhanderi 16.07.2024 07:14

да, именно: вам следует исправить проблему как можно скорее, а не при анализе ваших данных, что, если вам нужно сделать это в другом месте - вы бы повторили свой код с replaceAll снова и снова?

pskink 16.07.2024 07:47
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
11
90
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

вы пытаетесь декодировать строку в Map<String, Dynamic>, но это не удается, поскольку строка может быть недопустимым JSON или декодируется неправильно попробуйте эту обработку ошибок.

    _onLoadResumeData(LoadResumeData event, Emitter<ResumeTemplatePreviewState> emit) async {emit(ResumeTemplatePreviewLoading());
  try {
    final jsonString = window.localStorage['RESUMEDATA'];
    if (jsonString == null || jsonString.isEmpty) {
      throw Exception('No resume data found in local storage');
    }
    // Log the jsonString for debugging
    print("Retrieved resume data JSON: $jsonString");
    // Decode jsonString into Map<String, dynamic>
    final Map<String, dynamic> resumeData = json.decode(jsonString);
    // Log decoded resume data for debugging
    print("Decoded resume data: $resumeData");
    emit(ResumeTemplatePreviewLoaded(resumeData));
  } catch (e) {
    print("Error loading resume data: $e");
    emit(ResumeTemplatePreviewError(e.toString()));
  }
}

Ошибка BlocBuilder: Ошибка: неожиданное нулевое значение в BlocBuilder<ResumeTemplatePreviewBloc, ResumeTemplatePreviewState>. Причина: Значение блока равно нулю. || Ошибка синтаксического анализа JSON: Ошибка: TypeError, указывающая, что строка не является подтипом Map<String, Dynamic>. Причина. Полученные данные JSON интерпретируются неправильно, возможно, из-за неправильного формата JSON или неправильной логики анализа.

Meet Bhanderi 15.07.2024 08:25
Ответ принят как подходящий

Ваш jsonString содержит " в начале и конце, поэтому, если вы уверены, что строка начинается и заканчивается ", вам нужно обрезать ее вручную.

try {
  String? jsonString = window.localStorage['RESUMEDATA'];
  if (jsonString == null || jsonString.isEmpty) {
    throw Exception('No resume data found in local storage');
  }
  if (jsonString.startsWith('"')){
     jsonString = jsonString.substring(1);
  }
  if (jsonString.endsWith('"')){
     jsonString = jsonString.substring(0, jsonString.length - 1);
  }
  jsonString = jsonString.replaceAll(r'\"', '"');

  final Map<String, dynamic> resumeData = json.decode(jsonString);
  log("Decoded resume data: $resumeData");

  emit(ResumeTemplatePreviewLoaded(resumeData));
} catch (e) {
  log(e.toString());
  emit(ResumeTemplatePreviewError(e.toString()));
}

Попробуйте использовать этот фрагмент в своем классе ResumeTemplatePreviewBloc

Другие вопросы по теме