estimateJsonFieldValueType function Null safety

ValueType estimateJsonFieldValueType(
  1. String? key,
  2. Object? value
)

Implementation

ValueType estimateJsonFieldValueType(
  String? key,
  Object? value,
) {
  if (key != null) {
    final keyValueType = estimateJsonFieldValueType(null, key);
    if (keyValueType is StringValueType) {
      if (likelyTimestampKey(key)) {
        final timestampValueType = estimateTimestampValueType(value);
        if (timestampValueType != null) {
          return timestampValueType;
        }
      }
    }
  }

  if (value == null) {
    return const UnknownValueType(optional: true);
  } else if (value is String) {
    if (likelyPandoraId(value)) {
      return const PandoraIdValueType(optional: false);
    } else if (likelyPandoraType(value)) {
      return const PandoraTypeValueType(optional: false);
    }
    return const StringValueType(optional: false);
  } else if (value is num) {
    if (value is int) {
      return const IntegerValueType(optional: false);
    } else if (value is double) {
      return const DoubleValueType(optional: false);
    }
    return const NumberValueType(optional: false);
  } else if (value is bool) {
    return const BooleanValueType(optional: false);
  } else if (value is List) {
    return TypedListValueType(
      estimateValueTypes(value),
      optional: false,
    );
  } else if (value is Map<String, dynamic>) {
    if (value.isEmpty) {
      // If the map is empty, it's more likely to be an empty JSON map than a
      // JSON object with no fields, so treat it as such.
      return const TypedJsonMapValueType(
        keyValueType: StringValueType(optional: false),
        valueValueType: UnknownValueType(optional: true),
        optional: false,
      );
    }

    // Determine whether the non-empty map is a (specialised) JSON map or not.
    final keyValueType =
        estimateValueTypes(value.keys) as ValueType<String, dynamic>;
    if (key != null && likelyAnnotationMap(key, keyValueType)) {
      return AnnotationMapValueType(optional: false);
    } else if (keyValueType != const StringValueType(optional: false)) {
      // If the JSON object key types aren't standard strings
      // (e.g. [PandoraIdValueType]s), treat the object like a map.
      final valueValueType = estimateValueTypes(value.values);
      return TypedJsonMapValueType(
        keyValueType: keyValueType,
        valueValueType: valueValueType,
        optional: false,
      );
    }

    return estimateJsonObjectValueType(value);
  }

  throw UnsupportedError('Unsupported JSON value type: ${value.runtimeType}');
}