deep_pick
Simplifies manual JSON parsing with a type-safe API. No dynamic, no manual casting. Flexible inputs types, fixed output types. Useful parsing error messages
1.1.0
151K downloads/mo
#956 most downloaded on pub.dev
passsy/deep_pick
What this package is like to depend on
Last release 2 years ago
no release in 18 months
Release timing varies
gaps range from 2 weeks to 1.4 years
Nearly every release is documented
notes for 18 of 18 stable releases
Nothing withdrawn
no release was ever pulled
7 years old
21 releases · first in 2019
0 releases in the last 12 months
see the full history below
Release timeline
21 releases · Jul 2019 to Aug 2024Releases
latest 21-
1.1.030 Aug 2024Release notes
Open source →- Allow
.letOrNull((pick) => null)to returnnullwithout manually setting a nullable type #61 - CI 2024 update
Release notes
Open source →- Allow
.letOrNull((pick) => null)to returnnullwithout manually setting a nullable type #61 - CI 2024 update
- Allow
-
1.0.019 Mar 2023Release notes
Open source →- Remove long deprecated methods:
addContext,asBool,asDateTime,asDouble,asInt,asList,asMap,asString. Use theiras*OrThrowreplacements. - Add support for timezones in
asDateTime*methods #47, #51 - Add official support for date formats
RFC 3339,RFC 2822andRFC 1036 - Push test coverage to 100% 🤘
BREAKING CHANGES ├─┬ Class Pick │ └── Field "addContext" removed (CF01) ├─┬ Class RequiredPick │ └── Field "addContext" removed (CF01) ├─┬ Class BoolPick │ └── Field "asBool" removed (CF01) ├─┬ Class NullableDateTimePick │ └── Field "asDateTime" removed (CF01) ├─┬ Class NullableDoublePick │ └── Field "asDouble" removed (CF01) ├─┬ Class NullableIntPick │ └── Field "asInt" removed (CF01) ├─┬ Class NullableListPick │ └── Method "asList" removed (CE10) ├─┬ Class NullableMapPick │ └── Field "asMap" removed (CF01) └─┬ Class NullableStringPick └── Field "asString" removed (CF01) - Remove long deprecated methods:
-
0.10.001 Nov 2021Release notes
Open source →- New: Support for more date formats.
asDateTime*received an optionalformatparameter. By default, all possible formats will be parsed. To the existingISO 8601format,RFC 1123,RFC 850andasctimehave been added which are typically used for the HTTP header or cookies. - Documentation added for
asDoubleandasMap
Release notes
Open source →- New: Support for more date formats.
asDateTime*received an optionalformatparameter. By default, all possible formats will be parsed. To the existingISO 8601format,RFC 1123,RFC 850andasctimehave been added which are typically used for the HTTP header or cookies. - Documentation added for
asDoubleandasMap
- New: Support for more date formats.
-
0.9.002 Aug 2021Release notes
Open source →-
New:
pickFromJson(json, args...)allows parsing of a json String, without manually callingjsonDecode#41 -
New:
pickDeep(json, 'some.key.inside.the.object'.split('.'))allows picking with a dynamic depth #40 -
Add
Pick.indexto get the element index for list items #38pick(["John", "Paul", "George", "Ringo"]).asListOrThrow((pick) { final index = pick.index!; return Artist(id: index, name: pick.asStringOrThrow()); );
-
Pick.asIntOrThrow()now allows parsing of doubles when one of the newroundDoubleortruncateDoubleparameters istrue#37. Thx @stevendz -
Add dartdoc to
asList*()extensions
Release notes
Open source →-
New:
pickFromJson(json, args...)allows parsing of a json String, without manually callingjsonDecode#41 -
New:
pickDeep(json, 'some.key.inside.the.object'.split('.'))allows picking with a dynamic depth #40 -
Add
Pick.indexto get the element index for list items #38pick(["John", "Paul", "George", "Ringo"]).asListOrThrow((pick) { final index = pick.index!; return Artist(id: index, name: pick.asStringOrThrow()); ); -
Pick.asIntOrThrow()now allows parsing of doubles when one of the newroundDoubleortruncateDoubleparameters istrue#37. Thx @stevendz -
Add dartdoc to
asList*()extensions
-
-
0.8.014 Feb 2021Release notes
Open source →- Deprecated parsing extensions of
RequiredPickto acknowledge that all parsers eventually causes errors.
From now on, always use.asIntOrThrow()instead of.required().asInt(). Only exception is.required().toString().
Read more in #34 - Replace
dynamicwithObjectwhere possible - Rename
Pick.location()toPick.debugParsingExit - Removal of
PickLocaitonandPickContextmixins. They are now part ofPick RequiredPicknow extendsPickmaking it easier to write parsers for custom types
This release is available as backport for Dart <2.12 with version
0.6.10Release notes
Open source →- Deprecated parsing extensions of
RequiredPickto acknowledge that all parsers eventually causes errors. From now on, always use.asIntOrThrow()instead of.required().asInt(). Only exception is.required().toString(). Read more in #34 - Replace
dynamicwithObjectwhere possible - Rename
Pick.location()toPick.debugParsingExit - Removal of
PickLocaitonandPickContextmixins. They are now part ofPick RequiredPicknow extendsPickmaking it easier to write parsers for custom types
- Deprecated parsing extensions of
-
0.7.009 Feb 2021 -
0.6.1014 Feb 2021 -
0.6.009 Feb 2021Release notes
Open source →API changes
-
Remove long deprecated
parseJsonTo*methods. Use thepick(json, args*)api -
New
asXyzOrThrow()methods as shorthand for.required().asXyz()featuring better error messagesasBoolOrThrow()asDateTimeOrThrow()asDoubleOrThrow()asIntOrThrow()letOrThrow()asListOrThrow()asMapOrThrow()asStringOrThrow()
-
New
Pick.isAbsentgetter to check if a value is absent ornull#24. Absent could mean- Accessing a key which doesn't exist in a
Map - Reading the value from
Listwhen the index is greater than the length - Trying to access a key in a
Mapbut the found data aObjectwhich isn't a Map
- Accessing a key which doesn't exist in a
-
New
RequiredPick.nullable()converting aRequiredPickback to aPickwith potentialnullvalue -
New
PickLocation.followablePath. WhilePickLocation.pathcontains the full path to the value,followablePathcontains only the part which could be followed with a non-nullable value -
Breaking
asList*()now requires the mapping function. -
Breaking
asList*()now ignoresnullvalues when parsing. The map function now receives aRequiredPickas fist parameter instead of aPickwith a potential null value, making parsing easier.Therefore
pick().required().asList((RequiredPick pick) => /*...*/)only maps non-nullable values. When your lists containnullit will be ignored. This is fine in most cases and simplifies the map function.In rare cases, where your lists contain
nullvalues with meaning, use the second parameterwhenNullto map those null values.asList((pick) => Person.fromPick(pick), whenNull: (Pick it) => null). The function still receives aPickwhich gives access to thecontextapi or thePickLocation. But thePicknever holds any value.
Parsing changes
-
-
0.6.0-nullsafety.209 Feb 2021 pre-releaseRelease notes
Open source →-
Breaking
asList*()methods now ignorenullvalues. The map function now receives aRequiredPickas fist parameter instead of aPickmaking parsing easier.Therefore
pick().required().asList((RequiredPick pick) => /*...*/)only maps non-nullable values. When your lists containnullit will be ignored.
This is fine in most cases and simplifies the map function.In rare cases, where your lists contain
nullvalues with meaning, use the second parameterwhenNullto map those null values.asList((pick) => Person.fromPick(pick), whenNull: (Pick it) => null). The function still receives aPickwhich gives access to thecontextapi or thePickLocation. But thePicknever holds any value. -
Breaking Don't parse doubles as int because the is no rounding method which satisfies all #31
-
Breaking Allow parsing of "german" doubles with
,as decimal separator #30 -
Improve error messages with more details where parsing stopped
-
New
RequiredPick.nullable()converting aRequiredPickback to aPickwith potentialnullvalue -
New
PickLocation.followablePath. WhilePickLocation.pathcontains the full path to the value,followablePathcontains only the part which could be followed with a non-nullable value
Release notes
Open source →-
Breaking
asList*()methods now ignorenullvalues. The map function now receives aRequiredPickas fist parameter instead of aPickmaking parsing easier.Therefore
pick().required().asList((RequiredPick pick) => /*...*/)only maps non-nullable values. When your lists containnullit will be ignored. This is fine in most cases and simplifies the map function.In rare cases, where your lists contain
nullvalues with meaning, use the second parameterwhenNullto map those null values.asList((pick) => Person.fromPick(pick), whenNull: (Pick it) => null). The function still receives aPickwhich gives access to thecontextapi or thePickLocation. But thePicknever holds any value. -
Breaking Don't parse doubles as int because the is no rounding method which satisfies all #31
-
Breaking Allow parsing of "german" doubles with
,as decimal separator #30 -
Improve error messages with more details where parsing stopped
-
New
RequiredPick.nullable()converting aRequiredPickback to aPickwith potentialnullvalue -
New
PickLocation.followablePath. WhilePickLocation.pathcontains the full path to the value,followablePathcontains only the part which could be followed with a non-nullable value
-
-
0.6.0-nullsafety.106 Dec 2020 pre-releaseRelease notes
Open source →- New
asXyzOrThrow()methods as shorthand for.required().asXyz()featuring better error messagesasBoolOrThrow()asDateTimeOrThrow()asDoubleOrThrow()asIntOrThrow()letOrThrow()asListOrThrow()asMapOrThrow()asStringOrThrow()
- New
Pick.isAbsentgetter to check if a value is absent ornull#24. Absent could mean- Accessing a key which doesn't exist in a
Map - Reading the value from
Listwhen the index is greater than the length - Trying to access a key in a
Mapbut the found data aObjectwhich isn't a Map
- Accessing a key which doesn't exist in a
- The String
"true"and"false"are now parsed as boolean - More nnbd refactoring
Release notes
Open source →- New
asXyzOrThrow()methods as shorthand for.required().asXyz()featuring better error messagesasBoolOrThrow()asDateTimeOrThrow()asDoubleOrThrow()asIntOrThrow()letOrThrow()asListOrThrow()asMapOrThrow()asStringOrThrow()
- New
Pick.isAbsentgetter to check if a value is absent ornull#24. Absent could mean- Accessing a key which doesn't exist in a
Map - Reading the value from
Listwhen the index is greater than the length - Trying to access a key in a
Mapbut the found data aObjectwhich isn't a Map
- Accessing a key which doesn't exist in a
- The String
"true"and"false"are now parsed as boolean - More nnbd refactoring
- New
-
0.6.0-nullsafety.023 Nov 2020 pre-releaseRelease notes
Open source →- Migrate to nullsafety (required Dart >=2.12)
- Remove deprecated long deprecated
parseJsonTo*methods. Use thepick(json, args*)api - Improve dartdoc
Release notes
Open source →- Migrate to nullsafety (required Dart >=2.12)
- Remove long deprecated
parseJsonTo*methods. Use thepick(json, args*)api - Improve dartdoc
-
0.5.104 Sep 2020Release notes
Open source →- Rename
Pick.addContexttoPick.withContextusing deprecation Pick.fromContextnow accepts 10 arguments for nested structures- Fix
Pick.fromContextalways returningcontextnot the value forkeyin contextMap
- Rename
-
0.5.031 Aug 2020Release notes
Open source →-
New context API. You can now attach relevant additional information for parsing directly to the
Pickobject. This allows passing information intofromPickconstructors without adding new parameters to all constructors in between.// Add context final shoes = pick(json, 'shoes') .addContext('apiVersion', "2.3.0") .addContext('lang', "en-US") .asListOrEmpty((p) => Shoe.fromPick(p.required()));import 'package:version/version.dart'; // Read context factory Shoe.fromPick(RequiredPick pick) { // read context API final version = pick.fromContext('newApi').required().let((pick) => Version(pick.asString())); return Shoe( id: pick('id').required().asString(), name: pick('name').required().asString(), // manufacturer is a required field in the new API manufacturer: version >= Version(2, 3, 0) ? pick('manufacturer').required().asString() : pick('manufacturer').asStringOrNull(), tags: pick('tags').asListOrEmpty(), ); } -
Breaking:
PickandRequiredPickhave chained their constructor signature.pathis now a named argument andcontexthas been added.
- RequiredPick(this.value, [this.path = const []]) + RequiredPick(this.value, {this.path = const [], Map<String, dynamic> context})- The
pathis now correctly forwarded afterPick#callorPick#asListOrEmptyand always shows the full path since origin
-
-
0.4.319 Aug 2020Release notes
Open source →- Fix error reporting for
asMapOr[Empty|Null]and don't swallow parsing errors - Throw Map cast errors when parsing, not lazily when accessing the data
- Fix error reporting for
-
0.4.217 Mar 2020Release notes
Open source →- Fix error reporting of
asListOrNull(mapToUser)andasListOrEmpty(mapToUser). Both now return errors during mapping and don't swallow them
- Fix error reporting of
-
0.4.107 Feb 2020Release notes
Open source →- Print correct path in error message when json is
null asDateTime()now skips parsing when the value is already aDateTime
- Print correct path in error message when json is
-
0.4.008 Nov 2019Release notes
Open source →Map objects
New APIs to map picks to objects and to map list elements to objects.
RequiredPick.let<R>(R Function(RequiredPick pick) block): R Pick.letOrNull<R>(R Function(RequiredPick pick) block): R RequiredPick.asList<T>([T Function(Pick) map]): List<T> Pick.asListOrNull<T>([T Function(Pick) map]): List<T> Pick.asListOrEmpty<T>([T Function(Pick) map]): List<T>Here are two example how to actually use them.
// easily pick and map objects to dart objects final Shoe oneShoe = pick(json, 'shoes', 0).letOrNull((p) => Shoe.fromPick(p)); // map list of picks to dart objects final List<Shoe> shoes = pick(json, 'shoes').asListOrEmpty((p) => Shoe.fromPick(p.required()));Required picks
Picknow offers a newrequired()method returning aRequiredPick. It makes sure the picked value exists or crashes if it isnull. Because it can't benull,RequiredPickdoesn't offer fallback methods like.asIntOrNull()but only.asInt(). This makes the API a bit easier to use for values you can't live without.// use required() to crash if a object doesn't exist final name = pick(json, 'shoes', 0, 'name').required().asString(); print(name); // Nike Zoom Fly 3Note: Calling
.asString()directly onPickhas been deprecated. You now have to callrequired()first to convert thePickto aRequiredPickor use a mapping method with fallbacks.Pick deeper
Ever got a
Pick/RequiredPickand you wanted to pick even further. This is now possible with thecallmethod. Very useful in constructors when parsing methods.factory Shoe.fromPick(RequiredPick pick) { return Shoe( id: pick('id').required().asString(), name: pick('name').required().asString(), manufacturer: pick('manufacturer').asStringOrNull(), tags: pick('tags').asListOrEmpty(), ); }Bugfixes
- Don't crash when selecting a out of range index from a
List .asMap(),.asMapOrNull()and.asMapOrEmpty()now consistently returnMap<dynamic, dynamic>(wasMap<String, dynamic>)
Also the lib has been converted to use static extension methods which were introduced in Dart 2.6
- Don't crash when selecting a out of range index from a
-
0.3.021 Oct 2019Release notes
Open source →asMapnow expects the key type, defaults todynamicinstead ofString-Pick.asMap(): Map<String, dynamic> +Pick.asMap<T>(): Map<T, dynamic> -
0.2.027 Sep 2019Release notes
Open source →New API! The old
parse*methods are now deprecated, but still work. Replace them with the newpick(json, arg0-9...)method.- final name = parseJsonToString(json, 'shoes', 0, 'name'); + final name = pick(json, 'shoes', 0, 'name').asString();pickreturns aPickwhich offers a rich API to parse values..asString() .asStringOrNull() .asMap() .asMapOrEmpty() .asMapOrNull() .asList() .asListOrEmpty() .asListOrNull() .asBool() .asBoolOrNull() .asBoolOrTrue() .asBoolOrFalse() .asInt() .asIntOrNull() .asDouble() .asDoubleOrNull() .asDateTime() .asDateTimeOrNull() -
0.1.117 Jul 2019 -
0.1.017 Jul 2019