Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get JSON Variable #4080

Merged
merged 3 commits into from
Jan 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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