castAttribute method

dynamic castAttribute(
  1. String key,
  2. dynamic value
)

Cast an attribute to its declared Dart type.

Implementation

dynamic castAttribute(String key, dynamic value) {
  if (value == null) return null;

  final castType = casts[key];

  // Custom AttributeCaster instances take priority.
  if (castType is AttributeCaster) return castType.get(value);

  // Non-generic types: use fast identity comparisons.
  if (castType == int) {
    if (value is int) return value;
    if (value is double) return value.toInt();
    if (value is bool) return value ? 1 : 0;
    return int.tryParse(value.toString());
  }
  if (castType == double) {
    if (value is double) return value;
    if (value is int) return value.toDouble();
    return double.tryParse(value.toString());
  }
  if (castType == String) {
    if (value is String) return value;
    return value.toString();
  }
  if (castType == bool) {
    if (value is bool) return value;
    if (value is int) return value != 0;
    final s = value.toString().toLowerCase();
    return s == 'true' || s == '1';
  }
  if (castType == DateTime) {
    if (value is DateTime) return value;
    return DateTime.tryParse(value.toString());
  }

  // Generic types: Dart's `==` operator can't parse `castType == List<X>`
  // directly (ambiguous with `<`), so use const-pattern switch.
  switch (castType) {
    case const (List<String>):
      if (value is List<String>) return value;
      if (value is List) return value.map((e) => e.toString()).toList();
      if (value is String) {
        try {
          final decoded = jsonDecode(value);
          if (decoded is List) {
            return decoded.map((e) => e.toString()).toList();
          }
        } catch (_) {}
      }
      return <String>[];

    case const (List<dynamic>):
      if (value is List) return value;
      if (value is String) {
        try {
          return jsonDecode(value) as List;
        } catch (_) {}
      }
      return <dynamic>[];

    case const (Map<String, dynamic>):
    case const (Map):
      if (value is Map<String, dynamic>) return value;
      if (value is Map) return Map<String, dynamic>.from(value);
      if (value is String) {
        try {
          final decoded = jsonDecode(value);
          if (decoded is Map) return Map<String, dynamic>.from(decoded);
        } catch (_) {}
      }
      return <String, dynamic>{};

    default:
      return value;
  }
}