parseJson static method

IntentParseResult parseJson(
  1. Object? json
)

Reads a decoded JSON value leniently: keys and words are matched case-insensitively (ignoring spaces, - and _), a few synonyms are accepted, single values stand in for lists, and everything unusable is dropped and listed. Never throws.

Implementation

static IntentParseResult parseJson(Object? json) {
  final dropped = <String>[];
  if (json is! Map) {
    if (json != null) dropped.add('not a JSON object');
    return IntentParseResult(ThemeIntent.none, List.unmodifiable(dropped));
  }
  final families = <ThemeFamily>[];
  ThemeBrightness? brightness;
  final colors = <IntentColor>[];
  IntentChroma? chroma;
  HarmonyScheme? harmony;
  (int, int)? hueRange;
  String? name;

  for (final entry in json.entries) {
    final key = entry.key is String ? _norm(entry.key as String) : '';
    final value = entry.value;
    switch (key) {
      case 'families' || 'family' || 'style' || 'styles':
        for (final v in _list(value)) {
          final f = _family(v);
          if (f == null) {
            dropped.add('families: $v');
          } else {
            families.add(f);
          }
        }
      case 'brightness' || 'mode' || 'tone':
        final w = value is String ? _norm(value) : null;
        switch (w) {
          case 'light' || 'bright' || 'day':
            brightness = ThemeBrightness.light;
          case 'dark' || 'night':
            brightness = ThemeBrightness.dark;
          case 'any' || 'either' || 'auto' || 'none':
            brightness = null;
          default:
            dropped.add('brightness: $value');
        }
      case 'colors' || 'colours' || 'color' || 'colour' || 'palette':
        for (final v in _list(value, splitText: true)) {
          final c = _color(v);
          if (c == null) {
            dropped.add('colors: $v');
          } else {
            colors.add(c);
          }
        }
      case 'chroma' || 'saturation' || 'intensity' || 'vibrancy':
        final c = value is String ? _chroma(_norm(value)) : null;
        if (c == null) {
          dropped.add('chroma: $value');
        } else {
          chroma = c;
        }
      case 'harmony' || 'scheme':
        final h = value is String ? _harmony(_norm(value)) : null;
        if (h == null) {
          dropped.add('harmony: $value');
        } else {
          harmony = h;
        }
      case 'huerange' || 'hue':
        final r = _hueRange(value);
        if (r == null) {
          dropped.add('hueRange: $value');
        } else {
          hueRange = r;
        }
      case 'name' || 'title':
        final n = value is String ? _cleanName(value) : null;
        if (n == null) {
          dropped.add('name: $value');
        } else {
          name = n;
        }
      default:
        dropped.add('unknown key ${entry.key}');
    }
  }
  final distinctColors = _distinct(colors);
  for (final c in distinctColors.skip(maxColors)) {
    dropped.add('colors: ${c.word} (more than $maxColors)');
  }
  return IntentParseResult(
    ThemeIntent(
      families: families,
      brightness: brightness,
      colors: distinctColors,
      chroma: chroma,
      harmony: harmony,
      hueRange: hueRange,
      name: name,
    ),
    List.unmodifiable(dropped),
  );
}