Flutter解析NewsAPI数据时出现_TypeError空类型不匹配错误求助
问题原因
- NewsAPI返回的新闻数据中
author、title、url、content等字段均可能返回null,但你的ArticleModel中所有属性都定义为不可空的String类型,构造函数也设置为required,只要任意字段为null就会触发类型不匹配错误。 - 你当前仅对
urlToImage和description做了非空过滤,未处理其他字段的空值场景,刚好遇到返回author为null的新闻数据就触发了报错。 - 额外问题:解析
content字段时你错误使用了element["context"]作为key,NewsAPI返回的内容字段为content,写错key也会导致该字段永远为null。
解决方案
方案1:空值兜底(推荐,无需额外处理渲染逻辑)
修改ArticleModel新增工厂解析方法,遇到空值时自动替换为默认值:
class ArticleModel { String author; String title; String description; String url; String urlToImage; String content; ArticleModel({ required this.author, required this.title, required this.description, required this.url, required this.urlToImage, required this.content, }); factory ArticleModel.fromJson(Map<String, dynamic> json) { return ArticleModel( author: json['author'] ?? '匿名作者', title: json['title'] ?? '无标题', description: json['description'] ?? '无内容摘要', url: json['url'] ?? '', urlToImage: json['urlToImage'] ?? '', content: json['content'] ?? '无全文内容', ); } }
修改数据拉取类的解析逻辑,调用工厂方法解析:
import 'dart:convert'; import 'package:newspaper/models/article.dart'; import 'package:http/http.dart' as http; class News { List<ArticleModel> news = []; Future<void> getNews() async { var url = Uri.parse( "https://newsapi.org/v2/top-headlines?country=in&category=business&apiKey=5c2be84a9b8548ab8dde4cfa1eaa1023"); var response = await http.get(url); var jsonData = jsonDecode(response.body); if (jsonData['status'] == "ok") { jsonData["articles"].forEach((element) { if (element["urlToImage"] != null && element['description'] != null) { ArticleModel articleModel = ArticleModel.fromJson(element); news.add(articleModel); } }); } } }
方案2:可空类型适配
如果允许字段为空,可将模型类属性改为可空类型:
class ArticleModel { String? author; String? title; String? description; String? url; String? urlToImage; String? content; ArticleModel({ this.author, this.title, this.description, this.url, this.urlToImage, this.content, }); }
使用该方案需要在页面渲染时对可空字段做空判断,例如:
class BlogTile extends StatelessWidget { final String? imageUrl, title, desc; const BlogTile( {required this.imageUrl, required this.title, required this.desc}); @override Widget build(BuildContext context) { return Container( child: Column( children: [ Image.network(imageUrl ?? '默认占位图地址'), Text(title ?? '无标题'), Text(desc ?? '无描述'), ], ), ); } }
内容的提问来源于stack exchange,提问作者19TUCS009 ARUN.V
相关产品推荐
相关产品推荐

