flutter中的json转对象

本文介绍了一种在Flutter中将JSON数据转换为实体类的方法,避免了使用在线工具和插件带来的不便。通过解析JSON内容并自动生成实体类代码,提高了开发效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

网上有好多json转对象的方法:
在线生成的:https://javiercbk.github.io/json_to_dart/
弊端:每次都要打开网页去生成,尤其是公司网不好的时候,急死;

插件生成的:插件名:FlutterJsonBeanFactory
弊端:不知道没弄明白还是根本没法设置,我只想要一个简单的文件,不要什么继承.
因为子类型总是重复生成.

以下我自己解析json内容生成对象[优化后]

只涉及到自己用到的类型,如有其他,读者可随时更改

import 'dart:convert';
import 'dart:io';

import 'package:flutter_test/flutter_test.dart';

void main() {
   test('生成实体数据', () async {
    Future<void> write(String fileName, String content) async {
      File indexFile = File(fileName);
      if (!await indexFile.exists()) {
        indexFile.createSync();
      } else {
        print("重写:$indexFile");
      }
      IOSink out = indexFile.openWrite();
      out.write(content);
    }

    String jsonFile = "models.json"; // json文件
    String jsonData = await File(jsonFile).readAsString();
    Map<String, dynamic> entities = convert.json.decode(jsonData);

    String filePath = entities.remove('path') ?? "lib/model"; // 生成目录,不带/后缀
    String libraryName = entities.remove('library') ?? "xgcs_model"; // 模块名称
    String entitySuffix = entities.remove('suffix') ?? "Entity"; // 实体后缀

    File libraryFile = File("$filePath/index.dart");
    await libraryFile.parent.create();

    Map<String, String> keyClassNameMap = {};
    for (String fileName in entities.keys) {
      Map<String, dynamic> data = entities[fileName];

      String className = fileName.substring(0, 1).toUpperCase() + fileName.substring(1) + entitySuffix;
      keyClassNameMap[fileName] = className;

      // 字段名
      List<String> fieldNames = [];
      // 字段对应索引类型名:String,int,type等
      Map<String, String> typeNames = {};
      // 泛型类型
      Map<String, String> itemTypeNames = {};
      for (var fieldName in data.keys) {
        var fieldValue = data[fieldName];
        var fieldType = fieldValue.runtimeType.toString();
        if (fieldValue is String) {
          if (keyClassNameMap.containsKey(fieldValue)) {
            // 引用已定义类型
            fieldType = keyClassNameMap[fieldValue]!;
          }
        } else if (fieldValue is List) {
          // 泛型类型
          var itemType = fieldValue[0];
          if (itemType is String && keyClassNameMap.containsKey(itemType)) {
            // 泛型集合
            itemType = keyClassNameMap[itemType];
            itemTypeNames[fieldName] = itemType;
          } else {
            itemType = itemType.runtimeType.toString();
          }
          fieldType = 'List<$itemType>';
        } else if (fieldValue is Map) {
          var mapKeyType = fieldValue.keys.first.runtimeType.toString();
          var mapValueType = fieldValue.values.first.runtimeType.toString();
          fieldType = 'Map<$mapKeyType,$mapValueType>';
        }
        fieldNames.add(fieldName);
        typeNames[fieldName] = fieldType;
      }
      String attributesContent = fieldNames.map((field) => "${typeNames[field]}? $field").join(";\n  ");
      String constructorContent = fieldNames.map((field) => 'this.$field').join(",\n    ");
      String copyWithContent = fieldNames.map((field) => "${typeNames[field]}? $field").join(",\n    ");
      String copyWithContentContent = fieldNames.map((field) => "$field: $field ?? this.$field").join(",\n      ");
      String forJsonContent = fieldNames.map((field) {
        var typeName = typeNames[field];
        if (typeName!.startsWith("List") && itemTypeNames.containsKey(field)) {
          var itemType = itemTypeNames[field];
          return "$field = ((json['$field'] ?? []) as List).map((_) => $itemType.forJson(_)).toList()";
        }
        if (keyClassNameMap.containsKey(field)) {
          return "$field = $typeName.forJson(json['$field'])";
        }
        return "$field = json['$field']";
      }).join(";\n    ");
      String toJsonContent = fieldNames.map((field) {
        var typeName = typeNames[field];
        if (typeName!.startsWith("List") && itemTypeNames.containsKey(field)) {
          return "data['$field'] = ($field ?? []).map((_) => _.toJson()).toList()";
        }
        if (keyClassNameMap.containsKey(field)) {
          return "data['$field'] = $field?.toJson()";
        }
        return "data['$field'] = $field";
      }).join(";\n    ");
      // class内容
      String classContent = """
part of $libraryName;

class $className {
  $attributesContent;

  $className({
    $constructorContent,
  });

  $className copyWith({
    $copyWithContent,
  }) {
    return $className(
      $copyWithContentContent,
    );
  }

  $className.forJson(Map<String, dynamic> json) {
    $forJsonContent;
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = {};
    $toJsonContent;
    return data;
  }
}
""";
      await write("$filePath/$fileName.dart", classContent);
    }
    await write("$filePath/index.dart", "library $libraryName;\n\n${entities.keys.map((_) => 'part \'$_.dart\'').join(';\n\n')};\n\npart 'extension.dart';");
  });
}

