PackageTrack
Sign in Get early access

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 2024
2020 2021 2022 2023 2024 2025 2026
Release Pre-release

Releases

latest 21
  1. 1.1.0 30 Aug 2024
    Release notes
    • Allow .letOrNull((pick) => null) to return null without manually setting a nullable type #61
    • CI 2024 update
    Open source →
    Release notes
    • Allow .letOrNull((pick) => null) to return null without manually setting a nullable type #61
    • CI 2024 update
    Open source →
  2. 1.0.0 19 Mar 2023
    Release notes
    • Remove long deprecated methods: addContext, asBool, asDateTime, asDouble, asInt, asList, asMap, asString. Use their as*OrThrow replacements.
    • Add support for timezones in asDateTime* methods #47, #51
    • Add official support for date formats RFC 3339, RFC 2822 and RFC 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)
    
    Open source →
    Release notes
    • Remove long deprecated methods: addContext, asBool, asDateTime, asDouble, asInt, asList, asMap, asString. Use their as*OrThrow replacements.
    • Add support for timezones in asDateTime* methods #47, #51
    • Add official support for date formats RFC 3339, RFC 2822 and RFC 1036
    • Push test coverage to 100% 🤘
    Open source →
  3. 0.10.0 01 Nov 2021
    Release notes
    • New: Support for more date formats. asDateTime* received an optional format parameter. By default, all possible formats will be parsed. To the existing ISO 8601 format, RFC 1123, RFC 850 and asctime have been added which are typically used for the HTTP header or cookies.
    • Documentation added for asDouble and asMap
    Open source →
    Release notes
    • New: Support for more date formats. asDateTime* received an optional format parameter. By default, all possible formats will be parsed. To the existing ISO 8601 format, RFC 1123, RFC 850 and asctime have been added which are typically used for the HTTP header or cookies.
    • Documentation added for asDouble and asMap
    Open source →
  4. 0.9.0 02 Aug 2021
    Release notes
    • New: pickFromJson(json, args...) allows parsing of a json String, without manually calling jsonDecode #41

    • New: pickDeep(json, 'some.key.inside.the.object'.split('.')) allows picking with a dynamic depth #40

    • Add Pick.index to get the element index for list items #38

      pick(["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 new roundDouble or truncateDouble parameters is true #37. Thx @stevendz

    • Add dartdoc to asList*() extensions

    Open source →
    Release notes
    • New: pickFromJson(json, args...) allows parsing of a json String, without manually calling jsonDecode #41

    • New: pickDeep(json, 'some.key.inside.the.object'.split('.')) allows picking with a dynamic depth #40

    • Add Pick.index to get the element index for list items #38

      pick(["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 new roundDouble or truncateDouble parameters is true #37. Thx @stevendz

    • Add dartdoc to asList*() extensions

    Open source →
  5. 0.8.0 14 Feb 2021
    Release notes
    • Deprecated parsing extensions of RequiredPick to 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 dynamic with Object where possible
    • Rename Pick.location() to Pick.debugParsingExit
    • Removal of PickLocaiton and PickContext mixins. They are now part of Pick
    • RequiredPick now extends Pick making it easier to write parsers for custom types

    This release is available as backport for Dart <2.12 with version 0.6.10

    Open source →
    Release notes
    • Deprecated parsing extensions of RequiredPick to 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 dynamic with Object where possible
    • Rename Pick.location() to Pick.debugParsingExit
    • Removal of PickLocaiton and PickContext mixins. They are now part of Pick
    • RequiredPick now extends Pick making it easier to write parsers for custom types
    Open source →
  6. 0.7.0 09 Feb 2021
    Release notes

    Enable nullsafety (requires Dart >=2.12)

    Open source →
    Release notes
    • Enable nullsafety (requires Dart >=2.12)
    Open source →
  7. 0.6.10 14 Feb 2021
    Release notes

    Backports 0.8.0 to pre-nullsafety

    Open source →
    Release notes

    Backports 0.8.0 to pre-nullsafety

    Open source →
  8. 0.6.0 09 Feb 2021
    Release notes

    API changes

    • Remove long deprecated parseJsonTo* methods. Use the pick(json, args*) api

    • New asXyzOrThrow() methods as shorthand for .required().asXyz() featuring better error messages

      • asBoolOrThrow()
      • asDateTimeOrThrow()
      • asDoubleOrThrow()
      • asIntOrThrow()
      • letOrThrow()
      • asListOrThrow()
      • asMapOrThrow()
      • asStringOrThrow()
    • New Pick.isAbsent getter to check if a value is absent or null #24. Absent could mean

      1. Accessing a key which doesn't exist in a Map
      2. Reading the value from List when the index is greater than the length
      3. Trying to access a key in a Map but the found data a Object which isn't a Map
    • New RequiredPick.nullable() converting a RequiredPick back to a Pick with potential null value

    • New PickLocation.followablePath. While PickLocation.path contains the full path to the value, followablePath contains only the part which could be followed with a non-nullable value

    • Breaking asList*() now requires the mapping function.

    • Breaking asList*() now ignores null values when parsing. The map function now receives a RequiredPick as fist parameter instead of a Pick with a potential null value, making parsing easier.

      Therefore pick().required().asList((RequiredPick pick) => /*...*/) only maps non-nullable values. When your lists contain null it will be ignored. This is fine in most cases and simplifies the map function.

      In rare cases, where your lists contain null values with meaning, use the second parameter whenNull to map those null values .asList((pick) => Person.fromPick(pick), whenNull: (Pick it) => null). The function still receives a Pick which gives access to the context api or the PickLocation. But the Pick never holds any value.

    Parsing changes

    • The String "true" and "false" are now parsed as boolean

    • 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

    Open source →
  9. 0.6.0-nullsafety.2 09 Feb 2021 pre-release
    Release notes
    • Breaking asList*() methods now ignore null values. The map function now receives a RequiredPick as fist parameter instead of a Pick making parsing easier.

      Therefore pick().required().asList((RequiredPick pick) => /*...*/) only maps non-nullable values. When your lists contain null it will be ignored.
      This is fine in most cases and simplifies the map function.

      In rare cases, where your lists contain null values with meaning, use the second parameter whenNull to map those null values .asList((pick) => Person.fromPick(pick), whenNull: (Pick it) => null). The function still receives a Pick which gives access to the context api or the PickLocation. But the Pick never 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 a RequiredPick back to a Pick with potential null value

    • New PickLocation.followablePath. While PickLocation.path contains the full path to the value, followablePath contains only the part which could be followed with a non-nullable value

    Open source →
    Release notes
    • Breaking asList*() methods now ignore null values. The map function now receives a RequiredPick as fist parameter instead of a Pick making parsing easier.

      Therefore pick().required().asList((RequiredPick pick) => /*...*/) only maps non-nullable values. When your lists contain null it will be ignored. This is fine in most cases and simplifies the map function.

      In rare cases, where your lists contain null values with meaning, use the second parameter whenNull to map those null values .asList((pick) => Person.fromPick(pick), whenNull: (Pick it) => null). The function still receives a Pick which gives access to the context api or the PickLocation. But the Pick never 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 a RequiredPick back to a Pick with potential null value

    • New PickLocation.followablePath. While PickLocation.path contains the full path to the value, followablePath contains only the part which could be followed with a non-nullable value

    Open source →
  10. 0.6.0-nullsafety.1 06 Dec 2020 pre-release
    Release notes
    • New asXyzOrThrow() methods as shorthand for .required().asXyz() featuring better error messages
      • asBoolOrThrow()
      • asDateTimeOrThrow()
      • asDoubleOrThrow()
      • asIntOrThrow()
      • letOrThrow()
      • asListOrThrow()
      • asMapOrThrow()
      • asStringOrThrow()
    • New Pick.isAbsent getter to check if a value is absent or null #24. Absent could mean
      1. Accessing a key which doesn't exist in a Map
      2. Reading the value from List when the index is greater than the length
      3. Trying to access a key in a Map but the found data a Object which isn't a Map
    • The String "true" and "false" are now parsed as boolean
    • More nnbd refactoring
    Open source →
    Release notes
    • New asXyzOrThrow() methods as shorthand for .required().asXyz() featuring better error messages
      • asBoolOrThrow()
      • asDateTimeOrThrow()
      • asDoubleOrThrow()
      • asIntOrThrow()
      • letOrThrow()
      • asListOrThrow()
      • asMapOrThrow()
      • asStringOrThrow()
    • New Pick.isAbsent getter to check if a value is absent or null #24. Absent could mean
      1. Accessing a key which doesn't exist in a Map
      2. Reading the value from List when the index is greater than the length
      3. Trying to access a key in a Map but the found data a Object which isn't a Map
    • The String "true" and "false" are now parsed as boolean
    • More nnbd refactoring
    Open source →
  11. 0.6.0-nullsafety.0 23 Nov 2020 pre-release
    Release notes
    • Migrate to nullsafety (required Dart >=2.12)
    • Remove deprecated long deprecated parseJsonTo* methods. Use the pick(json, args*) api
    • Improve dartdoc
    Open source →
    Release notes
    • Migrate to nullsafety (required Dart >=2.12)
    • Remove long deprecated parseJsonTo* methods. Use the pick(json, args*) api
    • Improve dartdoc
    Open source →
  12. 0.5.1 04 Sep 2020
    Release notes
    • Rename Pick.addContext to Pick.withContext using deprecation
    • Pick.fromContext now accepts 10 arguments for nested structures
    • Fix Pick.fromContext always returning context not the value for key in context Map
    Open source →
  13. 0.5.0 31 Aug 2020
    Release notes
    • New context API. You can now attach relevant additional information for parsing directly to the Pick object. This allows passing information into fromPick constructors 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: Pick and RequiredPick have chained their constructor signature. path is now a named argument and context has been added.

    - RequiredPick(this.value, [this.path = const []])
    + RequiredPick(this.value, {this.path = const [], Map<String, dynamic> context})
    
    • The path is now correctly forwarded after Pick#call or Pick#asListOrEmpty and always shows the full path since origin
    Open source →
  14. 0.4.3 19 Aug 2020
    Release notes
    • 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
    Open source →
  15. 0.4.2 17 Mar 2020
    Release notes
    • Fix error reporting of asListOrNull(mapToUser) and asListOrEmpty(mapToUser). Both now return errors during mapping and don't swallow them
    Open source →
  16. 0.4.1 07 Feb 2020
    Release notes
    • Print correct path in error message when json is null
    • asDateTime() now skips parsing when the value is already a DateTime
    Open source →
  17. 0.4.0 08 Nov 2019
    Release notes

    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

    Pick now offers a new required() method returning a RequiredPick. It makes sure the picked value exists or crashes if it is null. Because it can't be null, RequiredPick doesn'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 3
    

    Note: Calling .asString() directly on Pick has been deprecated. You now have to call required() first to convert the Pick to a RequiredPick or use a mapping method with fallbacks.

    Pick deeper

    Ever got a Pick/RequiredPick and you wanted to pick even further. This is now possible with the call method. 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 return Map<dynamic, dynamic> (was Map<String, dynamic>)

    Also the lib has been converted to use static extension methods which were introduced in Dart 2.6

    Open source →
  18. 0.3.0 21 Oct 2019
    Release notes

    asMap now expects the key type, defaults to dynamic instead of String

    -Pick.asMap(): Map<String, dynamic>
    +Pick.asMap<T>(): Map<T, dynamic>
    
    Open source →
  19. 0.2.0 27 Sep 2019
    Release notes

    New API! The old parse* methods are now deprecated, but still work. Replace them with the new pick(json, arg0-9...) method.

    - final name = parseJsonToString(json, 'shoes', 0, 'name');
    + final name = pick(json, 'shoes', 0, 'name').asString();
    

    pick returns a Pick which 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()
    
    Open source →
  20. 0.1.1 17 Jul 2019
    Release notes
    • pubspec description updated
    Open source →
  21. 0.1.0 17 Jul 2019
    Release notes
    • Initial version
    Open source →

Every package, every release, already written down.

The archive is open and free. Watching your own project is what we are building next.

Browse the archive