halaxa / json-machine

Efficient, easy-to-use, and fast PHP JSON stream parser
Apache License 2.0
1.1k stars 65 forks source link

Non-Intersecting Pointers Considered Intersecting #106

Closed XedinUnknown closed 1 year ago

XedinUnknown commented 1 year ago

Symptoms

Let's say I have some sample data:

{
  "items": [
    {},
    {},
    {}
  ],
  "page": 1,
  "page_size": 10,
  "total_pages": 100,
  "total_results": 995
}

I want the values of page and page_size keys, so I read this into a streaming collection:

$data = Items::fromStream($resource, [
    'decoder' => new ExtJsonDecoder(true),
    'pointer' => ['/page', '/page_size'],
    'debug' => true,
]);

I get an error:

JsonMachine\Exception\InvalidArgumentException: JSON Pointers must not intersect. At least these two do: '/page_size', '/page'

Possible Cause

While validating, the pointers are all compared to each other. One way in which they are compared is by checking if one contains the other, in which case they are considered intersecting. However, while the string /page_size contains /page, they are in fact separate keys, and do not intersect.

Suggested Solution

Add a path delimiter to the end of each compared pointer string. This will ensure that the pointers explicitly terminate. image

Comparing two terminated pointers in this way would mean comparing /page/ and /page_size/ in this case: /page_size/ does not contain /page/. This is a similar approach to why Composer requires autoload namespace declarations to terminate with a namespace delimiter.

XedinUnknown commented 1 year ago

Fix PR now available for your consideration, @halaxa.

halaxa commented 1 year ago

Good job, thanks. I'll look into it asap.