Skip to content

Commit ee4874e

Browse files
authored
Merge pull request #4080 from caswell-wc/get-json-var
Get JSON Variable
2 parents 6e356e2 + 53a329d commit ee4874e

4 files changed

Lines changed: 152 additions & 2 deletions

File tree

system/HTTP/IncomingRequest.php

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ public function isSecure(): bool
288288
//--------------------------------------------------------------------
289289

290290
/**
291-
* Fetch an item from the $_REQUEST object. This is the simplest way
291+
* Fetch an item from the $_REQUEST object or a JSON input stream. This is the simplest way
292292
* to grab data from the request object and can be used in lieu of the
293293
* other get* methods in most cases.
294294
*
@@ -300,6 +300,26 @@ public function isSecure(): bool
300300
*/
301301
public function getVar($index = null, $filter = null, $flags = null)
302302
{
303+
if ($this->isJSON())
304+
{
305+
if (is_null($index))
306+
{
307+
return $this->getJSON();
308+
}
309+
310+
if (is_array($index))
311+
{
312+
$output = [];
313+
foreach ($index as $key)
314+
{
315+
$output[$key] = $this->getJsonVar($key);
316+
}
317+
return $output;
318+
}
319+
320+
return $this->getJsonVar($index);
321+
}
322+
303323
return $this->fetchGlobal('request', $index, $filter, $flags);
304324
}
305325

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

348+
/**
349+
* Get a specific variable from a JSON input stream
350+
*
351+
* @param string $index The variable that you want which can use dot syntax for getting specific values.
352+
* @param boolean $assoc If true, return the result as an associative array.
353+
*
354+
* @return mixed
355+
*/
356+
public function getJsonVar(string $index, bool $assoc = false)
357+
{
358+
helper('array');
359+
360+
$data = dot_array_search($index, $this->getJSON(true));
361+
if (is_array($data) && ! $assoc)
362+
{
363+
return json_decode(json_encode($data));
364+
}
365+
return $data;
366+
}
367+
328368
//--------------------------------------------------------------------
329369

330370
/**

system/HTTP/Message.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ public function getProtocolVersion(): string
140140
*
141141
* @deprecated Use header calls directly
142142
*/
143-
public function isJSON()
143+
public function isJSON()
144144
{
145145
if (! $this->hasHeader('Content-Type'))
146146
{

tests/system/HTTP/IncomingRequestTest.php

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,77 @@ public function testCanGrabGetRawJSON()
298298
$this->assertEquals($expected, $request->getJSON(true));
299299
}
300300

301+
public function testCanGetAVariableFromJson()
302+
{
303+
$jsonObj = [
304+
'foo' => 'bar',
305+
'baz' => [
306+
'fizz' => 'buzz',
307+
],
308+
];
309+
$json = json_encode($jsonObj);
310+
311+
$config = new App();
312+
$config->baseURL = 'http://example.com/';
313+
314+
$request = new IncomingRequest($config, new URI(), $json, new UserAgent());
315+
316+
$this->assertEquals('bar', $request->getJsonVar('foo'));
317+
$jsonVar = $request->getJsonVar('baz');
318+
$this->assertIsObject($jsonVar);
319+
$this->assertEquals('buzz', $jsonVar->fizz);
320+
$this->assertEquals('buzz', $request->getJsonVar('baz.fizz'));
321+
}
322+
323+
public function testGetJsonVarAsArray()
324+
{
325+
$jsonObj = [
326+
'baz' => [
327+
'fizz' => 'buzz',
328+
'foo' => 'bar',
329+
],
330+
];
331+
$json = json_encode($jsonObj);
332+
333+
$config = new App();
334+
$config->baseURL = 'http://example.com/';
335+
336+
$request = new IncomingRequest($config, new URI(), $json, new UserAgent());
337+
338+
$jsonVar = $request->getJsonVar('baz', true);
339+
$this->assertIsArray($jsonVar);
340+
$this->assertEquals('buzz', $jsonVar['fizz']);
341+
$this->assertEquals('bar', $jsonVar['foo']);
342+
}
343+
344+
public function testGetVarWorksWithJson()
345+
{
346+
$jsonObj = [
347+
'foo' => 'bar',
348+
'fizz' => 'buzz',
349+
];
350+
$json = json_encode($jsonObj);
351+
352+
$config = new App();
353+
$config->baseURL = 'http://example.com/';
354+
355+
$request = new IncomingRequest($config, new URI(), $json, new UserAgent());
356+
$request->setHeader('Content-Type', 'application/json');
357+
358+
$this->assertEquals('bar', $request->getVar('foo'));
359+
$this->assertEquals('buzz', $request->getVar('fizz'));
360+
361+
$multiple = $request->getVar(['foo', 'fizz']);
362+
$this->assertIsArray($multiple);
363+
$this->assertEquals('bar', $multiple['foo']);
364+
$this->assertEquals('buzz', $multiple['fizz']);
365+
366+
$all = $request->getVar();
367+
$this->assertIsObject($all);
368+
$this->assertEquals('bar', $all->foo);
369+
$this->assertEquals('buzz', $all->fizz);
370+
}
371+
301372
public function testCanGrabGetRawInput()
302373
{
303374
$rawstring = 'username=admin001&role=administrator&usepass=0';

user_guide_src/source/incoming/incomingrequest.rst

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,45 @@ arrays, pass in ``true`` as the first parameter.
141141
The second and third parameters match up to the ``depth`` and ``options`` arguments of the
142142
`json_decode <https://www.php.net/manual/en/function.json-decode.php>`_ PHP function.
143143

144+
If the incoming request has a ``CONTENT_TYPE`` header set to "application/json", you can also use ``getVar()`` to get
145+
the JSON stream. Using ``getVar()`` in this way will always return an object.
146+
147+
**Get Specific Data from JSON**
148+
149+
You can get a specific piece of data from a JSON stream by passing a variable name into ``getVar()`` for the
150+
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.
151+
152+
::
153+
154+
//With a request body of:
155+
{
156+
"foo": "bar",
157+
"fizz": {
158+
"buzz": "baz"
159+
}
160+
}
161+
$data = $request->getVar('foo');
162+
//$data = "bar"
163+
164+
$data = $request->getVar('fizz.buzz');
165+
//$data = "baz"
166+
167+
168+
If you want the result to be an associative array instead of an object, you can use ``getJsonVar()`` instead and pass
169+
true in the second parameter. This function can also be used if you can't guarantee that the incoming request will have the
170+
correct ``CONTENT_TYPE`` header.
171+
172+
::
173+
174+
//With the same request as above
175+
$data = $request->getJsonVar('fizz');
176+
//$data->buzz = "baz"
177+
178+
$data = $request->getJsonVar('fizz', true);
179+
//$data = ["buzz" => "baz"]
180+
181+
.. note:: See the documentation for ``dot_array_search()`` in the ``Array`` helper for more information on "dot" notation.
182+
144183
**Retrieving Raw data (PUT, PATCH, DELETE)**
145184

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

0 commit comments

Comments
 (0)