Flutter报错:type 'String'不是Map<String, dynamic>子类型,求解决
Flutter解析XML转JSON时
type 'String' is not a subtype of type 'Map<String, dynamic>'错误解决方法 错误原因
- Model类型不匹配:你的Model类中,
fromJson方法多处用??""作为默认值,但当目标字段需要Map<String, dynamic>或List类型时,传入空字符串会直接触发类型转换错误。比如Rss.fromJson(json["rss"]??""),若json["rss"]不存在,会传入空字符串,而Rss.fromJson要求的是Map类型。 - 赋值顺序错误:API调用中,
counter在haberResult未赋值前就尝试获取其属性长度,不仅会导致空指针,还会影响后续UI渲染。
修正后的代码
1. 修正后的Model文件
// To parse this JSON data, do // // final economylistXml = economylistXmlFromJson(jsonString); import 'dart:convert'; EconomylistXml economylistXmlFromJson(String str) => EconomylistXml.fromJson(json.decode(str)); String economylistXmlToJson(EconomylistXml data) => json.encode(data.toJson()); class EconomylistXml { EconomylistXml({ required this.rss, }); Rss rss; factory EconomylistXml.fromJson(Map<String, dynamic> json) => EconomylistXml( rss: Rss.fromJson(json["rss"] ?? {}), ); Map<String, dynamic>? toJson() => { "rss": rss.toJson(), }; } class Rss { Rss({ required this.empty, required this.channel, }); Empty empty; Channel channel; factory Rss.fromJson(Map<String, dynamic> json) => Rss( empty: Empty.fromJson(json["\u0024"] ?? {}), channel: Channel.fromJson(json["channel"] ?? {}), ); Map<String, dynamic>? toJson() => { "\u0024": empty.toJson(), "channel": channel.toJson(), }; } class Channel { Channel({ required this.title, required this.link, required this.description, required this.language, required this.copyright, required this.image, required this.item, }); String? title; String? link; String? description; String? language; String? copyright; Image image; List<Item> item; factory Channel.fromJson(Map<String, dynamic> json) => Channel( title: json["title"] ?? "", link: json["link"] ?? "", description: json["description"] ?? "", language: json["language"] ?? "", copyright: json["copyright"] ?? "", image: Image.fromJson(json["image"] ?? {}), item: (json["item"] as List?)?.map((x) => Item.fromJson(x as Map<String, dynamic>)).toList() ?? [], ); Map<String, dynamic>? toJson() => { "title": title, "link": link, "description": description, "language": language, "copyright": copyright, "image": image.toJson(), "item": List<dynamic>.from(item.map((x) => x.toJson())), }; } class Image { Image({ required this.title, required this.url, required this.link, required this.width, required this.height, }); String? title; String? url; String? link; String? width; String? height; factory Image.fromJson(Map<String, dynamic> json) => Image( title: json["title"] ?? "", url: json["url"] ?? "", link: json["link"] ?? "", width: json["width"] ?? "", height: json["height"] ?? "", ); Map<String, dynamic>? toJson() => { "title": title, "url": url, "link": link, "width": width, "height": height, }; } class Item { Item({ required this.title, required this.description, required this.link, required this.pubDate, }); String? title; String? description; String? link; String? pubDate; factory Item.fromJson(Map<String, dynamic> json) => Item( title: json["title"] ?? "", description: json["description"] ?? "", link: json["link"] ?? "", pubDate: json["pubDate"] ?? "", ); Map<String, dynamic>? toJson() => { "title": title, "description": description, "link": link, "pubDate": pubDate, }; } class Empty { Empty({ required this.version, }); String? version; factory Empty.fromJson(Map<String, dynamic> json) => Empty( version: json["version"] ?? "", ); Map<String, dynamic>? toJson() => { "version": version, }; }
2. 修正后的API调用文件
import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import '../models/apis/economy_xml.dart'; import 'haberdetail.dart'; class Economy extends StatefulWidget { const Economy({Key? key}) : super(key: key); @override State<Economy> createState() => _EconomyState(); } class _EconomyState extends State<Economy> { ScrollController? controller; final scaffoldKey = GlobalKey<ScaffoldState>(); final url = Uri.parse('https://v1.nocodeapi.com/miktadtahir/xml_to_json/htvLvoPDCwIEyTxa?url=https://ekonomigundemi.com.tr/rss/ekonomi/246.xml'); int? counter; EconomylistXml? haberResult; Future callHaber() async { try{ final response = await http.get(url); if(response.statusCode == 200){ var rss = economylistXmlFromJson(response.body); if(mounted){ setState(() { haberResult = rss; counter = haberResult?.rss.channel.item.length; }); } return rss; } else { print(response.statusCode); } } catch(e) { print(e.toString()); } } @override void initState() { super.initState(); callHaber(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( centerTitle: false, automaticallyImplyLeading: false, title: const Text('Ekonomi Haberleri'), ), body: Center( child: Padding( padding: const EdgeInsets.all(8.0), child: counter != null ? ListView.builder( itemCount: counter!, itemBuilder: (context, index){ final item = haberResult?.rss.channel.item[index]; return Card( child: ListTile( title: Text(item?.title ?? ""), // 注意:description是文本内容,若要显示图片需解析其中的img标签提取链接 leading: CircleAvatar( backgroundImage: NetworkImage(item?.description ?? ""), ), onTap: () => Navigator.push( context, MaterialPageRoute( builder: (context) => HaberDetailScreen( subtitle: item?.title ?? "", title: item?.description ?? "" ) ) ), ), ); }) : const Center(child: CircularProgressIndicator()), ), ), ); } }
关键修正点
- Model类型适配:
- 需要
Map类型的字段,默认值从""改为{},确保传入类型匹配 - 列表字段改用安全转换逻辑,避免空值或非列表类型导致的错误
- 需要
- API调用逻辑修复:
- 调整
counter赋值顺序,先给haberResult赋值再获取列表长度 - 修复
if(mounted);的语法错误,避免不必要的状态更新 - 给
counter指定明确的int?类型,消除类型歧义
- 调整
内容的提问来源于stack exchange,提问作者Mıktad Tahir Durak
相关产品推荐
相关产品推荐

