prefer-correct-json-casts

Path
lint/correctness/prefer-correct-json-casts
Default
Off, opt in
Origin
Falcon
Rule
340 of 512

Decode JSON containers using their actual runtime generic types.

Instead of jsonDecode(text) as List<int>, use (jsonDecode(text) as List<Object?>).cast<int>(). For maps, first use Map<String, Object?>, then .cast<String, Value>().

Tracks canonical SDK jsonDecode/json.decode calls without a reviver, direct no-reviver JsonDecoder().convert calls, immutable local aliases, casts, and indexing into those decoded values. Cast patterns in conditionals, switch cases/expressions, and pattern declarations are checked. Arbitrary dynamic values, unresolved generic arguments, parameters merely named json, mutable aliases, custom decoders, and values returned from collection conversions are not assumed to be decoded JSON.

Reference: https://dcm.dev/docs/rules/common/prefer-correct-json-casts/

Invalid

example.dartdart
import 'dart:convert';
import 'dart:convert' as convert;

void decode(String text) {
  final numbers = jsonDecode(text) as List<int>;
  final mapping = convert.jsonDecode(text) as Map<String, int>;
  final json = jsonDecode(text) as Map<String, Object?>;
  final items = json['items'] as List<String>;
  final alias = json;
  final nested = alias['nested'] as Map<String, List<int>>;
  final wrongKeys = jsonDecode(text) as Map<int, dynamic>;
  if (json['items'] case Object() as List<int>) {}
}
Cast JSON to `List<Object?>` or `Map<String, Object?>` first, then use `cast()` to check its contents.
4void decode(String text) {
5 final numbers = jsonDecode(text) as List<int>;
Cast JSON to `List<Object?>` or `Map<String, Object?>` first, then use `cast()` to check its contents.
5 final numbers = jsonDecode(text) as List<int>;
6 final mapping = convert.jsonDecode(text) as Map<String, int>;
Cast JSON to `List<Object?>` or `Map<String, Object?>` first, then use `cast()` to check its contents.
7 final json = jsonDecode(text) as Map<String, Object?>;
8 final items = json['items'] as List<String>;
Cast JSON to `List<Object?>` or `Map<String, Object?>` first, then use `cast()` to check its contents.
9 final alias = json;
10 final nested = alias['nested'] as Map<String, List<int>>;
Cast JSON to `List<Object?>` or `Map<String, Object?>` first, then use `cast()` to check its contents.
10 final nested = alias['nested'] as Map<String, List<int>>;
11 final wrongKeys = jsonDecode(text) as Map<int, dynamic>;
Cast JSON to `List<Object?>` or `Map<String, Object?>` first, then use `cast()` to check its contents.
11 final wrongKeys = jsonDecode(text) as Map<int, dynamic>;
12 if (json['items'] case Object() as List<int>) {}

Valid

example.dartdart
import 'dart:convert';

void decode(String text, dynamic unrelated) {
  final json = jsonDecode(text) as Map<String, Object?>;
  final items = (json['items'] as List<Object?>).cast<int>().toList();
  final map = (json['map'] as Map<String, dynamic>).cast<String, int>();
  final list = jsonDecode(text) as List<dynamic>;
  final raw = jsonDecode(text) as Map;
  final scalar = json['count'] as int;
  final nonJson = unrelated as List<int>;
  final converted = items as List<int>;
  {
    final json = <String, dynamic>{'items': <int>[1]};
    final typed = json['items'] as List<int>;
  }
  final revived = jsonDecode(text, reviver: (key, value) => value) as List<int>;
}

Configure prefer-correct-json-casts

Set its severity in falcon.json. See the configuration guide.

falcon.jsonjson
{
  "linter": {
    "rules": {
      "correctness": {
        "prefer-correct-json-casts": "error"
      }
    }
  }
}

Or silence one occurrence with a suppression comment; the reason is required.

example.dartdart
// falcon-ignore lint/correctness/prefer-correct-json-casts: <reason>