FlutterIM项目_Part5_safeutil空安全工具类

17 阅读2分钟

麻烦

拿到一个可能为空且类型不确定的res, 希望它安全转换成bool值,通常需要这么做。 res as? bool ?? false

SafeUtil工具类

工具类直接 res.toSafeBool();

import 'dart:convert';

class SafeUtil {
  static Map<String, dynamic> safeMap(dynamic input) {
    if (input == null) {
      return {};
    }

    if (input is Map<String, dynamic>) {
      return input;
    } else if (input is String) {
      // 如果是字符串,尝试解析为 JSON 对象(Map)
      try {
        final decoded = jsonDecode(input);
        if (decoded is Map<String, dynamic>) {
          return decoded;
        }
      } catch (_) {
        return {};
      }
    } else if (input is Map) {
      // 如果是 Map 但不是 Map<String, dynamic>,尝试转换
      Map<String, dynamic> result = {};
      input.forEach((key, value) {
        result[key.toString()] = value;
      });
      return result;
    } else {
      // 其他类型
      return {};
    }
    return {};
  }

  static String safeString(dynamic input) {
    if (input == null) {
      return '';
    }

    if (input is String) {
      return input;
    } else {
      return input.toString();
    }
  }

  static bool safeBool(dynamic input) {
    if (input == null) {
      return false;
    }

    if (input is bool) {
      return input;
    }

    var strInput = input.toString().toLowerCase();
    if (strInput == 'true' || strInput == '1') {
      return true;
    } else if (strInput == 'false' || strInput == '0') {
      return false;
    }

    return false;
  }

  static List<dynamic> safeList(dynamic input) {
    if (input == null) {
      return [];
    }

    if (input is List<dynamic>) {
      return input;
    } else if (input is String) {
      // 如果是字符串,尝试解析为 JSON 数组
      try {
        final decoded = jsonDecode(input);
        if (decoded is List<dynamic>) {
          return decoded;
        }
      } catch (_) {
        return [];
      }
    } else if (input is Iterable) {
      // 如果是可迭代对象,但不是 List<dynamic>,尝试转换
      return List.from(input);
    } else {
      // 其他类型
      return [input]; // 将单个元素包装成列表
    }
    return [];
  }

  static int safeInt(dynamic input, [int defaultValue = 0]) {
    if (input == null) {
      return defaultValue;
    }

    if (input is int) {
      return input;
    } else if (input is String) {
      // 如果是字符串,尝试解析为整数
      final parsedInt = int.tryParse(input);
      return (parsedInt != null) ? parsedInt : defaultValue;
    } else if (input is double) {
      // 如果是浮点数,尝试转换为整数
      return input.toInt();
    } else {
      // 尝试调用输入对象的toString方法并解析为整数
      final parsedInt = int.tryParse(input.toString());
      return (parsedInt != null) ? parsedInt : defaultValue;
    }
  }

  static double safeDouble(dynamic input, [double defaultValue = 0.0]) {
    if (input == null) {
      return defaultValue;
    }

    if (input is double) {
      return input;
    } else if (input is int) {
      // 如果是整数,直接转换为浮点数
      return input.toDouble();
    } else if (input is String) {
      // 如果是字符串,尝试解析为浮点数
      final parsedDouble = double.tryParse(input);
      return (parsedDouble != null) ? parsedDouble : defaultValue;
    } else {
      // 尝试调用输入对象的toString方法并解析为浮点数
      final parsedDouble = double.tryParse(input.toString());
      return (parsedDouble != null) ? parsedDouble : defaultValue;
    }
  }
}

//每次使用都SafeUtil.safeBool(res) 这样太麻烦了,提供extension, 简化成res.toSafeBool()
extension SafeExtensions on dynamic {
  Map<String, dynamic> toSafeMap() => SafeUtil.safeMap(this);

  String toSafeString() => SafeUtil.safeString(this);

  bool toSafeBool() => SafeUtil.safeBool(this);

  List<dynamic> toSafeList() => SafeUtil.safeList(this);

  int toSafeInt([int defaultValue = 0]) => SafeUtil.safeInt(this, defaultValue);

  double toSafeDouble([double defaultValue = 0.0]) =>
      SafeUtil.safeDouble(this, defaultValue);
}