{"id":24813741,"url":"https://github.com/quincyjo/scala-json-path","last_synced_at":"2026-05-02T09:33:23.915Z","repository":{"id":213387397,"uuid":"734020018","full_name":"quincyjo/scala-json-path","owner":"quincyjo","description":"Scala library for programmatic integration with JsonPaths, including modeling, serialization, parsing, and evaluation.","archived":false,"fork":false,"pushed_at":"2025-02-06T23:49:23.000Z","size":244,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-07T00:25:07.503Z","etag":null,"topics":["json","json-path","scala"],"latest_commit_sha":null,"homepage":"","language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/quincyjo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-12-20T17:06:07.000Z","updated_at":"2025-02-06T23:49:27.000Z","dependencies_parsed_at":"2023-12-29T01:28:02.840Z","dependency_job_id":"3bebd969-34a3-491a-9dbc-48464acda4ac","html_url":"https://github.com/quincyjo/scala-json-path","commit_stats":null,"previous_names":["verbetam/scaka-json-path","verbetam/scala-json-path"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quincyjo%2Fscala-json-path","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quincyjo%2Fscala-json-path/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quincyjo%2Fscala-json-path/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/quincyjo%2Fscala-json-path/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/quincyjo","download_url":"https://codeload.github.com/quincyjo/scala-json-path/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245517629,"owners_count":20628377,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["json","json-path","scala"],"created_at":"2025-01-30T15:51:54.885Z","updated_at":"2026-05-02T09:33:23.896Z","avatar_url":"https://github.com/quincyjo.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"# scala-json-path\n\n`scala-json-path` is a Scala library for the usage of [JSONPath](https://datatracker.ietf.org/doc/rfc9535) built\non [Cats](https://typelevel.org/cats/) and [Braid](https://github.com/quincyjo/braid) that is exception free and fully\n[RFC 9535](https://datatracker.ietf.org/doc/rfc9535) compliant.\nThis library provides a direct ADT for modeling JSONPaths with support for serialization, parsing and evaluation.\nEvaluation is implemented generically against any underlying JSON library\nvia [Braid](https://github.com/quincyjo/braid).\n\n## Getting Started\n\nTo get started, you can add play-json as a dependency in your project:\n\n* sbt\n  ```\n  libraryDependencies += \"com.quincyjo\" %% \"scala-json-path\" % -version-\n  ```\n* Gradle\n  ```\n  compile group: 'com.quincyjo', name: 'scala-json-path_2.13', version: -version-\n  ```\n* Maven\n  ```xml\n  \u003cdependency\u003e\n    \u003cgroupId\u003ecom.quincyjo\u003c/groupId\u003e\n    \u003cartifactId\u003escala-json-path_2.13\u003c/artifactId\u003e\n    \u003cversion\u003e-version-\u003c/version\u003e\n  \u003c/dependency\u003e\n  ```\n\nSee [GitHub releases](https://github.com/quincyjo/scala-json-path/releases) for the correct version.\n\nScala Json Path interfaces with the underlying JSON library generically via [Braid](https://github.com/quincyjo/braid).\nA `JsonPathEvaluator` can be defined for any `Json` type that has an implicit `Braid` in scope for it.\n\nThere are also several pre-defined `JsonPathEvaluator` implementations for common JSON libraries as listed before.\n\n* Modules\n  ```\n  libraryDependencies += \"com.quincyjo\" %% \"scala-json-path-circe\" % -version-\n  libraryDependencies += \"com.quincyjo\" %% \"scala-json-path-play\" % -version-\n  ```\n\n## Usage\n\n### Direct Modeling\n\nJSONPaths may be defined using the ADT API directly, or via a simple DSL.\n\n`JsonPath` has two subtypes, `JsonPath.Query` and `JsonPath.SingularQuery`. The first represents a query which may\nresolve to more than one node, and the second is guaranteed to resolve to at most one node. `JsonPath.Query` is not\ndirectly constructable, but the `JsonPath` model handles switching between the two as it is built.\n\n\u003c!-- @formatter:off --\u003e\n```scala\nscala\u003e JsonPath.$ / \"foobar\" / 5 \nval res0: com.quincyjo.jsonpath.JsonPath.SingularQuery = $['foobar'][5]\n\nscala\u003e JsonPath.$ / Wildcard / Slice.take(3)\nval res1: com.quincyjo.jsonpath.JsonPath.Query = $[*][:3]\n\nscala\u003e JsonPath.`@` */ Wildcard // \u003c-- Recursive descent DSL\nval res2: com.quincyjo.jsonpath.JsonPath.Query = @..*\n\nscala\u003e JsonPath.$ /? GreaterThan(Count(JsonPathNodes(JsonPath.`@`)), LiteralNumber(10)) // \u003c-- Filter DSL\nval res3: com.quincyjo.jsonpath.JsonPath.Query = $[?(count(@) \u003e 10)]\n```\n\u003c!-- @formatter:on --\u003e\n\n### Parsing\n\nParsing is provided via `JsonPathReader`, which reads `JsonPath`s from strings. A direct API is also provided via\nthe `parser` package object. Parse results are exposed via the sum of `Parsed[T]` and `ParseError`. This library is\nbuilt on top of Cats, and `ParseResult` is both a `MonadError` and `Traverse`able.\n\n\u003c!-- @formatter:off --\u003e\n```scala\nscala\u003e import com.quincyjo.jsonpath\n\nscala\u003e jsonpath.parser.parse(\"$.foobar[5][-3:][\\\"1\\\",1]\")\nval res0: ParseResult[com.quincyjo.jsonpath.JsonPath] = Parsed($.foobar[5][-3:][\"1\",1])\n\nscala\u003e jsonpath.parser.parse(\"some.invalid.path\")\nval res1: ParseResult[com.quincyjo.jsonpath.JsonPath] = ParseError: Failed to parse JsonPath at index 0 in 'some.invalid.path': A JSON Path must start with either '$' or '@'\n```\n\u003c!-- @formatter:on --\u003e\n\n#### Escape Sequences\n\nParsing and serialization of JSONPaths handles escape sequences as specified\nin [RFC 9535 section 2.3.1.2](https://datatracker.ietf.org/doc/html/rfc9535#section-2.3.1.2). This is mostly the same as\nhow escape sequences are handled in Scala, but with a few differences. Most notably, solidus (`/`) may optionally be\nescaped with a backslash (`\\`) while this is an invalid escape sequence in Scala.\n\nWhen defining a name selector via the ADT, the provided string is accepted as is and is not processed further. If for\nsome reason processing of escapes is required on a `String` in code, the API is exposed via the `StringEscapes` object.\n\n\u003c!-- @formatter:off --\u003e\n```scala\nscala\u003e StringEscapes.processEscapes(s\"\\\\\\\"\") // Literal '\\\"'\nval res0: Either[InvalidStringEncoding, ValueAt[String]] = Right(ValueAt(\",0,\\\"))\n        \nscala\u003e StringEscapes.processEscapes(\"\\\\a\") // Literal '\\a', an invalid escape\nval res1: Either[InvalidStringEncoding, ValueAt[String]] = Left(InvalidStringEncoding: Invalid escape in string '\\a' at index 0)\n\nscala\u003e JsonPathParser.default.parse(\"$['\\\\\\\"']\") // Parse a JSONPath from a string, handling escapes\nval res2: ParseResult[JsonPath] = Parsed($['\"'])\n\nscala\u003e JsonPath.Attribute(\"\\t\") // Raw tab character passed to an Attribute, is not processed.\nval res3: JsonPath.Attribute = '\\t' // \u003c-- toString escapes it.\n\nscala\u003e JsonPath.Attribute(\"\\\\t\") // Raw string of `\\t` is not processed.\nval res4: JsonPath.Attribute = '\\\\t' // \u003c-- Reverse solidus is escaped\n```\n\u003c!-- @formatter:on --\u003e\n\n### Literals\n\nLiteral strings are provided via `jsonpath.literal` package.\n\n\u003c!-- @formatter:off --\u003e\n```scala\nscala\u003e import com.quincyjo.jsonpath.literal.JsonPathStringContext\n\nscala\u003e jsonPath\"\"\"@[1:2:3][\"foobar\"]\"\"\"\nval res0: com.quincyjo.jsonpath.JsonPath = @[1:2:3]['foobar']\n```\n\u003c!-- @formatter:on --\u003e\n\n### Evaluation\n\nEvaluation of a `JsonPath` is performed by a `JsonPathEvaluator`, which is implemented generically via Braid. Once a\n[Braid](https://github.com/quincyjo/braid) is in scope for your JSON library of choice, an evaluator may be defined\nas below:\n\n```scala\nimport JsonBean.jsonBeanBraid // Implicit instance of Braid[JsonBean]\n\nfinal case object JsonBeanEvaluator extends JsonPathEvaluator[JsonBean]\n\n```\n\nEvaluation returns a `List` of the matching nodes of the path in the given JSON. A node is defined as the tuple its\nlocation via a singular query (a JSONPath that points to at most one node) and the value at that location.\n\n\u003c!-- @formatter:off --\u003e\n```scala\nscala\u003e val json = Json.obj(\"foobar\" -\u003e Json.arr(Json.fromString(\"deadbeef\"), Json.Tr ue, Json.fromInt(42)))\nval json: io.circe.Json =\n{\n  \"foobar\" : [\n    \"deadbeef\",\n    true,\n    42\n  ]\n}\n\nscala\u003e CirceEvaluator.evaluate(jsonPath\"$$.foobar\", json)\nval res0: List[com.quincyjo.jsonpath.Node[io.circe.Json]] =\nList(Node($['foobar'],[\n  \"deadbeef\",\n  true,\n  42\n]))\n\nscala\u003e CirceEvaluator.evaluate(jsonPath\"$$.foobar.*\", json)\nval res1: List[com.quincyjo.jsonpath.Node[io.circe.Json]] = List(Node($['foobar'][0],\"deadbeef\"), Node($['foobar'][1],true), Node($['foobar'][2],42))\n\nscala\u003e CirceEvaluator.evaluate(jsonPath\"$$.foobar[-1:]\", json)\nval res2: List[com.quincyjo.jsonpath.Node[io.circe.Json]] = List(Node($['foobar'][2],42))\n\nscala\u003e CirceEvaluator.evaluate(jsonPath\"$$..*\", json)\nval res3: List[com.quincyjo.jsonpath.Node[io.circe.Json]] =\nList(Node($['foobar'],[\n  \"deadbeef\",\n  true,\n  42\n]), Node($['foobar'][0],\"deadbeef\"), Node($['foobar'][1],true), Node($['foobar'][2],42))\n```\n\u003c!-- @formatter:on --\u003e\n\nSingular queries may also be evaluated explicitly via `JsonPathEvaluator.singular`, which returns `Option[Node[Json]]`\ninstead.\n\n## Expressions\n\nExpressions have their own AST which can be used to describe expressions in either JSONPath scripts or filters.\nExpressions are evaluated against a JsonPath context and return a result based on their expression type. Expressions are\nwell typed according to [RFC 9535 section 2.4.3](https://datatracker.ietf.org/doc/html/rfc9535#section-2.4.3), both at\nparse time and via AST declaration.\n\nFunctions are always safe to evaluate, as evaluating a JSONPath is guaranteed to be error free. All error handling is\nhandled when parsing a JSONPath, and thus parsing fails if an expression is malformed.\n\n\u003c!-- @formatter:off --\u003e\n```scala\nscala\u003e jsonPath\"$$[?value(@.foo)]\"\ncom.quincyjo.jsonpath.parser.models.ParseError: Failed to parse JsonPath at index 4 in '$[?value(@.foo)]': Filter requires a logical expression but was: value(@['foo'])\n\nscala\u003e $ /? Value(JsonPathValue(`@` / \"foo\"))\n                 ^\n       error: type mismatch;\n        found   : com.quincyjo.jsonpath.extensions.Value\n        required: com.quincyjo.jsonpath.Expression.LogicalType\n\nscala\u003e jsonPath\"$$[?match(@.name)]\"\ncom.quincyjo.jsonpath.parser.models.ParseError: Failed to parse JsonPath at index 15 in '$[?match(@.name)]': function 'match' expects 2 arguments, but got 1\n\nscala\u003e jsonPath\"$$[?match(@..*, 'deadbeef')]\"\ncom.quincyjo.jsonpath.parser.models.ParseError: Failed to parse JsonPath at index 3 in '$[?match(@..*, 'deadbeef')]': function 'match' invalid argument '@..*': NodesType can only be coerced to ValueType when from a singular query.\n\nscala\u003e $ /? Match(JsonPathNodes(`@` */ Wildcard), LiteralString(\"deadbeef\"))\n                               ^\n       error: type mismatch;\n        found   : com.quincyjo.jsonpath.Expression.JsonPathNodes\n        required: com.quincyjo.jsonpath.Expression.ValueType\n```\n\u003c!-- @formatter:on --\u003e\n\n### Types\n\nAll expressions have a declared type which is one of the following.\n\n- `ValueType`: A JSON atomic literal value. And evaluates to a single JSON value or nothing, which is represented as\n  `Option[Json]` with the `Json` type being determined at evaluation. May be coerced from a singular query.\n- `LogicalType`: Either a logical true or false, which is distinct from JSON booleans. May be coerced from any\n  `NodesType` as an existence check.\n- `NodesType`: Any JSONPath, which evaluates to the matching nodes.\n\nExpressions used in a filter selector must be of type `LogicalType`, and function extensions must have a declared\ntype and their parameters are type-checked during parsing.\n\nThere are implicit `def`s in scope for each type to enable implicit conversions according to the above. These will apply\nautomatically whenever an expression type is used as a parameter. There are also utility methods on relevant types to\nmake this explicit.\n\n\u003c!-- @formatter:off --\u003e\n```scala\nscala\u003e JsonPath.$ /? JsonPathNodes(JsonPath.`@` / \"bar\") // \u003c-- NodesType to Logical Type\nval res0: com.quincyjo.jsonpath.JsonPath.Query = $[?(@['bar'])]\n\nscala\u003e JsonPath.$ /? Equal(JsonPathValue(JsonPath.`@` / \"name\"), LiteralString(\"Jane Doe\")) // \u003c-- NodesType to ValueType\nval res1: com.quincyjo.jsonpath.JsonPath.Query = $[?(@['name'] == \"Jane Doe\")]\n\nscala\u003e JsonPath.$ / \"products\" */ Wildcard /? JsonPathValue(`@` / \"restrictions\").exists\nval res2: com.quincyjo.jsonpath.JsonPath.Query = $['products']..*[?(@['restrictions'])]\n```\n\u003c!-- @formatter:on --\u003e\n\nSyntax implicits are available via `ExpressionsSyntax` to make writing expressions easier.\n\n\u003c!-- @formatter:off --\u003e\n```scala\nscala\u003e import com.quincyjo.jsonpath.syntax.ExpressionSyntax._\nimport com.quincyjo.jsonpath.syntax.ExpressionSyntax._\n\nscala\u003e JsonPath.$ */ \"products\" /? (`@` / \"price\" \u003c 100)\nval res0: com.quincyjo.jsonpath.JsonPath.Query = $..['products'][?(@['price'] \u003c 100)]\n```\n\u003c!-- @formatter:on --\u003e\n\n## Function Extensions\n\nThere is an open trait `FunctionExtension` for defining functions extensions. Any `FunctionExtension` may be used when\ndefining a `JsonPath`, and may be parsed by mixing in a `WithExtension` for the function extension to a parser.\n\n### Default Function Extensions\n\nThe default function extensions as defined\nin [RFC 9535 section 2.4](https://datatracker.ietf.org/doc/html/rfc9535#section-2.4) are enabled in the default\n`JsonPathParser`, `JsonPathParser.default`. A mix-in to add these extensions to any `JsonPathParser` is provided via the\n`StandardExtensions` trait.\n\nThe following extensions are provided by default:\n\n- `Count(NodesType): ValueType`: Counts the number of nodes matched by a given `NodesType`.\n- `Length(ValueType): ValueType`: Returns the length of a given `ValueType` if it is a string, array, or object. Nothing\n  is returned if the\n  operand is not one of the aforementioned types.\n- `Value(NodesType): ValueType`: Converts a `NodesType` to a `ValueType`.\n- `Match(ValueType, ValueType): LogicalType`: Determines if the first parameter as a string matches the second parameter\n  as a regex. If the first parameter is not a string or the second parameter is not a valid regex, then the result is\n  false.\n- `Search(ValueType, ValueType): LogicalType`: Similar to `Match`, but returns true if the first parameter contains a\n  substring which matches the regex.\n\n### Adding Function Extensions\n\nCustom function extensions can be defined as needed. Keep in mind that all JSONPath evaluations have no error state, so\nany custom function extensions must be exception free. A common pattern for invalid arguments is to return `None` in the\ncase of `ValueType` extensions such as the default `Match` and `Search` extensions when the regex parameters is not\nvalid.\n\nThe following example shows how to define a new function extension and add it to a custom parser.\n\nFirst, define the new function extension. This can immediately be used when defining a JSONPath programmatically.\n\n```scala\nfinal case class StringOrNull(value: ValueType)\n  extends FunctionExtension[ValueType]\n    with ValueType {\n\n  override val name: String = StringOrNull.extensionName\n\n  override val args: List[Expression] = List(value)\n\n  override def apply[Json: Braid](\n                                   evaluator: JsonPathEvaluator[Json],\n                                   root: Json,\n                                   current: Json\n                                 ): Option[Json] = Some {\n    value(evaluator, root, current)\n      .filter(Braid[Json].isString)\n      .getOrElse(Braid[Json].Null)\n  }\n}\n\nobject StringOrNull {\n\n  val extensionName: String = \"stringOrNull\"\n\n  val extension: Extension[NodesType, StringOrNull] =\n    Extension(extensionName)(StringOrNull.apply)\n\n  trait StringOrNullExtension extends WithExtension {\n    self: JsonPathParser =\u003e\n\n    addExtension(StringOrNull.extension)\n  }\n}\n\n```\n\nThen mix it in to a custom parser to be able to parse it.\n\n```scala\ncase object MyJsonPathParser\n  extends JsonPathParser\n    with StandardExtensions\n    with StringOrNothingExtension\n\n```\n\n### Arithmetic Operations\n\nArithmetic operations are disabled by default as they are not part of the JSONPath specification. Similar to function\nextensions, they may be enabled via a mix-in. This enables parsing of arithmetic operations including: `+`, `-`, `*`,\nand `/`.\n\nPlus (`+`) will perform arithmetic summation if both sides are a number or null, otherwise it will coerce both sides to\nstrings and concatenate them. All other arithmetic operations will attempt to coerce both sides to numbers according to\nES coercion rules and perform the corresponding arithmetic operation if both side are successfully coerced.\n\n```scala\ncase object MyJsonPathParser extends JsonPathParser with ArithmeticOperations\n\n```\n\n\u003c!-- @formatter:off --\u003e\n```scala\nscala\u003e case object MyJsonPathParser extends JsonPathParser with ArithmeticOperations\n\nobject MyJsonPathParser\n\nscala\u003e val raw = \"$[?(@.price + @.tax \u003c 50)]\"\nval raw: String = $[?(@.price + @.tax \u003c 50)]\n\nscala\u003e JsonPathParser.default.parse(raw)\nval res0: com.quincyjo.jsonpath.parser.models.ParseResult[com.quincyjo.jsonpath.JsonPath] = com.quincyjo.jsonpath.parser.models.ParseError: Failed to parse JsonPath at index 12 in '$[?(@.price + @.tax \u003c 50)]': Arithmetic operators are disabled.\n\nscala\u003e MyJsonPathParser.parse(raw)\nval res1: com.quincyjo.jsonpath.parser.models.ParseResult[com.quincyjo.jsonpath.JsonPath] = Parsed($[?(@['price'] + @['tax'] \u003c 50)])\n```\n\u003c!-- @formatter:on --\u003e\n\nBecause arithmetic operations are not a standard feature, they are not defined within the `Expression` companion object.\nInstead, they are available within the `ArithmeticOperations` companion. It is also worth keeping in mind that there is\nno defined behavior of these operators within the definition of JSONPath, so the behaviour of them may vary depending\non the specific implementation of JSONPath that is being used.\n\n## Example\n\nThe below example uses Circe JSON.\n\n\u003c!-- @formatter:off --\u003e\n```scala\nscala\u003e val json = Json.obj(\n     |   \"products\" -\u003e Json.obj(\n     |     \"fruit\" -\u003e Json.arr(\n     |       Json.obj(\n     |         \"label\" -\u003e \"Apple\".asJson,\n     |         \"price\" -\u003e 2.asJson,\n     |         \"quantity\" -\u003e 15.asJson\n     |       ),     \n     |       Json.obj(\n     |         \"label\" -\u003e \"Banana\".asJson,\n     |         \"price\" -\u003e 1.asJson,\n     |         \"quantity\" -\u003e 23.asJson\n     |       )\n     |     ),\n     |     \"other\" -\u003e Json.arr(\n     |       Json.obj(\n     |         \"label\" -\u003e \"Dinner Set\".asJson,\n     |         \"price\" -\u003e 30.asJson,\n     |         \"quantity\" -\u003e 2.asJson\n     |       ),\n     |       Json.obj(\n     |         \"label\" -\u003e \"Silverware Set\".asJson,\n     |         \"price\" -\u003e 10.asJson,\n     |         \"quantity\" -\u003e 4.asJson\n     |       )\n     |     )\n     |   )\n     | )\nval json: io.circe.Json =\n{\n  \"products\" : {\n    \"fruit\" : [\n      {\n        \"label\" : \"Apple\",\n        \"price\" : 2,\n        \"quantity\" : 15\n      },\n      {\n        \"label\" : \"Banana\",\n        \"price\" : 1,\n        \"quantity\" : 23\n      }\n    ],\n    \"other\" : [\n      {\n        \"label\" : \"Dinner Set\",\n        \"price\" : 30,\n        \"quantity\" : 2\n      },\n      {\n        \"label\" : \"Silverware Set\",\n        \"price\" : 10,\n        \"quantity\" : 4\n      }\n    ]\n  }\n}\n\nscala\u003e val jsonPath = $ / \"products\" / Wildcard /\n     |   Filter(\n     |     LessThanOrEqualTo(\n     |       JsonPathValue(`@` / \"price\"),\n     |       LiteralNumber(10)\n     |     )\n     |   )\nval jsonPath: com.quincyjo.jsonpath.JsonPath = $.products.*[?(@.price \u003c= 10)]\n\nscala\u003e CirceEvaluator.evaluate(jsonPath, json)\nval res0: List[com.quincyjo.jsonpath.Node[io.circe.Json]] =\nList(Node($['products']['fruit'][0],{\n  \"label\" : \"Apple\",\n  \"price\" : 2,\n  \"quantity\" : 15\n}), Node($['products']['fruit'][1],{\n  \"label\" : \"Banana\",\n  \"price\" : 1,\n  \"quantity\" : 23\n}), Node($['products']['other'][1],{\n  \"label\" : \"Silverware Set\",\n  \"price\" : 10,\n  \"quantity\" : 4\n}))\n```\n\u003c!-- @formatter:on --\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquincyjo%2Fscala-json-path","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fquincyjo%2Fscala-json-path","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fquincyjo%2Fscala-json-path/lists"}