Skip to content

Commit

Permalink
Readme update
Browse files Browse the repository at this point in the history
  • Loading branch information
halaxa committed Nov 23, 2024
1 parent 0857857 commit f051ff5
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 18 deletions.
93 changes: 77 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -320,25 +320,51 @@ foreach ($fruits as $key => $value) {
```

<a name="recursive"></a>
### Recursive iteration (BETA)
Recursive iteration can be enabled via `recursive` option set to `true`.
Every JSON iterable that JSON Machine encounters will then be yielded as an instance of `NestedIterator`.
No JSON array or object will be materialized and kept in memory.
The only PHP values you get materialized will be scalar values.
Let's see an example with many, many users with many, many friends
### Recursive iteration
Use `RecursiveItems` instead of `Items`.
When `RecursiveItems` encounters a list or dict in the JSON, it returns a new instance of `RecursiveItems`
which can then be iterated over and the cycle repeats.
Thus, it never returns a PHP array or object, but only either scalar values or `RecursiveItems`.
No JSON vector will ever be fully loaded into memory at once.
This feature is advantageous when the JSON has a complex structure
that is difficult or even impossible to iterate over with just `Items` and JSON pointers.

Let's see an example with many, many users with many, many friends:
```json
[
{
"username": "user",
"e-mail": "[email protected]",
"friends": [
{
"username": "friend1",
"e-mail": "[email protected]"
},
{
"username": "friend2",
"e-mail": "[email protected]"
}
]
}
]
```

```php
<?php

use JsonMachine\Items;

$users = Items::fromFile('users.json', ['recursive' => true]);
foreach ($users as $user) { // $user instanceof Traversable, not an array/object
foreach ($user as $userField => $userValue) {
if ($userField === 'friends') {
foreach ($userValue as $friend) { // $userValue instanceof Traversable, not an array/object
foreach ($friend as $friendField => $friendValue) { // $friend instanceof Traversable, not an array/object
// do whatever you want here
use JsonMachine\RecursiveItems

$users = RecursiveItems::fromFile('users.json');
foreach ($users as $user) {
/** @var $user RecursiveItems */
foreach ($user as $field => $value) {
if ($field === 'friends') {
/** @var $value RecursiveItems */
foreach ($value as $friend) {
/** @var $friend RecursiveItems */
foreach ($friend as $friendField => $friendValue) {
$friendField == 'username';
$friendValue == 'friend1';
}
}
}
Expand All @@ -351,6 +377,42 @@ foreach ($users as $user) { // $user instanceof Traversable, not an array/object
> JSON Machine must iterate it the background to be able to read next value.
> Such an attempt will result in closed generator exception.
#### Convenience methods of `RecursiveItems`
- `toArray(): array`
If you are sure that a certain instance of RecursiveItems is pointing to a memory-manageable data structure
(for example, $friend), you can call `$friend->toArray()`, and the item will materialize into a PHP array.

- `advanceToKey(int|string $key): scalar|RecursiveItems`
When searching for a specific key in a collection (for example, `$user["friends"]`),
you do not need to use a loop and a condition to search for it.
Instead, you can simply call `$user->advanceToKey("friends")`.
It will iterate for you and return the value at this key.

The previous example could thus be simplified as follows:
```php
<?php

use JsonMachine\RecursiveItems

$users = RecursiveItems::fromFile('users.json');
foreach ($users as $user) {
/** @var $user RecursiveItems */
foreach ($user->advanceToKey('friends') as $friend) {
/** @var $friend RecursiveItems */
$friendArray = $friend->toArray();
$friendArray['username'] == 'friend1';
}
}
```

#### Also `RecursiveItems implements \RecursiveIterator`
So you can use for example PHP's builtin tools to work over `\RecursiveIterator` like those:

- [RecursiveCallbackFilterIterator](https://www.php.net/manual/en/class.recursivecallbackfilteriterator.php)
- [RecursiveFilterIterator](https://www.php.net/manual/en/class.recursivefilteriterator.php)
- [RecursiveRegexIterator](https://www.php.net/manual/en/class.recursiveregexiterator.php)
- [RecursiveTreeIterator](https://www.php.net/manual/en/class.recursivetreeiterator.php)

<a name="json-pointer"></a>
### What is JSON Pointer anyway?
It's a way of addressing one item in JSON document. See the [JSON Pointer RFC 6901](https://tools.ietf.org/html/rfc6901).
Expand Down Expand Up @@ -378,7 +440,6 @@ Some examples:
Options may change how a JSON is parsed. Array of options is the second parameter of all `Items::from*` functions.
Available options are:
- `pointer` - A JSON Pointer string that tells which part of the document you want to iterate.
- `recursive` - Bool. Any JSON array/object the parser hits will not be decoded but served lazily as a `Traversable`. Default `false`.
- `decoder` - An instance of `ItemDecoder` interface.
- `debug` - `true` or `false` to enable or disable the debug mode. When the debug mode is enabled, data such as line,
column and position in the document are available during parsing or in exceptions. Keeping debug disabled adds slight
Expand Down
4 changes: 2 additions & 2 deletions src/RecursiveItems.php
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,9 @@ public function getChildren(): ?\RecursiveIterator
* Finds the desired key on this level and returns its value.
* It moves the internal cursor to it so subsequent calls to self::current() returns the same value.
*
* @param $key
* @param string|int $key
*
* @return mixed
* @return scalar|self
*
* @throws JsonMachineException when the key is not found on this level
*/
Expand Down

0 comments on commit f051ff5

Please sign in to comment.