如何手动过滤JSON中的Store数组并生成安全的Store实例列表?
解决方案
完全可以用where + map的方式实现需求,核心是先做好空值安全处理,避免空指针异常,再完成过滤和映射逻辑。以下是具体实现方案:
步骤说明
- 安全获取stores数组:先从API响应中取出
stores,如果字段不存在或为null,直接用空数组兜底。 - 过滤目标项:筛选出
sells_drugs明确为false的店铺(需处理该字段可能为null的情况)。 - 映射为Store实例:从每个店铺的
profile数组中找到lang为en的项,提取title作为店铺名称;如果找不到对应语言的profile,给默认名称兜底。
完整代码示例
假设你的API响应是Map<String, dynamic>类型,处理逻辑如下:
// 假设这是你的Store类 class Store { final String id; final String name; Store({required this.id, required this.name}); } // 处理API响应的逻辑 void processLoginResponse(Map<String, dynamic> response) { // 1. 安全获取stores数组,不存在则返回空数组 final List<dynamic> storesJson = (response['stores'] as List<dynamic>?) ?? []; // 2. 过滤+映射成Store列表 List<Store> filteredStores = storesJson .where((store) { // 确保sells_drugs存在且为false,避免字段缺失导致错误 final sellsDrugs = store['sells_drugs'] as bool?; return sellsDrugs == false; }) .map((store) { // 安全获取profile数组 final List<dynamic> profiles = (store['profile'] as List<dynamic>?) ?? []; // 找到lang为en的profile,找不到则用默认值 final enProfile = profiles.firstWhere( (profile) => profile['lang'] == 'en', orElse: () => {'title': 'Unnamed Store'}, ); // 提取名称,兜底默认值 final storeName = enProfile['title'] as String? ?? 'Unnamed Store'; // 提取ID,根据实际接口返回类型调整(这里假设是String) final storeId = store['id'] as String? ?? ''; return Store(id: storeId, name: storeName); }) .toList(); // 后续使用filteredStores即可 }
关键细节说明
- 空值兜底:全程使用
??操作符处理可能为null的字段,确保即使接口返回异常数据(比如stores缺失、profile为空),程序也不会崩溃。 - 过滤条件修正:你原本的
where((u)=>u.sells_drugs)会筛选出sells_drugs为true的项,需要改为sellsDrugs == false才能符合需求。 - profile处理:用
firstWhere+orElse确保找不到英文profile时,依然能生成合法的Store实例,避免遍历失败抛出异常。
内容的提问来源于stack exchange,提问作者Dimitrios Desyllas
相关产品推荐
相关产品推荐

