221faa9c97
CI and Release / format (push) Successful in 34s
CI and Release / analyze (push) Successful in 26s
CI and Release / test (push) Successful in 48s
CI and Release / pana (push) Successful in 2m9s
CI and Release / version-and-changelog (push) Successful in 20s
CI and Release / publish (push) Failing after 13s
Initial release 🥳 Reviewed-on: #1
90 lines
2.7 KiB
Markdown
90 lines
2.7 KiB
Markdown
# list_or
|
|
|
|
Ever worked with an API that usually returns a list of items, but sometimes decides to return a single item just to keep you on your toes?
|
|
|
|
`list_or` is a lightweight Dart utility that fixes this exact headache. It takes an arbitrary dynamic value, whether it's a single object, an array, a `Set`, or even `null`, and normalizes it into a standard, predictable `List<T>`.
|
|
|
|
No more writing boilerplate type-checks for every flexible JSON payload.
|
|
|
|
## Features
|
|
|
|
* **Normalizes inputs:** Wraps single values into a list, or passes through existing iterables.
|
|
* **Fully mutable:** Implements `ListMixin`, meaning you can `.add()`, `.map()`, `.remove()`, and iterate over it just like any other Dart list.
|
|
* **Type-safe:** Strictly enforces your generic type `T`. If you expect a `String` and get an `int`, it throws immediately.
|
|
* **Smart null handling:** Explicitly supports `null` values only if you define the type as nullable (e.g., `ListOr<String?>`).
|
|
* **Clean stringification:** If the list only has one item, `toString()` prints just that item instead of adding `[ ]` brackets.
|
|
|
|
## Getting Started
|
|
|
|
Add the package to your `pubspec.yaml`:
|
|
|
|
```bash
|
|
dart pub add list_or
|
|
|
|
```
|
|
|
|
Or, if you're using Flutter:
|
|
|
|
```bash
|
|
flutter pub add list_or
|
|
|
|
```
|
|
|
|
Import it in your file:
|
|
|
|
```dart
|
|
import 'package:list_or/list_or.dart';
|
|
|
|
```
|
|
|
|
## Usage
|
|
|
|
The most common use case is parsing unpredictable JSON.
|
|
|
|
Imagine an API endpoint where the `tags` field might be a single string or an array of strings depending on how many tags the user added.
|
|
|
|
```dart
|
|
import 'package:list_or/list_or.dart';
|
|
|
|
void main() {
|
|
// Scenario A: The API returns a single string
|
|
final Map<String, dynamic> json1 = {'id': 1, 'tags': 'flutter'};
|
|
|
|
// Scenario B: The API returns an array of strings
|
|
final Map<String, dynamic> json2 = {'id': 2, 'tags': ['dart', 'backend']};
|
|
|
|
// ListOr normalizes both seamlessly.
|
|
final tags1 = ListOr<String>(json1['tags']);
|
|
final tags2 = ListOr<String>(json2['tags']);
|
|
|
|
print(tags1); // Output: flutter
|
|
print(tags2); // Output: [dart, backend]
|
|
|
|
// You can interact with it exactly like a normal list
|
|
tags1.add('mobile');
|
|
print(tags1.length); // Output: 2
|
|
print(tags1.contains('mobile')); // Output: true
|
|
}
|
|
|
|
```
|
|
|
|
### Handling Nulls
|
|
|
|
If your payload might intentionally contain nulls, just make your generic type
|
|
nullable:
|
|
|
|
```dart
|
|
// This works perfectly
|
|
final nullableList = ListOr<int?>(null);
|
|
print(nullableList.length); // Output: 1
|
|
|
|
// This will throw an ArgumentError to keep your types safe
|
|
final strictList = ListOr<int>(null);
|
|
|
|
```
|
|
|
|
## Additional Information
|
|
|
|
* **Found a bug?** Open an issue on the issue tracker.
|
|
* **Want to contribute?** Pull requests are welcome. Please ensure that all existing tests pass and add new tests for any new functionality.
|