Skip to content

Commit

Permalink
Merge pull request #4080 from caswell-wc/get-json-var
Browse files Browse the repository at this point in the history
Get JSON Variable
  • Loading branch information
paulbalandan authored Jan 28, 2021
2 parents 6e356e2 + 53a329d commit ee4874e
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 2 deletions.
42 changes: 41 additions & 1 deletion system/HTTP/IncomingRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ public function isSecure(): bool
//--------------------------------------------------------------------

/**
* Fetch an item from the $_REQUEST object. This is the simplest way
* Fetch an item from the $_REQUEST object or a JSON input stream. This is the simplest way
* to grab data from the request object and can be used in lieu of the
* other get* methods in most cases.
*
Expand All @@ -300,6 +300,26 @@ public function isSecure(): bool
*/
public function getVar($index = null, $filter = null, $flags = null)
{
if ($this->isJSON())
{
if (is_null($index))
{
return $this->getJSON();
}

if (is_array($index))
{
$output = [];
foreach ($index as $key)
{
$output[$key] = $this->getJsonVar($key);
}
return $output;
}

return $this->getJsonVar($index);
}

return $this->fetchGlobal('request', $index, $filter, $flags);
}

Expand All @@ -325,6 +345,26 @@ public function getJSON(bool $assoc = false, int $depth = 512, int $options = 0)
return json_decode($this->body, $assoc, $depth, $options);
}

/**
* Get a specific variable from a JSON input stream
*
* @param string $index The variable that you want which can use dot syntax for getting specific values.
* @param boolean $assoc If true, return the result as an associative array.
*
* @return mixed
*/
public function getJsonVar(string $index, bool $assoc = false)
{
helper('array');

$data = dot_array_search($index, $this->getJSON(true));
if (is_array($data) && ! $assoc)
{
return json_decode(json_encode($data));
}
return $data;
}

//--------------------------------------------------------------------

/**
Expand Down
2 changes: 1 addition & 1 deletion system/HTTP/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ public function getProtocolVersion(): string
*
* @deprecated Use header calls directly
*/
public function isJSON()
public function isJSON()
{
if (! $this->hasHeader('Content-Type'))
{
Expand Down
71 changes: 71 additions & 0 deletions tests/system/HTTP/IncomingRequestTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,77 @@ public function testCanGrabGetRawJSON()
$this->assertEquals($expected, $request->getJSON(true));
}

public function testCanGetAVariableFromJson()
{
$jsonObj = [
'foo' => 'bar',
'baz' => [
'fizz' => 'buzz',
],
];
$json = json_encode($jsonObj);

$config = new App();
$config->baseURL = 'http://example.com/';

$request = new IncomingRequest($config, new URI(), $json, new UserAgent());

$this->assertEquals('bar', $request->getJsonVar('foo'));
$jsonVar = $request->getJsonVar('baz');
$this->assertIsObject($jsonVar);
$this->assertEquals('buzz', $jsonVar->fizz);
$this->assertEquals('buzz', $request->getJsonVar('baz.fizz'));
}

public function testGetJsonVarAsArray()
{
$jsonObj = [
'baz' => [
'fizz' => 'buzz',
'foo' => 'bar',
],
];
$json = json_encode($jsonObj);

$config = new App();
$config->baseURL = 'http://example.com/';

$request = new IncomingRequest($config, new URI(), $json, new UserAgent());

$jsonVar = $request->getJsonVar('baz', true);
$this->assertIsArray($jsonVar);
$this->assertEquals('buzz', $jsonVar['fizz']);
$this->assertEquals('bar', $jsonVar['foo']);
}

public function testGetVarWorksWithJson()
{
$jsonObj = [
'foo' => 'bar',
'fizz' => 'buzz',
];
$json = json_encode($jsonObj);

$config = new App();
$config->baseURL = 'http://example.com/';

$request = new IncomingRequest($config, new URI(), $json, new UserAgent());
$request->setHeader('Content-Type', 'application/json');

$this->assertEquals('bar', $request->getVar('foo'));
$this->assertEquals('buzz', $request->getVar('fizz'));

$multiple = $request->getVar(['foo', 'fizz']);
$this->assertIsArray($multiple);
$this->assertEquals('bar', $multiple['foo']);
$this->assertEquals('buzz', $multiple['fizz']);

$all = $request->getVar();
$this->assertIsObject($all);
$this->assertEquals('bar', $all->foo);
$this->assertEquals('buzz', $all->fizz);
}

public function testCanGrabGetRawInput()
{
$rawstring = 'username=admin001&role=administrator&usepass=0';
Expand Down
39 changes: 39 additions & 0 deletions user_guide_src/source/incoming/incomingrequest.rst
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,45 @@ arrays, pass in ``true`` as the first parameter.
The second and third parameters match up to the ``depth`` and ``options`` arguments of the
`json_decode <https://www.php.net/manual/en/function.json-decode.php>`_ PHP function.

If the incoming request has a ``CONTENT_TYPE`` header set to "application/json", you can also use ``getVar()`` to get
the JSON stream. Using ``getVar()`` in this way will always return an object.

**Get Specific Data from JSON**

You can get a specific piece of data from a JSON stream by passing a variable name into ``getVar()`` for the
data that you want or you can use "dot" notation to dig into the JSON to get data that is not on the root level.

::

//With a request body of:
{
"foo": "bar",
"fizz": {
"buzz": "baz"
}
}
$data = $request->getVar('foo');
//$data = "bar"

$data = $request->getVar('fizz.buzz');
//$data = "baz"


If you want the result to be an associative array instead of an object, you can use ``getJsonVar()`` instead and pass
true in the second parameter. This function can also be used if you can't guarantee that the incoming request will have the
correct ``CONTENT_TYPE`` header.

::

//With the same request as above
$data = $request->getJsonVar('fizz');
//$data->buzz = "baz"

$data = $request->getJsonVar('fizz', true);
//$data = ["buzz" => "baz"]

.. note:: See the documentation for ``dot_array_search()`` in the ``Array`` helper for more information on "dot" notation.

**Retrieving Raw data (PUT, PATCH, DELETE)**

Finally, you can grab the contents of php://input as a raw stream with ``getRawInput()``::
Expand Down

0 comments on commit ee4874e

Please sign in to comment.