Git Product home page Git Product logo

jessie's Introduction

RFC 9535 - JSONPath: Query Expressions for JSON in Dart

Pub Package GitHub Issues GitHub Forks GitHub Stars GitHub License

import 'dart:convert';

import 'package:json_path/json_path.dart';

void main() {
  final json = jsonDecode('''
{
  "store": {
    "book": [
      {
        "category": "reference",
        "author": "Nigel Rees",
        "title": "Sayings of the Century",
        "price": 8.95
      },
      {
        "category": "fiction",
        "author": "Evelyn Waugh",
        "title": "Sword of Honour",
        "price": 12.99
      },
      {
        "category": "fiction",
        "author": "Herman Melville",
        "title": "Moby Dick",
        "isbn": "0-553-21311-3",
        "price": 8.99
      },
      {
        "category": "fiction",
        "author": "J. R. R. Tolkien",
        "title": "The Lord of the Rings",
        "isbn": "0-395-19395-8",
        "price": 22.99
      }
    ],
    "bicycle": {
      "color": "red",
      "price": 19.95
    }
  }
}  
  ''');

  final prices = JsonPath(r'$..price');

  print('All prices in the store:');

  /// The following code will print:
  ///
  /// $['store']['book'][0]['price']:	8.95
  /// $['store']['book'][1]['price']:	12.99
  /// $['store']['book'][2]['price']:	8.99
  /// $['store']['book'][3]['price']:	22.99
  /// $['store']['bicycle']['price']:	19.95
  prices
      .read(json)
      .map((match) => '${match.path}:\t${match.value}')
      .forEach(print);
}

This library fully implements the RFC 9535 JsonPath specification. It also should pass the latest version of the Compliance Test Suite. If you find a missing or incorrectly implemented feature, please open an issue.

Data manipulation

Each JsonPathMatch produced by the .read() method contains the .pointer property which is a valid JSON Pointer and can be used to alter the referenced value. If you only need to manipulate JSON data, check out my JSON Pointer implementation.

User-defined functions

The JSONPath parser may be extended with user-defined functions. The user-defined functions take precedence over the built-in ones specified by the standard. Currently, only functions of 1 and 2 arguments are supported.

To create your own function:

  1. Import package:json_path/fun_sdk.dart.
  2. Create a class implementing either Fun1 (1 argument) or Fun2 (2 arguments).

To use it:

  1. Create a new JsonPathParser with your function: final parser = JsonPathParser(functions: [MyFunction()]);
  2. Use it to parse you expression: final jsonPath = parser.parse(r'$[?my_function(@)]');

For more details see the included example.

This package comes with some non-standard functions which you might find useful. To use them, import package:json_path/fun_extra.dart.

References

jessie's People

Contributors

dependabot[bot] avatar f3ath avatar matthiee avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

jessie's Issues

Results do not match other implementations

