init
This commit is contained in:
commit
d205277cdd
182 changed files with 22978 additions and 0 deletions
59
lib/subsonic/json_helpers.dart
Normal file
59
lib/subsonic/json_helpers.dart
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/// Defensive JSON helpers for the Subsonic protocol.
|
||||
///
|
||||
/// Subsonic servers are inconsistent (Ratune handles the same quirks in
|
||||
/// `ratune-subsonic/src/models.rs` via `OneOrMany` / `deserialize_flexible_id`):
|
||||
/// * a field that is sometimes a single object and sometimes an array
|
||||
/// * IDs that are sometimes strings and sometimes integers
|
||||
/// Every accessor below tolerates nulls and mixed types rather than throwing.
|
||||
library;
|
||||
|
||||
/// Coerce a value that may be a single object, a list, or null into a list of
|
||||
/// `T`, applying [fromJson] to each map element.
|
||||
List<T> oneOrMany<T>(
|
||||
dynamic value,
|
||||
T Function(Map<String, dynamic>) fromJson,
|
||||
) {
|
||||
if (value == null) return const [];
|
||||
if (value is List) {
|
||||
return value
|
||||
.whereType<Map>()
|
||||
.map((e) => fromJson(e.cast<String, dynamic>()))
|
||||
.toList();
|
||||
}
|
||||
if (value is Map) {
|
||||
return [fromJson(value.cast<String, dynamic>())];
|
||||
}
|
||||
return const [];
|
||||
}
|
||||
|
||||
/// Read a string that the server might encode as an int (e.g. IDs).
|
||||
String? asString(dynamic value) {
|
||||
if (value == null) return null;
|
||||
if (value is String) return value;
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
/// Read an int from a value that might be an int, num, or numeric string.
|
||||
int? asInt(dynamic value) {
|
||||
if (value == null) return null;
|
||||
if (value is int) return value;
|
||||
if (value is num) return value.toInt();
|
||||
if (value is String) return int.tryParse(value);
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Read a double from an int/num/numeric-string.
|
||||
double? asDouble(dynamic value) {
|
||||
if (value == null) return null;
|
||||
if (value is double) return value;
|
||||
if (value is num) return value.toDouble();
|
||||
if (value is String) return double.tryParse(value);
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Read a bool that might arrive as a bool or the string "true"/"false".
|
||||
bool asBool(dynamic value, {bool orElse = false}) {
|
||||
if (value is bool) return value;
|
||||
if (value is String) return value.toLowerCase() == 'true';
|
||||
return orElse;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue