Page MenuHomeSealhub

No OneTemporary

diff --git a/src/parser/PhutilJSON.php b/src/parser/PhutilJSON.php
index 0bcc4f76..5f43a625 100644
--- a/src/parser/PhutilJSON.php
+++ b/src/parser/PhutilJSON.php
@@ -1,155 +1,161 @@
<?php
/**
* Utilities for wrangling JSON.
*
* @task pretty Formatting JSON Objects
* @task internal Internals
*/
final class PhutilJSON extends Phobject {
/* -( Formatting JSON Objects )-------------------------------------------- */
/**
* Encode an object in JSON and pretty-print it. This generates a valid JSON
* object with human-readable whitespace and indentation.
*
* @param dict An object to encode in JSON.
* @return string Pretty-printed object representation.
*/
- public function encodeFormatted(array $object) {
+ public function encodeFormatted($object) {
return $this->encodeFormattedObject($object, 0)."\n";
}
/**
* Encode a list in JSON and pretty-print it, discarding keys.
*
* @param list<wild> List to encode in JSON.
* @return string Pretty-printed list representation.
*/
public function encodeAsList(array $list) {
return $this->encodeFormattedArray($list, 0)."\n";
}
/* -( Internals )---------------------------------------------------------- */
/**
* Pretty-print a JSON object.
*
* @param dict Object to format.
* @param int Current depth, for indentation.
* @return string Pretty-printed value.
* @task internal
*/
private function encodeFormattedObject($object, $depth) {
+ if ($object instanceof stdClass) {
+ $object = (array)$object;
+ }
+
if (empty($object)) {
return '{}';
}
$pre = $this->getIndent($depth);
$key_pre = $this->getIndent($depth + 1);
$keys = array();
$vals = array();
$max = 0;
foreach ($object as $key => $val) {
$ekey = $this->encodeFormattedValue((string)$key, 0);
$max = max($max, strlen($ekey));
$keys[] = $ekey;
$vals[] = $this->encodeFormattedValue($val, $depth + 1);
}
$key_lines = array();
foreach ($keys as $k => $key) {
$key_lines[] = $key_pre.$key.': '.$vals[$k];
}
$key_lines = implode(",\n", $key_lines);
$out = "{\n";
$out .= $key_lines;
$out .= "\n";
$out .= $pre.'}';
return $out;
}
/**
* Pretty-print a JSON list.
*
* @param list List to format.
* @param int Current depth, for indentation.
* @return string Pretty-printed value.
* @task internal
*/
private function encodeFormattedArray($array, $depth) {
if (empty($array)) {
return '[]';
}
$pre = $this->getIndent($depth);
$val_pre = $this->getIndent($depth + 1);
$vals = array();
foreach ($array as $val) {
$vals[] = $val_pre.$this->encodeFormattedValue($val, $depth + 1);
}
$val_lines = implode(",\n", $vals);
$out = "[\n";
$out .= $val_lines;
$out .= "\n";
$out .= $pre.']';
return $out;
}
/**
* Pretty-print a JSON value.
*
* @param dict Value to format.
* @param int Current depth, for indentation.
* @return string Pretty-printed value.
* @task internal
*/
private function encodeFormattedValue($value, $depth) {
if (is_array($value)) {
if (phutil_is_natural_list($value)) {
return $this->encodeFormattedArray($value, $depth);
} else {
return $this->encodeFormattedObject($value, $depth);
}
+ } else if (is_object($value)) {
+ return $this->encodeFormattedObject($value, $depth);
} else {
if (defined('JSON_UNESCAPED_SLASHES')) {
// If we have a new enough version of PHP, disable escaping of slashes
// when pretty-printing values. Escaping slashes can defuse an attack
// where the attacker embeds "</script>" inside a JSON string, but that
// isn't relevant when rendering JSON for human viewers.
return json_encode($value, JSON_UNESCAPED_SLASHES);
} else {
return json_encode($value);
}
}
}
/**
* Render a string corresponding to the current indent depth.
*
* @param int Current depth.
* @return string Indentation.
* @task internal
*/
private function getIndent($depth) {
if (!$depth) {
return '';
} else {
return str_repeat(' ', $depth);
}
}
}
diff --git a/src/parser/__tests__/PhutilJSONTestCase.php b/src/parser/__tests__/PhutilJSONTestCase.php
index 295d7b55..63630a9d 100644
--- a/src/parser/__tests__/PhutilJSONTestCase.php
+++ b/src/parser/__tests__/PhutilJSONTestCase.php
@@ -1,21 +1,50 @@
<?php
final class PhutilJSONTestCase extends PhutilTestCase {
public function testEmptyArrayEncoding() {
$serializer = new PhutilJSON();
$expect = <<<EOJSON
{
"x": []
}
EOJSON;
$this->assertEqual(
$expect,
$serializer->encodeFormatted(array('x' => array())),
pht('Empty arrays should serialize as `%s`, not `%s`.', '[]', '{}'));
}
+ public function testNestedObjectEncoding() {
+ $expect = <<<EOJSON
+{
+ "empty-object": {},
+ "pair-object": {
+ "duck": "quack"
+ }
+}
+
+EOJSON;
+
+ $empty_object = new stdClass();
+
+ $pair_object = new stdClass();
+ $pair_object->duck = 'quack';
+
+ $input = (object)array(
+ 'empty-object' => $empty_object,
+ 'pair-object' => $pair_object,
+ );
+
+ $serializer = new PhutilJSON();
+
+ $this->assertEqual(
+ $expect,
+ $serializer->encodeFormatted($input),
+ pht('Serialization of PHP-object JSON values.'));
+ }
+
}

File Metadata

Mime Type
text/x-diff
Expires
Fri, Jan 24, 04:34 (1 d, 11 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
601540
Default Alt Text
(5 KB)

Event Timeline