The following queries provide results that do not match those of other implementations of JSONPath
(compare https://cburgmer.github.io/json-path-comparison/):

  • $[:] (#12)
    Input:

    [
      "first",
      "second"
    ]
    

    Expected output:

    ["first", "second"]
    

    Actual output:
    NOT_SUPPORTED

    FormatException: Unexpected bracket expression
    
  • $..[0] (#13)
    Input:

    [
      "first",
      {
        "key": [
          "first nested",
          {
            "more": [
              {
                "nested": [
                  "deepest",
                  "second"
                ]
              },
              [
                "more",
                "values"
              ]
            ]
          }
        ]
      }
    ]
    

    Expected output (in any order as no consensus on ordering exists):

    ["deepest", "first nested", "first", "more", {"nested": ["deepest", "second"]}]
    

    Error:

    type 'List<dynamic>' is not a subtype of type 'Iterable<JsonPathMatch<dynamic>>'
    
  • $["key"]
    Input:

    {
      "key": "value"
    }
    

    Expected output:

    ["value"]
    

    Actual output:
    NOT_SUPPORTED

    FormatException: Unexpected bracket expression
    
  • $[""]
    Input:

    {
      "": 42,
      "''": 123,
      "\"\"": 222
    }
    

    Expected output:

    [42]
    

    Actual output:
    NOT_SUPPORTED

    FormatException: Empty brackets
    
  • $[-1] (#14)
    Input:

    [
      "first",
      "second",
      "third"
    ]
    

    Expected output:

    ["third"]
    

    Error:

    RangeError (index): Invalid value: Not in inclusive range 0..2: -1
    
  • $[0] (#15)
    Input:

    {
      "0": "value"
    }
    

    Error:

    type 'List<dynamic>' is not a subtype of type 'Iterable<JsonPathMatch<dynamic>>'
    
  • $[0] (#16)
    Input:

    "Hello World"
    

    Expected output:

    []
    

    Error:

    type 'List<dynamic>' is not a subtype of type 'Iterable<JsonPathMatch<dynamic>>'
    
  • $['single'quote']
    Input:

    {
      "single'quote": "value"
    }
    

    Expected output:

    NOT_SUPPORTED
    

    Actual output:

    []
    
  • $['two'.'some']
    Input:

    {
      "one": {
        "key": "value"
      },
      "two": {
        "some": "more",
        "key": "other value"
      },
      "two.some": "42",
      "two'.'some": "43"
    }
    

    Expected output:

    NOT_SUPPORTED
    

    Actual output:

    [
      {
        "key": "other value",
        "some": "more"
      }
    ]
    
  • $[two.some]
    Input:

    {
      "one": {
        "key": "value"
      },
      "two": {
        "some": "more",
        "key": "other value"
      },
      "two.some": "42"
    }
    

    Expected output:

    NOT_SUPPORTED
    

    Actual output:

    [
      {
        "key": "other value",
        "some": "more"
      }
    ]
    
  • $..[*]
    Input:

    {
      "key": "value",
      "another key": {
        "complex": "string",
        "primitives": [
          0,
          1
        ]
      }
    }
    

    Expected output (in any order as no consensus on ordering exists):

    ["string", "value", 0, 1, [0, 1], {"complex": "string", "primitives": [0, 1]}]
    

    Actual output:

    [
      0,
      1
    ]
    
  • $[*]
    Input:

    {
      "some": "string",
      "int": 42,
      "object": {
        "key": "value"
      },
      "array": [
        0,
        1
      ]
    }
    

    Expected output (in any order as no consensus on ordering exists):

    ["string", 42, [0, 1], {"key": "value"}]
    

    Actual output:

    []
    
  • $.[key]
    Input:

    {
      "key": "value",
      "other": {
        "key": [
          {
            "key": 42
          }
        ]
      }
    }
    

    Expected output:

    NOT_SUPPORTED
    

    Actual output:

    []
    
  • $.
    Input:

    {
      "key": 42,
      "": 9001,
      "''": "nice"
    }
    

    Expected output:

    NOT_SUPPORTED
    

    Actual output:

    [
      {
        "": 9001,
        "''": "nice",
        "key": 42
      }
    ]
    
  • $.屬性
    Input:

    {
      "\u5c6c\u6027": "value"
    }
    

    Expected output:

    ["value"]
    

    Actual output:

    [
      {
        "\u5c6c\u6027": "value"
      }
    ]
    
  • $[?(@.key=='value')]
    Input:

    [
      {
        "key": "some"
      },
      {
        "key": "value"
      }
    ]
    

    Expected output:

    [{"key": "value"}]
    

    Actual output:
    NOT_SUPPORTED

    FormatException: Filter not found: "."
    
  • $(key,more)
    Input:

    {
      "key": 1,
      "some": 2,
      "more": 3
    }
    

    Expected output:

    NOT_SUPPORTED
    

    Actual output:

    []
    
  • $[0,0]
    Input:

    [
      "a"
    ]
    

    Expected output:

    ["a", "a"]
    

    Actual output:

    [
      "a"
    ]
    
  • $[4,1]
    Input:

    [
      1,
      2,
      3,
      4,
      5
    ]
    

    Expected output:

    [5, 2]
    

    Actual output:

    [
      2,
      5
    ]
    
  • $[*,1]
    Input:

    [
      "first",
      "second",
      "third",
      "forth",
      "fifth"
    ]
    

    Expected output:

    NOT_SUPPORTED
    

    Actual output:

    []
    

For reference, the output was generated by the program in https://github.com/cburgmer/json-path-comparison/tree/master/implementations/Dart_json_path.

Separate Match from Node

Match - a user-facing wrapper over a matching node. A match has: value, path, pointer, key/index.
Node - a json node representation for (custom) functions.

Please unpublish 0.4.3 and republish as 0.5.0

json_path 0.4.3 suggest it's a non-breaking upgrade from 0.4.2, but that's not actually the case. The version 0.4.2 worked with petitparser 5.1.0, but 0.4.3 requires 5.2.0+.

That's a problem because petitparser 5.1.0 depends on meta 1.8.0 (the one currently in Flutter stable), but 5.2.0+ depends on meta 1.9.0. This makes petitparser 5.2.0+ unable to be used in any application on Flutter stable, which also makes 0.4.2 Flutter compatible and 0.4.3 as non-Flutter compatible.

Ideally when there's a breaking change that should be noted in the semver so users aren't automatically upgraded to a broken state.

I tried contacting the author of petitparser about the issue via: petitparser/dart-petitparser#144

Someone else tried contacting the Flutter folks about this same issue: flutter/flutter#121391

They both collectively gave a ¯\_(ツ)_/¯. I'm hoping for a more helpful / positive outcome here.

Running "flutter pub get" problem

To Reproduce (i.e. user steps, not code)
Steps to reproduce the behavior:

Go to ' terminal make flutter upgrade be sure the Version is 2.10.4 on channel stable'
Click on 'run flutter pub get'
See error
Error messages

What went wrong:
Because every version of flutter_test from sdk depends on collection 1.15.0 and xml >=5.4.0 depends on collection ^1.16.0, flutter_test from sdk is incompatible with xml >=5.4.0.
And because flutter_native_splash >=1.3.0 depends on xml ^5.3.1, if flutter_test from sdk and flutter_native_splash >=1.3.0 then xml >=5.3.1 <5.4.0.
And because xml >=5.3.0 <5.4.0 depends on petitparser ^4.3.0 and json_path 0.4.0 depends on petitparser ^5.0.0, one of flutter_test from sdk or flutter_native_splash >=1.3.0 or json_path 0.4.0 must be false.
And because no versions of json_path match >0.4.0 <0.5.0 and flutter_project depends on json_path ^0.4.0, flutter_test from sdk is incompatible with flutter_native_splash >=1.3.0.
So, because flutter_project depends on both flutter_native_splash ^2.0.4 and flutter_test from sdk, version solving failed.
pub get failed (1; So, because flutter_project depends on both flutter_native_splash ^2.0.4 and flutter_test from sdk, version solving failed.)

Expected behavior
i am Expecting my app to run without any problem

Screenshots
If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

OS: [e.g. MacOS Big Sur + 11.6.2]
Browser [e.g. chrome + 99.0.4844.82]
Smartphone (please complete the following information):

Device: [e.g. Pixel 3 a]
OS: [e.g. Android Tiramisu]
Flutter SDK version
environment:
sdk: ">=2.16.1 <3.0.0"

Flutter 2.10.3 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 7e9793dee1 (3 weeks ago) • 2022-03-02 11:23:12 -0600
Engine • revision bd539267b4
Tools • Dart 2.16.1 • DevTools 2.9.2

insert output of "flutter doctor -v" here
[✓] Flutter (Channel stable, 2.10.4, on macOS 11.6.2 20G314 darwin-x64, locale en-TR)
• Flutter version 2.10.4 at /Users/imac/flutterDevelopment/flutter
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision c860cba910 (7 days ago), 2022-03-25 00:23:12 -0500
• Engine revision 57d3bac3dd
• Dart version 2.16.2
• DevTools version 2.9.2

[✓] Android toolchain - develop for Android devices (Android SDK version 32.1.0-rc1)
• Android SDK at /Users/imac/Library/Android/sdk
• Platform android-32, build-tools 32.1.0-rc1
• Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 11.0.11+0-b60-7590822)
• All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 13.2.1)
• Xcode at /Applications/Xcode.app/Contents/Developer
• CocoaPods version 1.11.3

[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2021.1)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 11.0.11+0-b60-7590822)

[✓] VS Code (version 1.66.0)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.36.0

[✓] Connected device (4 available)
• SM A125F (mobile) • R58R21ZSWAR • android-arm64 • Android 11 (API 30)
• iPhone 13 Pro (mobile) • 4326275E-EB0C-4C06-A7B2-B30861DE3A38 • ios • com.apple.CoreSimulator.SimRuntime.iOS-15-2 (simulator)
• macOS (desktop) • macos • darwin-x64 • macOS 11.6.2 20G314 darwin-x64
• Chrome (web) • chrome • web-javascript • Google Chrome 100.0.4896.60
! Error: iPhone is not connected. Xcode will continue when iPhone is connected. (code -13)

[✓] HTTP Host Availability
• All required HTTP hosts are available

• No issues found!

Additional context
I am trying to use json_path on last version of flutter
Because every version of flutter_test from sdk depends on collection 1.15.0 and xml >=5.4.0 depends on collection ^1.16.0, flutter_test from sdk is incompatible with xml >=5.4.0.
And because flutter_native_splash >=1.3.0 depends on xml ^5.3.1, if flutter_test from sdk and flutter_native_splash >=1.3.0 then xml >=5.3.1 <5.4.0.
And because xml >=5.3.0 <5.4.0 depends on petitparser ^4.3.0 and json_path 0.4.0 depends on petitparser ^5.0.0, one of flutter_test from sdk or flutter_native_splash >=1.3.0 or json_path 0.4.0 must be false.
And because no versions of json_path match >0.4.0 <0.5.0 and flutter_project depends on json_path ^0.4.0, flutter_test from sdk is incompatible with flutter_native_splash >=1.3.0.
So, because flutter_project depends on both flutter_native_splash ^2.0.4 and flutter_test from sdk, version solving failed.
pub get failed (1; So, because flutter_project depends on both flutter_native_splash ^2.0.4 and flutter_test from sdk, version solving failed.)

is there any solution

Note: when deleting one of json_path from pubspec.yaml the app run without any problem

Filtering doesn't work?

I'm trying to use a filter:

 JsonPath(r'$.metadata.realm', filter: {
      'realm': (e) {
        _log.finer('filtered $e');
        return true;
      }
    })

I find that the filter test never gets invoked, even thought the json contains a realm expression:

FINER: 2020-08-25 18:39:38.536755: $['metadata']['realm']:	/

Maybe a doc issue?

Filter with subquery throws FormatException

I'm unable to run JsonPaths that contain a filter with a subquery similar to example.dart Line 79:

JsonPath(r'$.store.book[[email protected] == $.store.book[-1].category].title')

When running this example against v0.4.4 it fails with the same FormatException as it does in my own code

FormatException (FormatException: end of input expected at 1:13. Expression: $.store.book[[email protected] == $.store.book[-1].category].title)

Any idea what's wrong?

Btw, thanks a lot for this truly awesome library!

Error on Build

Thankyou for wonderful plugin, but i occured problem when build in flutter 3.7.10. The error say like this :

Target dart2js failed: Exception: Warning: The 'dart2js' entrypoint script is deprecated, please use 'dart compile js' instead.
../../../.pub-cache/hosted/pub.dev/json_path-0.5.3/lib/src/grammar/strings.dart:43:51:
Error: The method 'timesString' isn't defined for the class 'Parser<String>'.
 - 'Parser' is from 'package:petitparser/src/core/parser.dart' ('../../../.pub-cache/hosted/pub.dev/petitparser-5.1.0/lib/src/core/parser.dart').
final _unicodeSymbol = (string(r'\u') & _hexDigit.timesString(4))

[*] wildcard

Hi, is there a way I can make $.store.book[*].author work with this lib?

When I use $.store.book[*] it gives me the objects but i'd like to select all the author inside all the selected objects.

Thank you

end of input expected at 1:2 for Expression: $.[*].value

Hi @f3ath, thanks for the library.

I'm receiving this error,

end of input expected at 1:2. Expression: $.[*].value

The relevant error-causing widget was: 
 ...
When the exception was thrown, this was the stack: 
#0      JsonPath._parse (package:json_path/src/json_path.dart:41:7)
#1      new JsonPath (package:json_path/src/json_path.dart:35:21)

Code:

final json = jsonDecode('''
[{"value": "HELLEBORUS BERBERIS SPECIAL ORDER"}, {"value": "HELLEBORUS COMP. A"}, {"value": "HELLEBORUS COMP. B"}, {"value": "HELLEBORUS COMP. C"}, {"value": "HELLEBORUS COMP. D"}]
  ''');

    final prices = JsonPath(r'$.[*].value');
    var val=prices.read(json);
    for (var element in val) {
      print("value>> "+element.value.toString());
      print("path>> "+element.path.toString());
      print("pointer>> "+element.pointer.toString());
    }

But this works here in the online evaluator for json path
https://jsonpath.com/

I believe there is a case that have been missed during pepitparser expression creation in this library.

Upgrading of petitparser

Would you consider upgrading the petitparser to the ver 5.0.0? In my project (an I am sure in many other projects) there are two libraries that use petitparser one of them (xml) is on the latest version of it and json_path still on 4.0.0.
IT appears there have been some breaking changes in the latest petitparser because if I force its latest version be used the json_path will not compile.

Consider implementing RFC 9535

IETF RFC 9535 defines a proposed standard for JSONPath. Other resources:

  • A partial Compliance Test Suite.
  • Behaviours of various implementations can be checked in the comparison project. Please note that the JSONPath Reference Implementation referenced in the comparison project is stalled/archived and incomplete.
  • At the time of writing, online sandboxes for RFC 9535 are available in C# and in Rust.
  • For more background and comments on the status of the CTS and RI, see this this post (also here in the IETF blog).
  • Public discussion occurs in the IETF JSONPath Working Group's mailing list (archive).

(See here for updates to this list of resources.)

Valid approaches for this project are to (a) implement the RFC in whole or in part, (b) document its behaviour relative to the RFC, and (c) do nothing.

Adapting json_path

Hello! Thanks so much for this package. I'm somewhat new to path-based navigation, so I was hoping I could ask for some help. I work with a data format called FHIR (https://www.hl7.org/fhir/overview.html). It's all json based. There is another specification called FHIRPath (http://hl7.org/fhirpath/), which is a path based navigation and extraction language. It is similar to XPath, and it certainly appears similar to JSONPath. However, it does have some idiosyncracies. Do you think I could implement these requirements using this package, or do you think I need to use petitparser and build it from the ground up?

Support for [*]

Hi, i'm wondering if you plan to support the [*] in your library. Currently we have this JSON:

{
	"key": "value",
	"PasswordList": [
		{
			"SafePassword": "<data_that_i_want>"
		}
	],
	"key2": "value2"
}

We are unable to get the value of the "SafePassword" key. We tried:

$.PasswordList[*].SafePassword

but it doesn't work.

Is there a way to achieve this?

Thank you!

Can't access properties with "-"

It fails to parse JSON paths with -s.

Example code:

  final json = jsonDecode('''
{
  "with-dash": "with-dash-val",
  "nodash": "no-dash-val"
}
''');
  print('No dash:');
  // (no-dash-val)
  print(JsonPath('\$.nodash').read(json).map((e) => e.value));

  print('With dash:');
  // Instance of 'ParserException': end of input expected (at 1:2)
  // This worked in 0.4.1
  print(JsonPath('\$.with-dash').read(json).map((e) => e.value));

I'm not sure if $.with-dash is a valid path, but every JSON path implementation I tried supports it, e.g. https://jsonpath.com/.

Failed to build iOS app

And here's the message:

Launching lib/main_basic.dart on iPhone 13 in debug mode...
Running Xcode build...
Xcode build done. 26.5s
Failed to build iOS app
Error (Xcode): ../../.pub-cache/hosted/pub.dev/json_path-0.4.3/lib/src/grammar/expression.dart:40:7: Error: The method 'primitive' isn't defined for the class 'ExpressionBuilder<dynamic Function(JsonPathMatch)>'.

Could not build the application for the simulator.
Error launching application on iPhone 13.

Import conflict since 0.3.1 in package:json_path/src/selector/expression_filter.dart

I'm getting such a problems when running newest version of that library.
Downgrading it to 0.3.0 fixes the problems.

: Error: 'Predicate' is imported from both 'package:json_path/src/selector/expression_filter.dart' and 'package:petitparser/src/parser/predicate/predicate.dart'.
../…/grammar/expression.dart:5
import 'package:petitparser/petitparser.dart';
package:petitparser/petitparser.dart:1
^^^^^^^^^

: Error: The argument type 'ExpressionFilter Function(bool Function(JsonPathMatch))' can't be assigned to the parameter type 'dynamic Function(dynamic)'.
../…/grammar/selector.dart:41
- 'ExpressionFilter' is from 'package:json_path/src/selector/expression_filter.dart' ('../../../../.pub-cache/hosted/pub.dartlang.org/json_path-0.3.1/lib/src/selector/expression_filter.dart').
package:json_path/…/selector/expression_filter.dart:1
- 'JsonPathMatch' is from 'package:json_path/src/json_path_match.dart' ('../../../../.pub-cache/hosted/pub.dartlang.org/json_path-0.3.1/lib/src/json_path_match.dart').
package:json_path/src/json_path_match.dart:1
        expression.map(ExpressionFilter.new))

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.