json格式如下[属性名不要与文件名冲突,bug为解决]

{
"library": "xgcs_model",
  "path": "lib/model",
  "suffix": "Entity",
  "user": {
    "id": "用户id-uuid",
    "username": "登录名一般为手机号",
    "nickname": "昵称",
    "phone": "绑定的手机号",
    "birthday": 1234567,
    "weiXinId": "绑定微信",
    "aliPayId": "绑定支付宝",
    "guide": false,
    "settings": {
      "String": "dynamic"
    }
  }
}

备注说明

1.原代码已删除,这个版本是优化后的.

<think>好的,用户想了解在Flutter中如何将JSON字符串换为Map对象。我需要先回想一下相关的知识点,确保信息准确。首先,Dart语言本身有内置的JSON解码支持,主要是通过dart:convert库中的json.decode方法。不过,用户可能刚接触Flutter,可能需要分步骤讲解。 接下来,我应该考虑用户可能的场景。比如,他们可能从网络请求获取了JSON数据,或者读取本地存储的JSON文件,需要解析成Map以便在应用中使用。用户可能没有提到具体使用场景,但常见的情况都需要用到这个方法。 然后,需要确认是否需要引入其他依赖。dart:convert是内置的,所以不需要额外添加包。但可能需要提醒用户处理异常,比如JSON格式不正确的情况。用户可能不知道如何处理解析错误,所以给出try-catch的例子会更好。 另外,用户可能分不清Map和自定义模型类的区别,是否需要提到使用json_serializable或类似库进行模型换?不过问题明确是Map对象,所以暂时不需要深入这部分,但或许可以简要提及后续步骤,比如换成模型类,作为扩展知识。 然后,结构上应该先展示基本用法,再给出示例代码,说明步骤。例如,先导入库,然后使用json.decode,处理异常,最后使用解析后的Map。同时提醒注意事项,比如JSON格式必须正确,否则会抛出异常。 可能还需要提到JSON的结构,比如如果顶层是对象,解析成Map;如果是数组,解析成List。用户可能对这点不太清楚,需要明确说明。 最后,检查是否有常见的错误或误区,比如忘记导入dart:convert,或者没有处理异常导致应用崩溃。确保示例代码准确,可以复制使用,比如完整的代码片段,包括main函数和打印结果。 总结下来,回答的结构应该是:先说明使用的方法和库,分步骤讲解,提供示例代码,处理异常,注意事项,可能的结构类型,以及扩展建议。这样用户能清晰理解并正确应用。</think>在 Flutter 中实现 JSON 字符串 Map 对象的标准做法是通过 `dart:convert` 库实现,以下是具体实现步骤和注意事项: ```dart import 'dart:convert'; // 必须导入换库 void main() { // 示例 JSON 字符串 String jsonString = '{"name": "张三", "age": 25, "isStudent": true}'; try { // 核心换方法 Map<String, dynamic> dataMap = jsonDecode(jsonString); // 使用解析后的 Map print(dataMap["name"]); // 输出:张三 print(dataMap["age"]); // 输出:25 print(dataMap["isStudent"]);// 输出:true } catch (e) { print("JSON 解析错误: $e"); } } ``` #### 关键要点说明: 1. **数据类型映射**: - JSON 对象 → `Map<String, dynamic>` - JSON 数组 → `List<dynamic>` - 嵌套结构会自动递归换 2. **异常处理**: 必须使用 try-catch 捕获以下异常: - `FormatException`:当 JSON 格式不合法时抛出 - `TypeError`:当类型换失败时抛出 3. **格式要求**: - JSON 字符串必须使用**双引号** - 键名必须用双引号包裹 - 不支持尾随逗号 - 布尔值必须小写(true/false) 4. **性能建议**: - 大型 JSON(超过 1MB)建议在隔离线程中解析 - 高频解析场景建议使用 `jsonDecode` 的 `reviver` 参数进行优化 #### 扩展场景: 当需要换为类型安全的模型对象时,推荐组合使用: ```dart // 1. 先换为 Map Map<String, dynamic> map = jsonDecode(jsonString); // 2. 再换为模型对象 User user = User.fromJson(map); ``` 可使用 [json_serializable](https://pub.dev/packages/json_serializable) 自动生成序列化代码,提高开发效率和类型安全性。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值