Skip to content

Commit

Permalink
⚡ decode returns Map<String, dynamic> instead of Map (#17)
Browse files Browse the repository at this point in the history
  • Loading branch information
techouse committed May 18, 2024
1 parent de9d285 commit 5384175
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 80 deletions.
10 changes: 5 additions & 5 deletions lib/src/extensions/decode.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ extension _$Decode on QS {
? val.split(',')
: val;

static Map _parseQueryStringValues(
static Map<String, dynamic> _parseQueryStringValues(
String str, [
DecodeOptions options = const DecodeOptions(),
]) {
final Map obj = {};
final Map<String, dynamic> obj = {};

final String cleanStr =
options.ignoreQueryPrefix ? str.replaceFirst('?', '') : str;
Expand Down Expand Up @@ -107,7 +107,7 @@ extension _$Decode on QS {
? List<dynamic>.empty(growable: true)
: [if (leaf is Iterable) ...leaf else leaf];
} else {
obj = Map.of({});
obj = <String, dynamic>{};
final String cleanRoot = root.startsWith('[') && root.endsWith(']')
? root.slice(1, root.length - 1)
: root;
Expand All @@ -116,7 +116,7 @@ extension _$Decode on QS {
: cleanRoot;
final int? index = int.tryParse(decodedRoot);
if (!options.parseLists && decodedRoot == '') {
obj = Map.of({0: leaf});
obj = <String, dynamic>{'0': leaf};
} else if (index != null &&
index >= 0 &&
root != decodedRoot &&
Expand All @@ -130,7 +130,7 @@ extension _$Decode on QS {
);
obj[index] = leaf;
} else {
obj[index ?? decodedRoot] = leaf;
obj[index?.toString() ?? decodedRoot] = leaf;
}
}

Expand Down
2 changes: 1 addition & 1 deletion lib/src/methods.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import 'package:qs_dart/src/models/encode_options.dart';
import 'package:qs_dart/src/qs.dart';

/// Convenience method for [QS.decode]
Map decode(
Map<String, dynamic> decode(
dynamic input, [
DecodeOptions options = const DecodeOptions(),
]) =>
Expand Down
42 changes: 22 additions & 20 deletions lib/src/qs.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,43 +19,45 @@ part 'extensions/encode.dart';

/// A query string decoder (parser) and encoder (stringifier) class.
final class QS {
/// Decodes a [String] or [Map] into a [Map].
/// Decodes a [String] or [Map<String, dynamic>] into a [Map<String, dynamic>].
/// Providing custom [options] will override the default behavior.
static Map decode(
static Map<String, dynamic> decode(
dynamic input, [
DecodeOptions options = const DecodeOptions(),
]) {
if (!(input is String? || input is Map?)) {
if (!(input is String? || input is Map<String, dynamic>?)) {
throw ArgumentError.value(
input,
'input',
'The input must be a String or a Map',
'The input must be a String or a Map<String, dynamic>',
);
}

if (input?.isEmpty ?? true) {
return Map.of({});
return <String, dynamic>{};
}

Map? tempObj = input is String
Map<String, dynamic>? tempObj = input is String
? _$Decode._parseQueryStringValues(input, options)
: input;
Map obj = {};
Map<String, dynamic> obj = {};

// Iterate over the keys and setup the new object
for (final MapEntry entry in tempObj?.entries ?? List.empty()) {
final newObj = _$Decode._parseKeys(
entry.key,
entry.value,
options,
input is String,
);

obj = Utils.merge(
obj,
newObj,
options,
);
if (tempObj?.isNotEmpty ?? false) {
for (final MapEntry<String, dynamic> entry in tempObj!.entries) {
final newObj = _$Decode._parseKeys(
entry.key,
entry.value,
options,
input is String,
);

obj = Utils.merge(
obj,
newObj,
options,
);
}
}

return Utils.compact(obj);
Expand Down
33 changes: 20 additions & 13 deletions lib/src/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,12 @@ final class Utils {
}
} else if (target is Map) {
if (source is Iterable) {
target = Map.of(target)
..addAll({
for (final (int i, dynamic item) in source.indexed)
if (item is! Undefined) i: item
});
target = <String, dynamic>{
for (final MapEntry entry in target.entries)
entry.key.toString(): entry.value,
for (final (int i, dynamic item) in source.indexed)
if (item is! Undefined) i.toString(): item
};
}
} else if (source != null) {
if (target is! Iterable && source is Iterable) {
Expand All @@ -105,9 +106,9 @@ final class Utils {

if (target == null || target is! Map) {
if (target is Iterable) {
return Map.of({
return Map<String, dynamic>.of({
for (final (int i, dynamic item) in target.indexed)
if (item is! Undefined) i: item,
if (item is! Undefined) i.toString(): item,
...source,
});
}
Expand All @@ -124,13 +125,19 @@ final class Utils {
];
}

Map mergeTarget = target is Iterable && source is! Iterable
? (target as Iterable).toList().whereNotUndefined().asMap()
: Map.of(target);
Map<String, dynamic> mergeTarget = target is Iterable && source is! Iterable
? {
for (final (int i, dynamic item) in (target as Iterable).indexed)
if (item is! Undefined) i.toString(): item
}
: {
for (final MapEntry entry in target.entries)
entry.key.toString(): entry.value
};

return source.entries.fold(mergeTarget, (Map acc, MapEntry entry) {
acc.update(
entry.key,
entry.key.toString(),
(value) => merge(
value,
entry.value,
Expand Down Expand Up @@ -332,8 +339,8 @@ final class Utils {
}
}

static Map compact(Map value) {
final List<Map> queue = [
static Map<String, dynamic> compact(Map<String, dynamic> value) {
final List<Map<String, dynamic>> queue = [
{
'obj': {'o': value},
'prop': 'o',
Expand Down
10 changes: 5 additions & 5 deletions test/fixtures/data/empty_test_cases.dart
Original file line number Diff line number Diff line change
Expand Up @@ -244,8 +244,8 @@ const List<Map<String, dynamic>> emptyTestCases = [
'repeat': '=a&=b& =1'
},
'noEmptyKeys': {
0: 'a',
1: 'b',
'0': 'a',
'1': 'b',
' ': ['1']
}
},
Expand All @@ -256,8 +256,8 @@ const List<Map<String, dynamic>> emptyTestCases = [
'a': ['1', '2']
},
'noEmptyKeys': {
0: 'a',
1: 'b',
'0': 'a',
'1': 'b',
'a': ['1', '2']
},
'stringifyOutput': {
Expand Down Expand Up @@ -292,6 +292,6 @@ const List<Map<String, dynamic>> emptyTestCases = [
'indices': '[0]=a&[1]=b',
'repeat': '=a&=b'
},
'noEmptyKeys': {0: 'a', 1: 'b'}
'noEmptyKeys': {'0': 'a', '1': 'b'}
}
];
16 changes: 10 additions & 6 deletions test/unit/array_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,21 @@ import 'package:test/test.dart';
void main() {
group('SplayTreeMap', () {
test('indices are ordered in value', () {
final SplayTreeMap<int, String> array =
SplayTreeMap<int, String>.from({1: 'a', 0: 'b', 2: 'c'});
final SplayTreeMap<String, String> array =
SplayTreeMap<String, String>.from({
'1': 'a',
'0': 'b',
'2': 'c',
});

expect(array.values, ['b', 'a', 'c']);
});

test('indices are ordered in value 2', () {
final SplayTreeMap<int, String> array = SplayTreeMap<int, String>();
array[1] = 'c';
array[0] = 'b';
array[2] = 'd';
final SplayTreeMap<String, String> array = SplayTreeMap<String, String>();
array['1'] = 'c';
array['0'] = 'b';
array['2'] = 'd';

expect(array.values, ['b', 'c', 'd']);
});
Expand Down
Loading

0 comments on commit 5384175

Please sign in to comment.