hans 5987eba14b
Release / create-tag-and-release (push) Successful in 15s
Add issue templates, contribution guidelines, and code of conduct; update CI/CD workflows and project metadata (#3)
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
Reviewed-on: #3
2026-05-13 14:13:57 +02:00
2026-05-13 13:06:34 +02:00
2026-05-13 13:06:34 +02:00
2026-05-13 13:06:34 +02:00
2026-05-13 13:06:34 +02:00
2026-05-13 13:06:34 +02:00

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:

dart pub add list_or

Or, if you're using Flutter:

flutter pub add list_or

Import it in your file:

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.

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:

// 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.
S
Description
No description provided
Readme BSD-3-Clause 68 KiB
v1.0.1 Latest
2026-05-13 14:14:09 +02:00
Languages
Dart 96%
Shell 4%