Page MenuHomePhabricator

D9627.id23091.diff
No OneTemporary

D9627.id23091.diff

diff --git a/externals/jsonlint/src/Seld/JsonLint/JsonParser.php b/externals/jsonlint/src/Seld/JsonLint/JsonParser.php
--- a/externals/jsonlint/src/Seld/JsonLint/JsonParser.php
+++ b/externals/jsonlint/src/Seld/JsonLint/JsonParser.php
@@ -374,7 +374,7 @@
case 17:
$yyval->token = $tokens[$len-2];
$key = $tokens[$len][0] === '' ? '_empty_' : $tokens[$len][0];
- if (($this->flags & self::DETECT_KEY_CONFLICTS) && isset($tokens[$len-2]->{$key})) {
+ if (($this->flags & self::DETECT_KEY_CONFLICTS) && isset($tokens[$len-2][$key])) {
$errStr = 'Parse error on line ' . ($yylineno+1) . ":\n";
$errStr .= $this->lexer->showPosition() . "\n";
$errStr .= "Duplicate key: ".$tokens[$len][0];
diff --git a/src/parser/PhutilJSONParser.php b/src/parser/PhutilJSONParser.php
--- a/src/parser/PhutilJSONParser.php
+++ b/src/parser/PhutilJSONParser.php
@@ -8,6 +8,12 @@
*/
final class PhutilJSONParser {
+ private $allowDuplicateKeys = false;
+
+ public function setAllowDuplicateKeys($allow_duplicate_keys) {
+ $this->allowDuplicateKeys = $allow_duplicate_keys;
+ }
+
public function parse($json) {
$jsonlint_root = phutil_get_library_root('phutil').'/../externals/jsonlint';
require_once($jsonlint_root.'/src/Seld/JsonLint/JsonParser.php');
@@ -21,18 +27,30 @@
$parser = new JsonLintJsonParser();
try {
- return $parser->parse($json);
+ return $parser->parse($json, $this->getFlags());
} catch (JsonLintParsingException $ex) {
$details = $ex->getDetails();
$message = preg_replace("/^Parse error .*\\^\n/s", '', $ex->getMessage());
throw new PhutilJSONParserException(
- $details['loc']['last_line'],
- $details['loc']['last_column'],
- $details['token'],
- $details['expected'],
+ idx(idx($details, 'loc', array()), 'last_line'),
+ idx(idx($details, 'loc', array()), 'last_column'),
+ idx($details, 'token'),
+ idx($details, 'expected'),
$message);
}
}
+ private function getFlags() {
+ $flags = 0;
+
+ if ($this->allowDuplicateKeys) {
+ $flags |= JsonLintJsonParser::ALLOW_DUPLICATE_KEYS;
+ } else {
+ $flags |= JsonLintJsonParser::DETECT_KEY_CONFLICTS;
+ }
+
+ return $flags;
+ }
+
}
diff --git a/src/parser/__tests__/PhutilJSONParserTestCase.php b/src/parser/__tests__/PhutilJSONParserTestCase.php
--- a/src/parser/__tests__/PhutilJSONParserTestCase.php
+++ b/src/parser/__tests__/PhutilJSONParserTestCase.php
@@ -85,4 +85,29 @@
}
}
+ public function testDuplicateKeys() {
+ $parser = new PhutilJSONParser();
+
+ $tests = array(
+ '{"foo": "bar", "foo": "baz"}' => array('foo' => 'bar'),
+ );
+
+ foreach ($tests as $input => $expect) {
+ $parser->setAllowDuplicateKeys(true);
+ $this->assertEqual(
+ $expect,
+ $parser->parse($input),
+ 'Parsing JSON: '.$input);
+
+ $parser->setAllowDuplicateKeys(false);
+ $caught = null;
+ try {
+ $parser->parse($input);
+ } catch (Exception $ex) {
+ $caught = $ex;
+ }
+ $this->assertTrue($caught instanceof PhutilJSONParserException);
+ }
+ }
+
}

File Metadata

Mime Type
text/plain
Expires
Thu, Mar 20, 1:31 AM (4 d, 19 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7712309
Default Alt Text
D9627.id23091.diff (3 KB)

Event Timeline