Traversing through deeply nested JSON object
When interacting with an API used for building forms, I make an API call to get all the response values associated with my form. The API returns a deeply nested JSON object with all my form values.
One of the many response objects looks like this:
{
"title":{
"plain":"Send Money"
},
"fieldset":[
{
"label":{
"plain":"Personal Info Section"
},
"fieldset":[
{
"field":[
{
"label":{
"plain":"First Name"
},
"value":{
"plain":"Bob"
},
"id":"a_1"
},
{
"label":{
"plain":"Last Name"
},
"value":{
"plain":"Hogan"
},
"id":"a_2"
}
],
"id":"a_8"
}
],
"id":"a_5"
},
{
"label":{
"plain":"Billing Details Section"
},
"fieldset":{
"field":{
"choices":{
"choice":{
"label":{
"plain":"Gift"
},
"id":"a_17",
"switch":""
}
},
"label":{
"plain":"Choose a category:"
},
"value":{
"plain":"Gift"
},
"id":"a_14"
},
"fieldset":{
"label":{
"plain":""
},
"field":[
{
"choices":{
"choice":{
"label":{
"plain":"Other"
},
"id":"a_25",
"switch":""
}
},
"label":{
"plain":"Amount"
},
"value":{
"plain":"Other" //(This could also be a dollar amount like 10.00)
},
"id":"a_21"
},
{
"label":{
"plain":"Other Amount"
},
"value":{
"plain":"200"
},
"id":"a_20"
}
],
"id":"a_26"
},
"id":"a_13"
},
"id":"a_12"
}
]
}
The goal here is to run a report of all responses and print the data out in a readable way (e.g. "Bob Hogan - $200, Chad Smith - $100").
I'm thinking I'll have to use some sort of map-reduce algorithm because simply nesting a bunch of loops can be unscalable as well as computationally expensive given the increasing time complexity if its a large dataset. Maybe I have to write a recursive function that maps through my dataset, checks the id value, reduces it down to an array if it finds a matching id?
Additionally, I'd like to avoid using a 3rd party library. PHP has enough native functions to facilitate what I'm trying to accomplish.
json mapreduce associative-array php-7
add a comment |
When interacting with an API used for building forms, I make an API call to get all the response values associated with my form. The API returns a deeply nested JSON object with all my form values.
One of the many response objects looks like this:
{
"title":{
"plain":"Send Money"
},
"fieldset":[
{
"label":{
"plain":"Personal Info Section"
},
"fieldset":[
{
"field":[
{
"label":{
"plain":"First Name"
},
"value":{
"plain":"Bob"
},
"id":"a_1"
},
{
"label":{
"plain":"Last Name"
},
"value":{
"plain":"Hogan"
},
"id":"a_2"
}
],
"id":"a_8"
}
],
"id":"a_5"
},
{
"label":{
"plain":"Billing Details Section"
},
"fieldset":{
"field":{
"choices":{
"choice":{
"label":{
"plain":"Gift"
},
"id":"a_17",
"switch":""
}
},
"label":{
"plain":"Choose a category:"
},
"value":{
"plain":"Gift"
},
"id":"a_14"
},
"fieldset":{
"label":{
"plain":""
},
"field":[
{
"choices":{
"choice":{
"label":{
"plain":"Other"
},
"id":"a_25",
"switch":""
}
},
"label":{
"plain":"Amount"
},
"value":{
"plain":"Other" //(This could also be a dollar amount like 10.00)
},
"id":"a_21"
},
{
"label":{
"plain":"Other Amount"
},
"value":{
"plain":"200"
},
"id":"a_20"
}
],
"id":"a_26"
},
"id":"a_13"
},
"id":"a_12"
}
]
}
The goal here is to run a report of all responses and print the data out in a readable way (e.g. "Bob Hogan - $200, Chad Smith - $100").
I'm thinking I'll have to use some sort of map-reduce algorithm because simply nesting a bunch of loops can be unscalable as well as computationally expensive given the increasing time complexity if its a large dataset. Maybe I have to write a recursive function that maps through my dataset, checks the id value, reduces it down to an array if it finds a matching id?
Additionally, I'd like to avoid using a 3rd party library. PHP has enough native functions to facilitate what I'm trying to accomplish.
json mapreduce associative-array php-7
add a comment |
When interacting with an API used for building forms, I make an API call to get all the response values associated with my form. The API returns a deeply nested JSON object with all my form values.
One of the many response objects looks like this:
{
"title":{
"plain":"Send Money"
},
"fieldset":[
{
"label":{
"plain":"Personal Info Section"
},
"fieldset":[
{
"field":[
{
"label":{
"plain":"First Name"
},
"value":{
"plain":"Bob"
},
"id":"a_1"
},
{
"label":{
"plain":"Last Name"
},
"value":{
"plain":"Hogan"
},
"id":"a_2"
}
],
"id":"a_8"
}
],
"id":"a_5"
},
{
"label":{
"plain":"Billing Details Section"
},
"fieldset":{
"field":{
"choices":{
"choice":{
"label":{
"plain":"Gift"
},
"id":"a_17",
"switch":""
}
},
"label":{
"plain":"Choose a category:"
},
"value":{
"plain":"Gift"
},
"id":"a_14"
},
"fieldset":{
"label":{
"plain":""
},
"field":[
{
"choices":{
"choice":{
"label":{
"plain":"Other"
},
"id":"a_25",
"switch":""
}
},
"label":{
"plain":"Amount"
},
"value":{
"plain":"Other" //(This could also be a dollar amount like 10.00)
},
"id":"a_21"
},
{
"label":{
"plain":"Other Amount"
},
"value":{
"plain":"200"
},
"id":"a_20"
}
],
"id":"a_26"
},
"id":"a_13"
},
"id":"a_12"
}
]
}
The goal here is to run a report of all responses and print the data out in a readable way (e.g. "Bob Hogan - $200, Chad Smith - $100").
I'm thinking I'll have to use some sort of map-reduce algorithm because simply nesting a bunch of loops can be unscalable as well as computationally expensive given the increasing time complexity if its a large dataset. Maybe I have to write a recursive function that maps through my dataset, checks the id value, reduces it down to an array if it finds a matching id?
Additionally, I'd like to avoid using a 3rd party library. PHP has enough native functions to facilitate what I'm trying to accomplish.
json mapreduce associative-array php-7
When interacting with an API used for building forms, I make an API call to get all the response values associated with my form. The API returns a deeply nested JSON object with all my form values.
One of the many response objects looks like this:
{
"title":{
"plain":"Send Money"
},
"fieldset":[
{
"label":{
"plain":"Personal Info Section"
},
"fieldset":[
{
"field":[
{
"label":{
"plain":"First Name"
},
"value":{
"plain":"Bob"
},
"id":"a_1"
},
{
"label":{
"plain":"Last Name"
},
"value":{
"plain":"Hogan"
},
"id":"a_2"
}
],
"id":"a_8"
}
],
"id":"a_5"
},
{
"label":{
"plain":"Billing Details Section"
},
"fieldset":{
"field":{
"choices":{
"choice":{
"label":{
"plain":"Gift"
},
"id":"a_17",
"switch":""
}
},
"label":{
"plain":"Choose a category:"
},
"value":{
"plain":"Gift"
},
"id":"a_14"
},
"fieldset":{
"label":{
"plain":""
},
"field":[
{
"choices":{
"choice":{
"label":{
"plain":"Other"
},
"id":"a_25",
"switch":""
}
},
"label":{
"plain":"Amount"
},
"value":{
"plain":"Other" //(This could also be a dollar amount like 10.00)
},
"id":"a_21"
},
{
"label":{
"plain":"Other Amount"
},
"value":{
"plain":"200"
},
"id":"a_20"
}
],
"id":"a_26"
},
"id":"a_13"
},
"id":"a_12"
}
]
}
The goal here is to run a report of all responses and print the data out in a readable way (e.g. "Bob Hogan - $200, Chad Smith - $100").
I'm thinking I'll have to use some sort of map-reduce algorithm because simply nesting a bunch of loops can be unscalable as well as computationally expensive given the increasing time complexity if its a large dataset. Maybe I have to write a recursive function that maps through my dataset, checks the id value, reduces it down to an array if it finds a matching id?
Additionally, I'd like to avoid using a 3rd party library. PHP has enough native functions to facilitate what I'm trying to accomplish.
json mapreduce associative-array php-7
json mapreduce associative-array php-7
edited Nov 22 '18 at 11:44
Flimzy
40.2k1367100
40.2k1367100
asked Nov 21 '18 at 23:12
lsimonettilsimonetti
4651616
4651616
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
Actually there 's no need for a magic algorithm. Just a bit of php magic in form of entites, hydrators and filters.
In this answer you 'll get an object orientated php approach, which will hydrate the json api response into objects, which you can easily filter. Just keep in mind, that in this oop apporach everything is an object.
The data object - data entity
First of all you have to know, how your data is structured. From this structury you can build php objects. From the given JSON structure you can use the following objects.
namespace ApplicationEntity;
// Just for recognizing entities as entities later
interface EntityInterface
{
}
class Title implements EntityInterface, JsonSerializable
{
public $plain;
public function getPlain() : ?string
{
return $this->plain;
}
public function setPlain(string $plain) : Title
{
$this->plain = $plain;
return $this;
}
public function jsonSerialize() : array
{
return get_object_vars($this);
}
}
class Fieldset implements EntityInterface, JsonSerializable
{
/**
* Label object
* @var Label
*/
public $label;
/**
* Collection of Field objects
* @var ArrayObject
*/
public $fieldset;
// implement getter and setter methods here
}
class Section implements EntityInterface, JsonSerializable
{
public $title;
public $fieldsets;
public function getTitle() : ?Title
{
return $this->title;
}
public function setTitle(Title $title) : Section
{
$this->title = $title;
return $this;
}
public function getFieldsets() : ArrayObject
{
if (!$this->fieldsets) {
$this->fieldsets = new ArrayObject();
}
return $this->fieldsets;
}
public function setFieldsets(Fieldset $fieldset) : Section
{
if (!$this->fieldsets) {
$this->fieldsets = new ArrayObject();
}
$this->fieldsets->append($fieldset);
return $this;
}
public function jsonSerialize() : array
{
return get_object_vars($this);
}
}
Well, this class depicts the properties of the very first json object given in your example. Why this class implements the JsonSerializable interface? With this implementation you are able to transform the class structure back into a well formed json string. I 'm not sure, if you need that. But for sure it is safe, while communicating with a rest api. The only thing you have to do now is programming entities for every expected complex data structure / json object. You need the title object with a plin property and a fieldset object with label and fieldset properties and so on.
How to get the json data into a php object - hydration
Of course, your given json structure is a string. When we talk about hydration we actually mean converting a json string into an object structure. The above mentioned entites are needed for this approach.
But first the hydrator class itself.
namespace ApplicationHydrator;
use ApplicationEntityEntityInterface;
class ClassMethodsHydrator
{
protected $strategies;
public function hydrate(array $data, EntityInterface $entity) : EntityInterface
{
foreach ($data as $key => $value) {
if (!method_exists($entity, 'set' . ucfirst($key)) {
throw new InvalidArgumentException(sprintf(
'The method %s does not exist in %s',
get_class($entity)
));
}
if ($this->strategies[$key]) {
$strategy = $this->strategies[$key];
$value = $strategy->hydrate($value);
}
$entity->{'set' . ucfirst($key)}($value);
}
return $entity;
}
public function addStrategy(string $name, StrategyInterface $strategy) : Hydrator
{
$this->strategies[$name] = $strategy;
return $this;
}
}
Well, this is the class where all the magic happens. I guess this is what you mentioned as algorithm. The hydrator takes your data from the json response and pushes it into your entities. When having the entites hydrated, you can easily access the given data by calling the get methods of the entities.
As the json data is complex and nested, we have to use hydrator strategies. A common pattern in hydration concerns. A strategy can be hooked into a object property and executes another hydrator. So we make sure that we represent the nested data in an identical object structure.
Here 's an example of a hydrator strategy.
namespace ApplicationHydratorStrategy;
use ApplicationEntityEntityInterface;
interface HydratorStrategy
{
public function hydrate(array $value) : EntityInterface;
}
use ApplicationEntityTitle;
class TitleHydratorStrategy implements HydratorStrategy
{
public function hydrate(array $value) : EntityInterface
{
$value = (new ClassMethods())->hydrate($value, new Title);
return $value;
}
}
// Use case of a strategy
$data = json_decode$($response, true);
$section = (new ClassMethods())
->addStrategy('title', new TitleHydratorStrategy())
->hydrate($data, new Section());
So what a hydrator strategy actually does? While iterating over our json api response, there are severel elements, which are an object or contain objects. To hydrate this multidimensional structure correctly, we use strategies.
To stay with your example of the JSON response I 've added a simple use case. First we decode the json response into an assiciative, multidimensional array. After that we use our entities, hydrators and hydrator strategies to get an object, which contains all the data. The use case knows, that the title property in the JSON response is an object that should hydrated into our title entity, which contains the plain property.
At the end our hydrated object has a structure like this ...
ApplicationEntitySection {
public:title => ApplicationEntityTitle [
public:plain => string 'Send Money'
}
...
}
Actually you can access the properties with the getter methods of our entities.
echo $section->getTitle()->getPlain(); // echoes 'Send money'
Knowing how to hydrate our classes leads us to the next step. Aggregation!
Getting the full string with aggregation
Actually aggregation is a common design pattern in modern object orientated programming. Aggregation means no more and no less than the allocation of data. Let 's have a look at your posted JSON response. As we can see the fieldset property of our root object contains a collection of fieldset objects, that we can access via our getter and setter methods. With this in mind, we can create additional getter methods in our section entity. Let us expand our section entity with a getFullName
method.
...
public function getFullName() : string
{
$firstname = $lastname = '';
// fetch the personal info section
if ($this->getFieldsets()->offsetExists(0)) {
$personalInfoFieldset = $this->getFieldsets()->offsetGet(0)->getFiedlset()->offsetGet(0);
$firstname = $personalInfoFieldset->getField()->offsetGet(0)->getValue();
$lastname = $personalInfoFieldset->getField()->offsetGet(1)->getValue();
}
return $this->concatenate(' ', $firstname, $lastname);
}
public function concatenate(string $filler, ...$strings) : string
{
$string = '';
foreach ($strings as $partial) {
$string .= $partial . $filler;
}
return trim($string);
}
This example assumes, that both the first name and the last name are available in the very first item of the fieldset collection of the section entity. So we get Bob Hogan
as return value. The concatenate
method is just a little helper, which concatenates a number of strings with a filler (space).
Filter data using our entities and the FilterIterator class
Further you mentioned, that you have to find specific data by id. One possible solution coould be filtering our entities by a specific item with the Filter Iterator class.
namespace ApplicationFilter;
class PersonIdFilter extends FilterIterator
{
protected $id;
public function __construct(Iterator $iterator, string $id)
{
parent::__construct($iterator);
$this->id = $id;
}
public function accept()
{
$person = $this->getInnerIterator()->current();
return ($person->getId() == $this->id) ? true : false;
}
}
Because of using ArrayObject
classes for our collections we are able to use iterators to filter for a specific argument. In this case we filter for the id in our personal info fieldsets.
Starting from our hydration example we it could be something like the following code.
$personalIterator = $section->getFieldsets()->offsetGet(0)->getFieldset()->getIterator();
$filter = new PersonIdFilter($personalIterator, 'a_8');
foreach ($filter as $result) {
var_dump($result); // will output the first fieldset with the personal data
}
Too complex? Absolutely not!
As you said you want a scalable solution without nested iterations in a huge loop. In my eyes it makes sense not writing just a huge single function, wich iterates the json response and returns the data you want. Working with objects in this case makes mch more sense because of the high scalability. You can access all the data you want in a glimpse by calling the right getter methods. Furthermore the code is mich more readable than a huge function which is recursivly iterating again and again. In the above shown approach you only code once and reuse all the objects again and again.
Please keep in mind, the the above shown code is just a theoretical suggestion. It is not tested.
Brilliant. I like the use of the Hydrator Strategy pattern. That makes a lot of sense. Do you think that having a huge number of responses being kept in objects would have a considerable memory impact? I'm just trying to think in terms of performance.
– lsimonetti
Nov 27 '18 at 13:59
I guess this kind of traversing through deeply nested data sets would affect the memory usage. As php7 optimized a lot concerning memory while handling objects and object iteration this approach would use a minimum of more memory. Actually this approach is used by zend framework and works very well. If you want to optimize the memory usage a bit, you can try to use generators when it comes to filtering the objects. PHP generators implement automatically the iterator interface while using fewer memory. I haven 't tried to yield a generator from an array object. Might be a possible solution.
– Marcel
Nov 27 '18 at 19:39
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53421756%2ftraversing-through-deeply-nested-json-object%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Actually there 's no need for a magic algorithm. Just a bit of php magic in form of entites, hydrators and filters.
In this answer you 'll get an object orientated php approach, which will hydrate the json api response into objects, which you can easily filter. Just keep in mind, that in this oop apporach everything is an object.
The data object - data entity
First of all you have to know, how your data is structured. From this structury you can build php objects. From the given JSON structure you can use the following objects.
namespace ApplicationEntity;
// Just for recognizing entities as entities later
interface EntityInterface
{
}
class Title implements EntityInterface, JsonSerializable
{
public $plain;
public function getPlain() : ?string
{
return $this->plain;
}
public function setPlain(string $plain) : Title
{
$this->plain = $plain;
return $this;
}
public function jsonSerialize() : array
{
return get_object_vars($this);
}
}
class Fieldset implements EntityInterface, JsonSerializable
{
/**
* Label object
* @var Label
*/
public $label;
/**
* Collection of Field objects
* @var ArrayObject
*/
public $fieldset;
// implement getter and setter methods here
}
class Section implements EntityInterface, JsonSerializable
{
public $title;
public $fieldsets;
public function getTitle() : ?Title
{
return $this->title;
}
public function setTitle(Title $title) : Section
{
$this->title = $title;
return $this;
}
public function getFieldsets() : ArrayObject
{
if (!$this->fieldsets) {
$this->fieldsets = new ArrayObject();
}
return $this->fieldsets;
}
public function setFieldsets(Fieldset $fieldset) : Section
{
if (!$this->fieldsets) {
$this->fieldsets = new ArrayObject();
}
$this->fieldsets->append($fieldset);
return $this;
}
public function jsonSerialize() : array
{
return get_object_vars($this);
}
}
Well, this class depicts the properties of the very first json object given in your example. Why this class implements the JsonSerializable interface? With this implementation you are able to transform the class structure back into a well formed json string. I 'm not sure, if you need that. But for sure it is safe, while communicating with a rest api. The only thing you have to do now is programming entities for every expected complex data structure / json object. You need the title object with a plin property and a fieldset object with label and fieldset properties and so on.
How to get the json data into a php object - hydration
Of course, your given json structure is a string. When we talk about hydration we actually mean converting a json string into an object structure. The above mentioned entites are needed for this approach.
But first the hydrator class itself.
namespace ApplicationHydrator;
use ApplicationEntityEntityInterface;
class ClassMethodsHydrator
{
protected $strategies;
public function hydrate(array $data, EntityInterface $entity) : EntityInterface
{
foreach ($data as $key => $value) {
if (!method_exists($entity, 'set' . ucfirst($key)) {
throw new InvalidArgumentException(sprintf(
'The method %s does not exist in %s',
get_class($entity)
));
}
if ($this->strategies[$key]) {
$strategy = $this->strategies[$key];
$value = $strategy->hydrate($value);
}
$entity->{'set' . ucfirst($key)}($value);
}
return $entity;
}
public function addStrategy(string $name, StrategyInterface $strategy) : Hydrator
{
$this->strategies[$name] = $strategy;
return $this;
}
}
Well, this is the class where all the magic happens. I guess this is what you mentioned as algorithm. The hydrator takes your data from the json response and pushes it into your entities. When having the entites hydrated, you can easily access the given data by calling the get methods of the entities.
As the json data is complex and nested, we have to use hydrator strategies. A common pattern in hydration concerns. A strategy can be hooked into a object property and executes another hydrator. So we make sure that we represent the nested data in an identical object structure.
Here 's an example of a hydrator strategy.
namespace ApplicationHydratorStrategy;
use ApplicationEntityEntityInterface;
interface HydratorStrategy
{
public function hydrate(array $value) : EntityInterface;
}
use ApplicationEntityTitle;
class TitleHydratorStrategy implements HydratorStrategy
{
public function hydrate(array $value) : EntityInterface
{
$value = (new ClassMethods())->hydrate($value, new Title);
return $value;
}
}
// Use case of a strategy
$data = json_decode$($response, true);
$section = (new ClassMethods())
->addStrategy('title', new TitleHydratorStrategy())
->hydrate($data, new Section());
So what a hydrator strategy actually does? While iterating over our json api response, there are severel elements, which are an object or contain objects. To hydrate this multidimensional structure correctly, we use strategies.
To stay with your example of the JSON response I 've added a simple use case. First we decode the json response into an assiciative, multidimensional array. After that we use our entities, hydrators and hydrator strategies to get an object, which contains all the data. The use case knows, that the title property in the JSON response is an object that should hydrated into our title entity, which contains the plain property.
At the end our hydrated object has a structure like this ...
ApplicationEntitySection {
public:title => ApplicationEntityTitle [
public:plain => string 'Send Money'
}
...
}
Actually you can access the properties with the getter methods of our entities.
echo $section->getTitle()->getPlain(); // echoes 'Send money'
Knowing how to hydrate our classes leads us to the next step. Aggregation!
Getting the full string with aggregation
Actually aggregation is a common design pattern in modern object orientated programming. Aggregation means no more and no less than the allocation of data. Let 's have a look at your posted JSON response. As we can see the fieldset property of our root object contains a collection of fieldset objects, that we can access via our getter and setter methods. With this in mind, we can create additional getter methods in our section entity. Let us expand our section entity with a getFullName
method.
...
public function getFullName() : string
{
$firstname = $lastname = '';
// fetch the personal info section
if ($this->getFieldsets()->offsetExists(0)) {
$personalInfoFieldset = $this->getFieldsets()->offsetGet(0)->getFiedlset()->offsetGet(0);
$firstname = $personalInfoFieldset->getField()->offsetGet(0)->getValue();
$lastname = $personalInfoFieldset->getField()->offsetGet(1)->getValue();
}
return $this->concatenate(' ', $firstname, $lastname);
}
public function concatenate(string $filler, ...$strings) : string
{
$string = '';
foreach ($strings as $partial) {
$string .= $partial . $filler;
}
return trim($string);
}
This example assumes, that both the first name and the last name are available in the very first item of the fieldset collection of the section entity. So we get Bob Hogan
as return value. The concatenate
method is just a little helper, which concatenates a number of strings with a filler (space).
Filter data using our entities and the FilterIterator class
Further you mentioned, that you have to find specific data by id. One possible solution coould be filtering our entities by a specific item with the Filter Iterator class.
namespace ApplicationFilter;
class PersonIdFilter extends FilterIterator
{
protected $id;
public function __construct(Iterator $iterator, string $id)
{
parent::__construct($iterator);
$this->id = $id;
}
public function accept()
{
$person = $this->getInnerIterator()->current();
return ($person->getId() == $this->id) ? true : false;
}
}
Because of using ArrayObject
classes for our collections we are able to use iterators to filter for a specific argument. In this case we filter for the id in our personal info fieldsets.
Starting from our hydration example we it could be something like the following code.
$personalIterator = $section->getFieldsets()->offsetGet(0)->getFieldset()->getIterator();
$filter = new PersonIdFilter($personalIterator, 'a_8');
foreach ($filter as $result) {
var_dump($result); // will output the first fieldset with the personal data
}
Too complex? Absolutely not!
As you said you want a scalable solution without nested iterations in a huge loop. In my eyes it makes sense not writing just a huge single function, wich iterates the json response and returns the data you want. Working with objects in this case makes mch more sense because of the high scalability. You can access all the data you want in a glimpse by calling the right getter methods. Furthermore the code is mich more readable than a huge function which is recursivly iterating again and again. In the above shown approach you only code once and reuse all the objects again and again.
Please keep in mind, the the above shown code is just a theoretical suggestion. It is not tested.
Brilliant. I like the use of the Hydrator Strategy pattern. That makes a lot of sense. Do you think that having a huge number of responses being kept in objects would have a considerable memory impact? I'm just trying to think in terms of performance.
– lsimonetti
Nov 27 '18 at 13:59
I guess this kind of traversing through deeply nested data sets would affect the memory usage. As php7 optimized a lot concerning memory while handling objects and object iteration this approach would use a minimum of more memory. Actually this approach is used by zend framework and works very well. If you want to optimize the memory usage a bit, you can try to use generators when it comes to filtering the objects. PHP generators implement automatically the iterator interface while using fewer memory. I haven 't tried to yield a generator from an array object. Might be a possible solution.
– Marcel
Nov 27 '18 at 19:39
add a comment |
Actually there 's no need for a magic algorithm. Just a bit of php magic in form of entites, hydrators and filters.
In this answer you 'll get an object orientated php approach, which will hydrate the json api response into objects, which you can easily filter. Just keep in mind, that in this oop apporach everything is an object.
The data object - data entity
First of all you have to know, how your data is structured. From this structury you can build php objects. From the given JSON structure you can use the following objects.
namespace ApplicationEntity;
// Just for recognizing entities as entities later
interface EntityInterface
{
}
class Title implements EntityInterface, JsonSerializable
{
public $plain;
public function getPlain() : ?string
{
return $this->plain;
}
public function setPlain(string $plain) : Title
{
$this->plain = $plain;
return $this;
}
public function jsonSerialize() : array
{
return get_object_vars($this);
}
}
class Fieldset implements EntityInterface, JsonSerializable
{
/**
* Label object
* @var Label
*/
public $label;
/**
* Collection of Field objects
* @var ArrayObject
*/
public $fieldset;
// implement getter and setter methods here
}
class Section implements EntityInterface, JsonSerializable
{
public $title;
public $fieldsets;
public function getTitle() : ?Title
{
return $this->title;
}
public function setTitle(Title $title) : Section
{
$this->title = $title;
return $this;
}
public function getFieldsets() : ArrayObject
{
if (!$this->fieldsets) {
$this->fieldsets = new ArrayObject();
}
return $this->fieldsets;
}
public function setFieldsets(Fieldset $fieldset) : Section
{
if (!$this->fieldsets) {
$this->fieldsets = new ArrayObject();
}
$this->fieldsets->append($fieldset);
return $this;
}
public function jsonSerialize() : array
{
return get_object_vars($this);
}
}
Well, this class depicts the properties of the very first json object given in your example. Why this class implements the JsonSerializable interface? With this implementation you are able to transform the class structure back into a well formed json string. I 'm not sure, if you need that. But for sure it is safe, while communicating with a rest api. The only thing you have to do now is programming entities for every expected complex data structure / json object. You need the title object with a plin property and a fieldset object with label and fieldset properties and so on.
How to get the json data into a php object - hydration
Of course, your given json structure is a string. When we talk about hydration we actually mean converting a json string into an object structure. The above mentioned entites are needed for this approach.
But first the hydrator class itself.
namespace ApplicationHydrator;
use ApplicationEntityEntityInterface;
class ClassMethodsHydrator
{
protected $strategies;
public function hydrate(array $data, EntityInterface $entity) : EntityInterface
{
foreach ($data as $key => $value) {
if (!method_exists($entity, 'set' . ucfirst($key)) {
throw new InvalidArgumentException(sprintf(
'The method %s does not exist in %s',
get_class($entity)
));
}
if ($this->strategies[$key]) {
$strategy = $this->strategies[$key];
$value = $strategy->hydrate($value);
}
$entity->{'set' . ucfirst($key)}($value);
}
return $entity;
}
public function addStrategy(string $name, StrategyInterface $strategy) : Hydrator
{
$this->strategies[$name] = $strategy;
return $this;
}
}
Well, this is the class where all the magic happens. I guess this is what you mentioned as algorithm. The hydrator takes your data from the json response and pushes it into your entities. When having the entites hydrated, you can easily access the given data by calling the get methods of the entities.
As the json data is complex and nested, we have to use hydrator strategies. A common pattern in hydration concerns. A strategy can be hooked into a object property and executes another hydrator. So we make sure that we represent the nested data in an identical object structure.
Here 's an example of a hydrator strategy.
namespace ApplicationHydratorStrategy;
use ApplicationEntityEntityInterface;
interface HydratorStrategy
{
public function hydrate(array $value) : EntityInterface;
}
use ApplicationEntityTitle;
class TitleHydratorStrategy implements HydratorStrategy
{
public function hydrate(array $value) : EntityInterface
{
$value = (new ClassMethods())->hydrate($value, new Title);
return $value;
}
}
// Use case of a strategy
$data = json_decode$($response, true);
$section = (new ClassMethods())
->addStrategy('title', new TitleHydratorStrategy())
->hydrate($data, new Section());
So what a hydrator strategy actually does? While iterating over our json api response, there are severel elements, which are an object or contain objects. To hydrate this multidimensional structure correctly, we use strategies.
To stay with your example of the JSON response I 've added a simple use case. First we decode the json response into an assiciative, multidimensional array. After that we use our entities, hydrators and hydrator strategies to get an object, which contains all the data. The use case knows, that the title property in the JSON response is an object that should hydrated into our title entity, which contains the plain property.
At the end our hydrated object has a structure like this ...
ApplicationEntitySection {
public:title => ApplicationEntityTitle [
public:plain => string 'Send Money'
}
...
}
Actually you can access the properties with the getter methods of our entities.
echo $section->getTitle()->getPlain(); // echoes 'Send money'
Knowing how to hydrate our classes leads us to the next step. Aggregation!
Getting the full string with aggregation
Actually aggregation is a common design pattern in modern object orientated programming. Aggregation means no more and no less than the allocation of data. Let 's have a look at your posted JSON response. As we can see the fieldset property of our root object contains a collection of fieldset objects, that we can access via our getter and setter methods. With this in mind, we can create additional getter methods in our section entity. Let us expand our section entity with a getFullName
method.
...
public function getFullName() : string
{
$firstname = $lastname = '';
// fetch the personal info section
if ($this->getFieldsets()->offsetExists(0)) {
$personalInfoFieldset = $this->getFieldsets()->offsetGet(0)->getFiedlset()->offsetGet(0);
$firstname = $personalInfoFieldset->getField()->offsetGet(0)->getValue();
$lastname = $personalInfoFieldset->getField()->offsetGet(1)->getValue();
}
return $this->concatenate(' ', $firstname, $lastname);
}
public function concatenate(string $filler, ...$strings) : string
{
$string = '';
foreach ($strings as $partial) {
$string .= $partial . $filler;
}
return trim($string);
}
This example assumes, that both the first name and the last name are available in the very first item of the fieldset collection of the section entity. So we get Bob Hogan
as return value. The concatenate
method is just a little helper, which concatenates a number of strings with a filler (space).
Filter data using our entities and the FilterIterator class
Further you mentioned, that you have to find specific data by id. One possible solution coould be filtering our entities by a specific item with the Filter Iterator class.
namespace ApplicationFilter;
class PersonIdFilter extends FilterIterator
{
protected $id;
public function __construct(Iterator $iterator, string $id)
{
parent::__construct($iterator);
$this->id = $id;
}
public function accept()
{
$person = $this->getInnerIterator()->current();
return ($person->getId() == $this->id) ? true : false;
}
}
Because of using ArrayObject
classes for our collections we are able to use iterators to filter for a specific argument. In this case we filter for the id in our personal info fieldsets.
Starting from our hydration example we it could be something like the following code.
$personalIterator = $section->getFieldsets()->offsetGet(0)->getFieldset()->getIterator();
$filter = new PersonIdFilter($personalIterator, 'a_8');
foreach ($filter as $result) {
var_dump($result); // will output the first fieldset with the personal data
}
Too complex? Absolutely not!
As you said you want a scalable solution without nested iterations in a huge loop. In my eyes it makes sense not writing just a huge single function, wich iterates the json response and returns the data you want. Working with objects in this case makes mch more sense because of the high scalability. You can access all the data you want in a glimpse by calling the right getter methods. Furthermore the code is mich more readable than a huge function which is recursivly iterating again and again. In the above shown approach you only code once and reuse all the objects again and again.
Please keep in mind, the the above shown code is just a theoretical suggestion. It is not tested.
Brilliant. I like the use of the Hydrator Strategy pattern. That makes a lot of sense. Do you think that having a huge number of responses being kept in objects would have a considerable memory impact? I'm just trying to think in terms of performance.
– lsimonetti
Nov 27 '18 at 13:59
I guess this kind of traversing through deeply nested data sets would affect the memory usage. As php7 optimized a lot concerning memory while handling objects and object iteration this approach would use a minimum of more memory. Actually this approach is used by zend framework and works very well. If you want to optimize the memory usage a bit, you can try to use generators when it comes to filtering the objects. PHP generators implement automatically the iterator interface while using fewer memory. I haven 't tried to yield a generator from an array object. Might be a possible solution.
– Marcel
Nov 27 '18 at 19:39
add a comment |
Actually there 's no need for a magic algorithm. Just a bit of php magic in form of entites, hydrators and filters.
In this answer you 'll get an object orientated php approach, which will hydrate the json api response into objects, which you can easily filter. Just keep in mind, that in this oop apporach everything is an object.
The data object - data entity
First of all you have to know, how your data is structured. From this structury you can build php objects. From the given JSON structure you can use the following objects.
namespace ApplicationEntity;
// Just for recognizing entities as entities later
interface EntityInterface
{
}
class Title implements EntityInterface, JsonSerializable
{
public $plain;
public function getPlain() : ?string
{
return $this->plain;
}
public function setPlain(string $plain) : Title
{
$this->plain = $plain;
return $this;
}
public function jsonSerialize() : array
{
return get_object_vars($this);
}
}
class Fieldset implements EntityInterface, JsonSerializable
{
/**
* Label object
* @var Label
*/
public $label;
/**
* Collection of Field objects
* @var ArrayObject
*/
public $fieldset;
// implement getter and setter methods here
}
class Section implements EntityInterface, JsonSerializable
{
public $title;
public $fieldsets;
public function getTitle() : ?Title
{
return $this->title;
}
public function setTitle(Title $title) : Section
{
$this->title = $title;
return $this;
}
public function getFieldsets() : ArrayObject
{
if (!$this->fieldsets) {
$this->fieldsets = new ArrayObject();
}
return $this->fieldsets;
}
public function setFieldsets(Fieldset $fieldset) : Section
{
if (!$this->fieldsets) {
$this->fieldsets = new ArrayObject();
}
$this->fieldsets->append($fieldset);
return $this;
}
public function jsonSerialize() : array
{
return get_object_vars($this);
}
}
Well, this class depicts the properties of the very first json object given in your example. Why this class implements the JsonSerializable interface? With this implementation you are able to transform the class structure back into a well formed json string. I 'm not sure, if you need that. But for sure it is safe, while communicating with a rest api. The only thing you have to do now is programming entities for every expected complex data structure / json object. You need the title object with a plin property and a fieldset object with label and fieldset properties and so on.
How to get the json data into a php object - hydration
Of course, your given json structure is a string. When we talk about hydration we actually mean converting a json string into an object structure. The above mentioned entites are needed for this approach.
But first the hydrator class itself.
namespace ApplicationHydrator;
use ApplicationEntityEntityInterface;
class ClassMethodsHydrator
{
protected $strategies;
public function hydrate(array $data, EntityInterface $entity) : EntityInterface
{
foreach ($data as $key => $value) {
if (!method_exists($entity, 'set' . ucfirst($key)) {
throw new InvalidArgumentException(sprintf(
'The method %s does not exist in %s',
get_class($entity)
));
}
if ($this->strategies[$key]) {
$strategy = $this->strategies[$key];
$value = $strategy->hydrate($value);
}
$entity->{'set' . ucfirst($key)}($value);
}
return $entity;
}
public function addStrategy(string $name, StrategyInterface $strategy) : Hydrator
{
$this->strategies[$name] = $strategy;
return $this;
}
}
Well, this is the class where all the magic happens. I guess this is what you mentioned as algorithm. The hydrator takes your data from the json response and pushes it into your entities. When having the entites hydrated, you can easily access the given data by calling the get methods of the entities.
As the json data is complex and nested, we have to use hydrator strategies. A common pattern in hydration concerns. A strategy can be hooked into a object property and executes another hydrator. So we make sure that we represent the nested data in an identical object structure.
Here 's an example of a hydrator strategy.
namespace ApplicationHydratorStrategy;
use ApplicationEntityEntityInterface;
interface HydratorStrategy
{
public function hydrate(array $value) : EntityInterface;
}
use ApplicationEntityTitle;
class TitleHydratorStrategy implements HydratorStrategy
{
public function hydrate(array $value) : EntityInterface
{
$value = (new ClassMethods())->hydrate($value, new Title);
return $value;
}
}
// Use case of a strategy
$data = json_decode$($response, true);
$section = (new ClassMethods())
->addStrategy('title', new TitleHydratorStrategy())
->hydrate($data, new Section());
So what a hydrator strategy actually does? While iterating over our json api response, there are severel elements, which are an object or contain objects. To hydrate this multidimensional structure correctly, we use strategies.
To stay with your example of the JSON response I 've added a simple use case. First we decode the json response into an assiciative, multidimensional array. After that we use our entities, hydrators and hydrator strategies to get an object, which contains all the data. The use case knows, that the title property in the JSON response is an object that should hydrated into our title entity, which contains the plain property.
At the end our hydrated object has a structure like this ...
ApplicationEntitySection {
public:title => ApplicationEntityTitle [
public:plain => string 'Send Money'
}
...
}
Actually you can access the properties with the getter methods of our entities.
echo $section->getTitle()->getPlain(); // echoes 'Send money'
Knowing how to hydrate our classes leads us to the next step. Aggregation!
Getting the full string with aggregation
Actually aggregation is a common design pattern in modern object orientated programming. Aggregation means no more and no less than the allocation of data. Let 's have a look at your posted JSON response. As we can see the fieldset property of our root object contains a collection of fieldset objects, that we can access via our getter and setter methods. With this in mind, we can create additional getter methods in our section entity. Let us expand our section entity with a getFullName
method.
...
public function getFullName() : string
{
$firstname = $lastname = '';
// fetch the personal info section
if ($this->getFieldsets()->offsetExists(0)) {
$personalInfoFieldset = $this->getFieldsets()->offsetGet(0)->getFiedlset()->offsetGet(0);
$firstname = $personalInfoFieldset->getField()->offsetGet(0)->getValue();
$lastname = $personalInfoFieldset->getField()->offsetGet(1)->getValue();
}
return $this->concatenate(' ', $firstname, $lastname);
}
public function concatenate(string $filler, ...$strings) : string
{
$string = '';
foreach ($strings as $partial) {
$string .= $partial . $filler;
}
return trim($string);
}
This example assumes, that both the first name and the last name are available in the very first item of the fieldset collection of the section entity. So we get Bob Hogan
as return value. The concatenate
method is just a little helper, which concatenates a number of strings with a filler (space).
Filter data using our entities and the FilterIterator class
Further you mentioned, that you have to find specific data by id. One possible solution coould be filtering our entities by a specific item with the Filter Iterator class.
namespace ApplicationFilter;
class PersonIdFilter extends FilterIterator
{
protected $id;
public function __construct(Iterator $iterator, string $id)
{
parent::__construct($iterator);
$this->id = $id;
}
public function accept()
{
$person = $this->getInnerIterator()->current();
return ($person->getId() == $this->id) ? true : false;
}
}
Because of using ArrayObject
classes for our collections we are able to use iterators to filter for a specific argument. In this case we filter for the id in our personal info fieldsets.
Starting from our hydration example we it could be something like the following code.
$personalIterator = $section->getFieldsets()->offsetGet(0)->getFieldset()->getIterator();
$filter = new PersonIdFilter($personalIterator, 'a_8');
foreach ($filter as $result) {
var_dump($result); // will output the first fieldset with the personal data
}
Too complex? Absolutely not!
As you said you want a scalable solution without nested iterations in a huge loop. In my eyes it makes sense not writing just a huge single function, wich iterates the json response and returns the data you want. Working with objects in this case makes mch more sense because of the high scalability. You can access all the data you want in a glimpse by calling the right getter methods. Furthermore the code is mich more readable than a huge function which is recursivly iterating again and again. In the above shown approach you only code once and reuse all the objects again and again.
Please keep in mind, the the above shown code is just a theoretical suggestion. It is not tested.
Actually there 's no need for a magic algorithm. Just a bit of php magic in form of entites, hydrators and filters.
In this answer you 'll get an object orientated php approach, which will hydrate the json api response into objects, which you can easily filter. Just keep in mind, that in this oop apporach everything is an object.
The data object - data entity
First of all you have to know, how your data is structured. From this structury you can build php objects. From the given JSON structure you can use the following objects.
namespace ApplicationEntity;
// Just for recognizing entities as entities later
interface EntityInterface
{
}
class Title implements EntityInterface, JsonSerializable
{
public $plain;
public function getPlain() : ?string
{
return $this->plain;
}
public function setPlain(string $plain) : Title
{
$this->plain = $plain;
return $this;
}
public function jsonSerialize() : array
{
return get_object_vars($this);
}
}
class Fieldset implements EntityInterface, JsonSerializable
{
/**
* Label object
* @var Label
*/
public $label;
/**
* Collection of Field objects
* @var ArrayObject
*/
public $fieldset;
// implement getter and setter methods here
}
class Section implements EntityInterface, JsonSerializable
{
public $title;
public $fieldsets;
public function getTitle() : ?Title
{
return $this->title;
}
public function setTitle(Title $title) : Section
{
$this->title = $title;
return $this;
}
public function getFieldsets() : ArrayObject
{
if (!$this->fieldsets) {
$this->fieldsets = new ArrayObject();
}
return $this->fieldsets;
}
public function setFieldsets(Fieldset $fieldset) : Section
{
if (!$this->fieldsets) {
$this->fieldsets = new ArrayObject();
}
$this->fieldsets->append($fieldset);
return $this;
}
public function jsonSerialize() : array
{
return get_object_vars($this);
}
}
Well, this class depicts the properties of the very first json object given in your example. Why this class implements the JsonSerializable interface? With this implementation you are able to transform the class structure back into a well formed json string. I 'm not sure, if you need that. But for sure it is safe, while communicating with a rest api. The only thing you have to do now is programming entities for every expected complex data structure / json object. You need the title object with a plin property and a fieldset object with label and fieldset properties and so on.
How to get the json data into a php object - hydration
Of course, your given json structure is a string. When we talk about hydration we actually mean converting a json string into an object structure. The above mentioned entites are needed for this approach.
But first the hydrator class itself.
namespace ApplicationHydrator;
use ApplicationEntityEntityInterface;
class ClassMethodsHydrator
{
protected $strategies;
public function hydrate(array $data, EntityInterface $entity) : EntityInterface
{
foreach ($data as $key => $value) {
if (!method_exists($entity, 'set' . ucfirst($key)) {
throw new InvalidArgumentException(sprintf(
'The method %s does not exist in %s',
get_class($entity)
));
}
if ($this->strategies[$key]) {
$strategy = $this->strategies[$key];
$value = $strategy->hydrate($value);
}
$entity->{'set' . ucfirst($key)}($value);
}
return $entity;
}
public function addStrategy(string $name, StrategyInterface $strategy) : Hydrator
{
$this->strategies[$name] = $strategy;
return $this;
}
}
Well, this is the class where all the magic happens. I guess this is what you mentioned as algorithm. The hydrator takes your data from the json response and pushes it into your entities. When having the entites hydrated, you can easily access the given data by calling the get methods of the entities.
As the json data is complex and nested, we have to use hydrator strategies. A common pattern in hydration concerns. A strategy can be hooked into a object property and executes another hydrator. So we make sure that we represent the nested data in an identical object structure.
Here 's an example of a hydrator strategy.
namespace ApplicationHydratorStrategy;
use ApplicationEntityEntityInterface;
interface HydratorStrategy
{
public function hydrate(array $value) : EntityInterface;
}
use ApplicationEntityTitle;
class TitleHydratorStrategy implements HydratorStrategy
{
public function hydrate(array $value) : EntityInterface
{
$value = (new ClassMethods())->hydrate($value, new Title);
return $value;
}
}
// Use case of a strategy
$data = json_decode$($response, true);
$section = (new ClassMethods())
->addStrategy('title', new TitleHydratorStrategy())
->hydrate($data, new Section());
So what a hydrator strategy actually does? While iterating over our json api response, there are severel elements, which are an object or contain objects. To hydrate this multidimensional structure correctly, we use strategies.
To stay with your example of the JSON response I 've added a simple use case. First we decode the json response into an assiciative, multidimensional array. After that we use our entities, hydrators and hydrator strategies to get an object, which contains all the data. The use case knows, that the title property in the JSON response is an object that should hydrated into our title entity, which contains the plain property.
At the end our hydrated object has a structure like this ...
ApplicationEntitySection {
public:title => ApplicationEntityTitle [
public:plain => string 'Send Money'
}
...
}
Actually you can access the properties with the getter methods of our entities.
echo $section->getTitle()->getPlain(); // echoes 'Send money'
Knowing how to hydrate our classes leads us to the next step. Aggregation!
Getting the full string with aggregation
Actually aggregation is a common design pattern in modern object orientated programming. Aggregation means no more and no less than the allocation of data. Let 's have a look at your posted JSON response. As we can see the fieldset property of our root object contains a collection of fieldset objects, that we can access via our getter and setter methods. With this in mind, we can create additional getter methods in our section entity. Let us expand our section entity with a getFullName
method.
...
public function getFullName() : string
{
$firstname = $lastname = '';
// fetch the personal info section
if ($this->getFieldsets()->offsetExists(0)) {
$personalInfoFieldset = $this->getFieldsets()->offsetGet(0)->getFiedlset()->offsetGet(0);
$firstname = $personalInfoFieldset->getField()->offsetGet(0)->getValue();
$lastname = $personalInfoFieldset->getField()->offsetGet(1)->getValue();
}
return $this->concatenate(' ', $firstname, $lastname);
}
public function concatenate(string $filler, ...$strings) : string
{
$string = '';
foreach ($strings as $partial) {
$string .= $partial . $filler;
}
return trim($string);
}
This example assumes, that both the first name and the last name are available in the very first item of the fieldset collection of the section entity. So we get Bob Hogan
as return value. The concatenate
method is just a little helper, which concatenates a number of strings with a filler (space).
Filter data using our entities and the FilterIterator class
Further you mentioned, that you have to find specific data by id. One possible solution coould be filtering our entities by a specific item with the Filter Iterator class.
namespace ApplicationFilter;
class PersonIdFilter extends FilterIterator
{
protected $id;
public function __construct(Iterator $iterator, string $id)
{
parent::__construct($iterator);
$this->id = $id;
}
public function accept()
{
$person = $this->getInnerIterator()->current();
return ($person->getId() == $this->id) ? true : false;
}
}
Because of using ArrayObject
classes for our collections we are able to use iterators to filter for a specific argument. In this case we filter for the id in our personal info fieldsets.
Starting from our hydration example we it could be something like the following code.
$personalIterator = $section->getFieldsets()->offsetGet(0)->getFieldset()->getIterator();
$filter = new PersonIdFilter($personalIterator, 'a_8');
foreach ($filter as $result) {
var_dump($result); // will output the first fieldset with the personal data
}
Too complex? Absolutely not!
As you said you want a scalable solution without nested iterations in a huge loop. In my eyes it makes sense not writing just a huge single function, wich iterates the json response and returns the data you want. Working with objects in this case makes mch more sense because of the high scalability. You can access all the data you want in a glimpse by calling the right getter methods. Furthermore the code is mich more readable than a huge function which is recursivly iterating again and again. In the above shown approach you only code once and reuse all the objects again and again.
Please keep in mind, the the above shown code is just a theoretical suggestion. It is not tested.
answered Nov 25 '18 at 14:16
MarcelMarcel
2,1401816
2,1401816
Brilliant. I like the use of the Hydrator Strategy pattern. That makes a lot of sense. Do you think that having a huge number of responses being kept in objects would have a considerable memory impact? I'm just trying to think in terms of performance.
– lsimonetti
Nov 27 '18 at 13:59
I guess this kind of traversing through deeply nested data sets would affect the memory usage. As php7 optimized a lot concerning memory while handling objects and object iteration this approach would use a minimum of more memory. Actually this approach is used by zend framework and works very well. If you want to optimize the memory usage a bit, you can try to use generators when it comes to filtering the objects. PHP generators implement automatically the iterator interface while using fewer memory. I haven 't tried to yield a generator from an array object. Might be a possible solution.
– Marcel
Nov 27 '18 at 19:39
add a comment |
Brilliant. I like the use of the Hydrator Strategy pattern. That makes a lot of sense. Do you think that having a huge number of responses being kept in objects would have a considerable memory impact? I'm just trying to think in terms of performance.
– lsimonetti
Nov 27 '18 at 13:59
I guess this kind of traversing through deeply nested data sets would affect the memory usage. As php7 optimized a lot concerning memory while handling objects and object iteration this approach would use a minimum of more memory. Actually this approach is used by zend framework and works very well. If you want to optimize the memory usage a bit, you can try to use generators when it comes to filtering the objects. PHP generators implement automatically the iterator interface while using fewer memory. I haven 't tried to yield a generator from an array object. Might be a possible solution.
– Marcel
Nov 27 '18 at 19:39
Brilliant. I like the use of the Hydrator Strategy pattern. That makes a lot of sense. Do you think that having a huge number of responses being kept in objects would have a considerable memory impact? I'm just trying to think in terms of performance.
– lsimonetti
Nov 27 '18 at 13:59
Brilliant. I like the use of the Hydrator Strategy pattern. That makes a lot of sense. Do you think that having a huge number of responses being kept in objects would have a considerable memory impact? I'm just trying to think in terms of performance.
– lsimonetti
Nov 27 '18 at 13:59
I guess this kind of traversing through deeply nested data sets would affect the memory usage. As php7 optimized a lot concerning memory while handling objects and object iteration this approach would use a minimum of more memory. Actually this approach is used by zend framework and works very well. If you want to optimize the memory usage a bit, you can try to use generators when it comes to filtering the objects. PHP generators implement automatically the iterator interface while using fewer memory. I haven 't tried to yield a generator from an array object. Might be a possible solution.
– Marcel
Nov 27 '18 at 19:39
I guess this kind of traversing through deeply nested data sets would affect the memory usage. As php7 optimized a lot concerning memory while handling objects and object iteration this approach would use a minimum of more memory. Actually this approach is used by zend framework and works very well. If you want to optimize the memory usage a bit, you can try to use generators when it comes to filtering the objects. PHP generators implement automatically the iterator interface while using fewer memory. I haven 't tried to yield a generator from an array object. Might be a possible solution.
– Marcel
Nov 27 '18 at 19:39
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53421756%2ftraversing-through-deeply-nested-json-object%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown