Skip to content

Commit 9d906df

Browse files
author
travis
committed
feat: add non-nullable versions of flexible parsing functions with default values
1 parent 1c991a8 commit 9d906df

File tree

6 files changed

+168
-3
lines changed

6 files changed

+168
-3
lines changed

CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
## 0.3.7
2+
3+
- Added comprehensive tests for all new features
4+
5+
## 0.3.6
6+
7+
- Added non-nullable versions of flexible functions that return default values instead of null:
8+
- `flexibleRequiredBoolFromJson`: Returns false if null
9+
- `flexibleRequiredListFromJson`: Returns empty list if null (alias for flexibleListNotNullFromJson)
10+
11+
## 0.3.5
12+
13+
- Added non-nullable versions of flexible functions that return default values instead of null:
14+
- `flexibleRequiredIntFromJson`: Returns 0 if null
15+
- `flexibleRequiredDoubleFromJson`: Returns 0.0 if null
16+
- `flexibleRequiredStringFromJson`: Returns empty string if null
17+
118
## 0.3.4
219

320
- Ran dart format on the codebase

README.md

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ Add this to your package's `pubspec.yaml` file:
6666

6767
```yaml
6868
dependencies:
69-
json_son: ^0.3.4 # Or the latest version
69+
json_son: ^0.3.7 # Or the latest version
7070
```
7171
7272
Then, run `flutter pub get` or `dart pub get`.
@@ -512,6 +512,31 @@ class TimestampInfo {
512512
- Filters out items that parse to `null`.
513513
- Returns an empty list if the input is `null` or if all items parse to `null`.
514514

515+
- `int flexibleRequiredIntFromJson(dynamic value)`
516+
- Non-nullable version of `flexibleIntFromJson`.
517+
- Returns `0` instead of `null` when the input is `null` or cannot be parsed as an integer.
518+
- Useful when you need to guarantee a non-null integer value.
519+
520+
- `double flexibleRequiredDoubleFromJson(dynamic value)`
521+
- Non-nullable version of `flexibleDoubleFromJson`.
522+
- Returns `0.0` instead of `null` when the input is `null` or cannot be parsed as a double.
523+
- Useful when you need to guarantee a non-null double value.
524+
525+
- `String flexibleRequiredStringFromJson(dynamic value)`
526+
- Non-nullable version of `flexibleStringFromJson`.
527+
- Returns an empty string (`""`) instead of `null` when the input is `null`.
528+
- Useful when you need to guarantee a non-null string value.
529+
530+
- `bool flexibleRequiredBoolFromJson(dynamic value)`
531+
- Non-nullable version of `flexibleBoolFromJson`.
532+
- Returns `false` instead of `null` when the input is `null` or cannot be parsed as a boolean.
533+
- Useful when you need to guarantee a non-null boolean value.
534+
535+
- `List<T> flexibleRequiredListFromJson<T>(dynamic value, T? Function(dynamic) itemParser)`
536+
- Alias for `flexibleListNotNullFromJson` to provide a consistent naming convention.
537+
- Returns an empty list if the input is `null` or if all items parse to `null`.
538+
- Useful when you need to guarantee a non-null list.
539+
515540
- `List<String>? flexibleCommaSeparatedListFromJson(dynamic value)`
516541
- Parses comma-separated strings (e.g., "apple, banana, cherry") into `List<String>?`.
517542
- Trims whitespace from each item and filters out empty strings.

lib/json_son.dart

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,14 @@ export 'src/json_son_extensions.dart';
2323
export 'src/json_son_validator.dart';
2424

2525
export 'src/json_son_base.dart'
26-
show flexibleMapFromJson, flexibleMapNotNullFromJson;
26+
show
27+
flexibleMapFromJson,
28+
flexibleMapNotNullFromJson,
29+
flexibleRequiredIntFromJson,
30+
flexibleRequiredDoubleFromJson,
31+
flexibleRequiredStringFromJson,
32+
flexibleRequiredBoolFromJson,
33+
flexibleRequiredListFromJson;
2734

2835
/// Parses a [dynamic] value into an [int]?.
2936
/// Handles `null`, `int`, `double` (truncates), and `String` representations.

lib/src/json_son_base.dart

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@ int? flexibleIntFromJson(dynamic value) {
1212
return null; // Fallback for other unexpected types
1313
}
1414

15+
/// Parses a [dynamic] value into a non-nullable [int].
16+
/// Similar to [flexibleIntFromJson], but returns 0 instead of null.
17+
/// Useful when you need to guarantee a non-null int value.
18+
int flexibleRequiredIntFromJson(dynamic value) {
19+
return flexibleIntFromJson(value) ?? 0;
20+
}
21+
1522
/// Parses a [dynamic] value into a [double]?.
1623
/// Handles `null`, `double`, `int`, and `String` representations.
1724
/// An empty string or a string that fails to parse will result in `null`.
@@ -26,6 +33,13 @@ double? flexibleDoubleFromJson(dynamic value) {
2633
return null; // Fallback for other unexpected types
2734
}
2835

36+
/// Parses a [dynamic] value into a non-nullable [double].
37+
/// Similar to [flexibleDoubleFromJson], but returns 0.0 instead of null.
38+
/// Useful when you need to guarantee a non-null double value.
39+
double flexibleRequiredDoubleFromJson(dynamic value) {
40+
return flexibleDoubleFromJson(value) ?? 0.0;
41+
}
42+
2943
/// Parses a [dynamic] value into a [bool]?.
3044
/// Handles `null`, `bool`, `String` (e.g., "true", "false", "1", "0", case-insensitive),
3145
/// and `int` (1 for true, 0 for false) representations.
@@ -46,6 +60,13 @@ bool? flexibleBoolFromJson(dynamic value) {
4660
return null; // Fallback for other unexpected types or unhandled values
4761
}
4862

63+
/// Parses a [dynamic] value into a non-nullable [bool].
64+
/// Similar to [flexibleBoolFromJson], but returns false instead of null.
65+
/// Useful when you need to guarantee a non-null boolean value.
66+
bool flexibleRequiredBoolFromJson(dynamic value) {
67+
return flexibleBoolFromJson(value) ?? false;
68+
}
69+
4970
/// Parses a [dynamic] value into a [String]?.
5071
/// Handles `null` and `String`. Converts other types (like `int`, `double`, `bool`)
5172
/// to their string representation using `.toString()`.
@@ -57,6 +78,13 @@ String? flexibleStringFromJson(dynamic value) {
5778
return value.toString();
5879
}
5980

81+
/// Parses a [dynamic] value into a non-nullable [String].
82+
/// Similar to [flexibleStringFromJson], but returns an empty string instead of null.
83+
/// Useful when you need to guarantee a non-null string value.
84+
String flexibleRequiredStringFromJson(dynamic value) {
85+
return flexibleStringFromJson(value) ?? '';
86+
}
87+
6088
/// Parses a [dynamic] value into a [num]? (int or double).
6189
/// Handles `null`, `num` (and its subtypes `int`, `double`), and `String` representations.
6290
/// An empty string or a string that fails to parse will result in `null`.
@@ -173,6 +201,22 @@ List<T> flexibleListNotNullFromJson<T>(
173201
return parsedSingleItem != null ? [parsedSingleItem] : <T>[];
174202
}
175203

204+
/// Alias for [flexibleListNotNullFromJson] to provide a consistent naming convention
205+
/// with other required functions.
206+
/// Returns an empty list if the input is null or if parsing results in all nulls.
207+
///
208+
/// Example:
209+
/// ```dart
210+
/// @JsonKey(fromJson: (v) => flexibleRequiredListFromJson(v, flexibleIntFromJson))
211+
/// List<int> scores; // Guarantees a List<int>, never null.
212+
/// ```
213+
List<T> flexibleRequiredListFromJson<T>(
214+
dynamic value,
215+
T? Function(dynamic) itemParser,
216+
) {
217+
return flexibleListNotNullFromJson<T>(value, itemParser);
218+
}
219+
176220
/// Parses comma-separated strings into a list of strings.
177221
/// Handles `null` input.
178222
/// If input is already a list, its elements are converted to strings.

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: json_son
22
description: >-
33
A Dart utility package providing helper functions to flexibly parse JSON values
44
that might have inconsistent data types (e.g., strings to numbers, strings/numbers to booleans).
5-
version: 0.3.4
5+
version: 0.3.7
66
homepage: https://github.com/scalecode-solutions/json_son/blob/main/README.md
77
repository: https://github.com/scalecode-solutions/json_son
88

test/required_functions_test.dart

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import 'package:json_son/json_son.dart';
2+
import 'package:test/test.dart';
3+
4+
void main() {
5+
group('Required (non-nullable) functions', () {
6+
test('flexibleRequiredIntFromJson returns 0 for null', () {
7+
expect(flexibleRequiredIntFromJson(null), equals(0));
8+
});
9+
10+
test('flexibleRequiredIntFromJson returns parsed value for valid input',
11+
() {
12+
expect(flexibleRequiredIntFromJson(42), equals(42));
13+
expect(flexibleRequiredIntFromJson('42'), equals(42));
14+
expect(flexibleRequiredIntFromJson(42.5), equals(42));
15+
});
16+
17+
test('flexibleRequiredDoubleFromJson returns 0.0 for null', () {
18+
expect(flexibleRequiredDoubleFromJson(null), equals(0.0));
19+
});
20+
21+
test('flexibleRequiredDoubleFromJson returns parsed value for valid input',
22+
() {
23+
expect(flexibleRequiredDoubleFromJson(42.5), equals(42.5));
24+
expect(flexibleRequiredDoubleFromJson('42.5'), equals(42.5));
25+
expect(flexibleRequiredDoubleFromJson(42), equals(42.0));
26+
});
27+
28+
test('flexibleRequiredStringFromJson returns empty string for null', () {
29+
expect(flexibleRequiredStringFromJson(null), equals(''));
30+
});
31+
32+
test('flexibleRequiredStringFromJson returns string for valid input', () {
33+
expect(flexibleRequiredStringFromJson('hello'), equals('hello'));
34+
expect(flexibleRequiredStringFromJson(42), equals('42'));
35+
expect(flexibleRequiredStringFromJson(true), equals('true'));
36+
});
37+
38+
test('flexibleRequiredBoolFromJson returns false for null', () {
39+
expect(flexibleRequiredBoolFromJson(null), equals(false));
40+
});
41+
42+
test('flexibleRequiredBoolFromJson returns parsed value for valid input',
43+
() {
44+
expect(flexibleRequiredBoolFromJson(true), equals(true));
45+
expect(flexibleRequiredBoolFromJson('true'), equals(true));
46+
expect(flexibleRequiredBoolFromJson(1), equals(true));
47+
expect(flexibleRequiredBoolFromJson(false), equals(false));
48+
expect(flexibleRequiredBoolFromJson('false'), equals(false));
49+
expect(flexibleRequiredBoolFromJson(0), equals(false));
50+
});
51+
52+
test('flexibleRequiredListFromJson returns empty list for null', () {
53+
expect(flexibleRequiredListFromJson(null, flexibleIntFromJson), isEmpty);
54+
});
55+
56+
test('flexibleRequiredListFromJson returns parsed list for valid input',
57+
() {
58+
expect(
59+
flexibleRequiredListFromJson([1, 2, 3], flexibleIntFromJson),
60+
equals([1, 2, 3]),
61+
);
62+
expect(
63+
flexibleRequiredListFromJson(['1', '2', '3'], flexibleIntFromJson),
64+
equals([1, 2, 3]),
65+
);
66+
expect(
67+
flexibleRequiredListFromJson(42, flexibleIntFromJson),
68+
equals([42]),
69+
);
70+
});
71+
});
72+
}

0 commit comments

Comments
 (0)