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}');
}