Hone logo
Hone
Problems

JSON Path Query Implementation in JavaScript

JSON Path is a query language for JSON, similar to XPath for XML. Implementing a JSON Path query engine allows you to efficiently extract specific data from complex JSON structures without needing to write verbose and potentially error-prone code. This challenge asks you to build a JavaScript function that evaluates JSON Path expressions against a given JSON object.

Problem Description

You are tasked with creating a JavaScript function called jsonPathQuery that takes two arguments: a JSON object (data) and a JSON Path expression (path). The function should return an array of values found at the specified path within the JSON object. If no values are found, it should return an empty array.

Key Requirements:

  • Path Syntax: The JSON Path expression should support the following syntax:
    • $ represents the root object.
    • . is used to access properties of an object.
    • [] is used to access array elements by index.
    • * is a wildcard that matches any value.
    • .. is a recursive descent operator (matches any descendant).
  • Data Types: The function should handle various JSON data types, including objects, arrays, strings, numbers, booleans, and null.
  • Wildcard Support: The wildcard * should match any value at the specified level.
  • Recursive Descent: The .. operator should recursively search for matches within nested objects and arrays.
  • Array Indexing: Array indices should be integers.
  • Return Type: The function must return an array of values that match the JSON Path expression. If multiple matches are found, they should all be included in the array.

Expected Behavior:

The function should return an array containing all values that match the given JSON Path expression within the provided JSON data. If no matches are found, an empty array should be returned.

Edge Cases to Consider:

  • Empty JSON data.
  • Invalid JSON Path expressions (e.g., syntax errors, non-integer array indices). While you don't need to throw errors for invalid paths, the function should gracefully return an empty array.
  • Paths that go beyond the bounds of an array.
  • Paths that reference non-existent properties.
  • Paths containing multiple wildcards.
  • Recursive descent paths that traverse deeply nested structures.

Examples

Example 1:

Input:
data: { "name": "John", "age": 30, "address": { "city": "New York" } }
path: "$.name"
Output: ["John"]
Explanation: The path "$.name" selects the value of the "name" property at the root level, which is "John".

Example 2:

Input:
data: { "items": [ { "id": 1, "name": "Apple" }, { "id": 2, "name": "Banana" } ] }
path: "$.items[*].name"
Output: ["Apple", "Banana"]
Explanation: The path "$.items[*].name" selects the "name" property from each element in the "items" array.

Example 3:

Input:
data: { "a": { "b": { "c": 1 } }, "d": [2, 3, 4] }
path: "$.a..c"
Output: [1]
Explanation: The path "$.a..c" recursively searches for the "c" property within the "a" object and its descendants.

Example 4:

Input:
data: { "a": [1, 2, { "b": 3 }] }
path: "$.a[2].b"
Output: [3]
Explanation: Accesses the 'b' property of the object at index 2 of the array 'a'.

Example 5:

Input:
data: { "a": [1, 2, 3] }
path: "$.a[5]"
Output: []
Explanation: Index 5 is out of bounds for the array 'a'.

Constraints

  • The JSON data will be a valid JavaScript object.
  • The JSON Path expression will be a string.
  • The length of the JSON Path expression can vary.
  • The function should execute within a reasonable time limit (e.g., less than 500ms for typical JSON structures). While absolute performance isn't the primary focus, avoid excessively inefficient algorithms.
  • The function should be able to handle JSON objects with a depth of up to 10 levels.

Notes

  • Consider using recursion to handle the recursive descent operator (..).
  • Break down the JSON Path expression into tokens to simplify parsing and evaluation.
  • Regular expressions can be helpful for parsing the JSON Path expression, but be mindful of their performance implications.
  • Start with simpler cases (e.g., direct property access) and gradually add support for more complex features like wildcards and recursive descent.
  • Thoroughly test your implementation with a variety of JSON data and JSON Path expressions, including edge cases.
Loading editor...
javascript