83 lines
3.0 KiB
Dart
83 lines
3.0 KiB
Dart
/// Parse a value that may be [int], [num], or [String] to [int].
|
|
/// Used as `@JsonKey(fromJson: flexibleInt)` and in manual `fromJson` factories
|
|
/// to handle Plex API responses where numeric fields may arrive as strings
|
|
/// (XML-to-JSON conversion).
|
|
int? flexibleInt(Object? v) => switch (v) {
|
|
final num n => n.toInt(),
|
|
final String s => int.tryParse(s),
|
|
_ => null,
|
|
};
|
|
|
|
/// Parse a value that may be [bool], [int] (0/1), or [String] ('1') to [bool].
|
|
/// Returns `false` for `null` or unrecognised values.
|
|
/// Handles Plex API responses where boolean fields may arrive as integers.
|
|
bool flexibleBool(Object? v) => switch (v) {
|
|
final bool b => b,
|
|
final int n => n == 1,
|
|
final String s => s == '1',
|
|
_ => false,
|
|
};
|
|
|
|
/// Parse a value that may be [bool], [int] (0/1), or [String] ('1') to [bool].
|
|
/// Returns `null` for `null` or unrecognised values.
|
|
bool? flexibleBoolNullable(Object? v) => switch (v) {
|
|
final bool b => b,
|
|
final int n => n == 1,
|
|
final String s => s == '1',
|
|
_ => null,
|
|
};
|
|
|
|
/// Parse a value that may be [double], [num], or [String] to [double].
|
|
double? flexibleDouble(Object? v) => switch (v) {
|
|
final num n => n.toDouble(),
|
|
final String s => double.tryParse(s),
|
|
_ => null,
|
|
};
|
|
|
|
/// `@JsonKey(readValue:)` adapter — coerces the named field to a String via
|
|
/// `toString()` before the generated cast. Use for required `String` fields
|
|
/// that Plex may return as int in some endpoints.
|
|
Object? readStringField(Map json, String key) => json[key]?.toString();
|
|
|
|
/// Coerce a value that may be a single Map or a List of Maps into a `List<dynamic>`.
|
|
/// Plex often returns `{"Part": {...}}` for single-part media and
|
|
/// `{"Part": [{...}, {...}]}` for multi-part — this normalises both shapes.
|
|
/// Returns `null` when the value is `null`.
|
|
List<dynamic>? flexibleList(Object? v) => switch (v) {
|
|
null => null,
|
|
final List l => l,
|
|
_ => <dynamic>[v],
|
|
};
|
|
|
|
/// Coerce a single String, a List of Strings, or null into `List<String>?`.
|
|
/// Non-string elements are dropped; an empty result (or null input) yields
|
|
/// `null`. Typed sibling of [flexibleList] — a bare String is wrapped into a
|
|
/// single-element list, so callers tolerate both single-value and list shapes.
|
|
List<String>? flexibleStringList(Object? v) {
|
|
final list = flexibleList(v);
|
|
if (list == null) return null;
|
|
final result = [
|
|
for (final e in list)
|
|
if (e is String) e,
|
|
];
|
|
return result.isEmpty ? null : result;
|
|
}
|
|
|
|
List<String>? stringListFromRaw(Object? raw, {String? mapKey, bool stringify = false, bool nullIfEmpty = false}) {
|
|
if (raw is! List) return null;
|
|
final result = <String>[];
|
|
for (final value in raw) {
|
|
final source = mapKey != null && value is Map ? value[mapKey] : value;
|
|
final string = stringify
|
|
? source?.toString()
|
|
: source is String
|
|
? source
|
|
: null;
|
|
if (string != null) result.add(string);
|
|
}
|
|
if (result.isEmpty && nullIfEmpty) return null;
|
|
return result;
|
|
}
|
|
|
|
List<T>? nullIfEmptyList<T>(List<T> values) => values.isEmpty ? null : values;
|