Details
- Reviewers
epriestley - Group Reviewers
Blessed Reviewers - Maniphest Tasks
- T5297: Create a native JSON parser.
- Commits
- rPHUdd7f571b61ed: Modify the JsonLint library to return `array` instead of `stdClass`.
Wrote a few additional test cases.
Diff Detail
- Repository
- rPHU libphutil
- Branch
- json2
- Lint
Lint Passed - Unit
Test Failures - Build Status
Buildable 1248 Build 1248: [Placeholder Plan] Wait for 30 Seconds
Time | Test | |
---|---|---|
0 ms | testValidJSON | |
0 ms | testBadStartRule | |
0 ms | testBogusGrammar | |
0 ms | testBugtraq | |
0 ms | testCanonicalize | |
View Full Test Results (1 Failed · 36 Passed) |
Event Timeline
Hmm, the empty string handling seems funky. Does that get cleaned up somewhere non-obvious? We should probably have a test case for it, regardless, since it has magical logic.
externals/jsonlint/src/Seld/JsonLint/JsonParser.php | ||
---|---|---|
361 | Is it practical/easier to fix this to array()? (And on line 374)? | |
371 | This _empty_ stuff seems wrong. {"":1} should parse like array('' => 1), but I'm guessing we end up with _empty_ on the way out of the parser instead? |
The other way would be to fix JsonLintLexer. If you pass an empty string into JsonLintJsonParser, the following warning is raised:
ERROR 2: str_repeat(): Second argument has to be greater than or equal to 0 at [/home/joshua/workspace/github.com/phacility/libphutil/externals/jsonlint/src/Seld/JsonLint/Lexer.php:82]
externals/jsonlint/src/Seld/JsonLint/JsonParser.php | ||
---|---|---|
361 | This was my initial approach... I think the issue here was that I wasn't able to later differentiate if something was a JSON object or a JSON array. | |
371 | Yeah I agree... I don't know why they have done this. I imagine we will strip this out. |
I wasn't able to later differentiate if something was a JSON object or a JSON array.
Hrrm, is this important?
If we want to retain the ability to distinguish between the two, we should probably export the stdClass from the parser, then recursively walk applying (array) casts it if some option is set.
I'm guessing the _empty_ junk is because PHP might not allow the empty string in property names, though:
$ php -r '$empty = ""; $o = (object)array(); $o->$empty = "x"; print_r($o);' PHP Fatal error: Cannot access empty property in Command line code on line 1 PHP Stack trace: PHP 1. {main}() Command line code:0
I guess we could also define class JSONNode implements ArrayAccess, and have that support both empty strings and some object vs array flag, to solve both problems. But: ugh, gross.
I'd suggest:
- For now, don't worry about distinguishing, and just always use array()?
- If we have a need to distinguish later, we can add a mode flag and implement something like JSONNode to work around the empty property issue?
No, I actually couldn't get the unit tests passing when using array() instead of new stdClass. Perhaps I was missing something though. Let me try again
This doesn't work... and I'm not sure why:
Assertion failed, expected values to be equal (at PhutilJSONParserTestCase.php:24): Parsing JSON: {"foo": "bar", "bar": ["baz"]} Expected vs Actual Output Diff --- Old Value +++ New Value @@ -1,10 +1,5 @@ Array ( [foo] => bar - [bar] => Array - ( - [0] => baz - ) - )
I think I got it -- that was tricky!
externals/jsonlint/src/Seld/JsonLint/JsonParser.php | ||
---|---|---|
386 | (This should be an index access now.) | |
389 | This is the actual bug, and should be $yyval->token[$key] = .... Since the thing is an array now, it gets copy-on-write semantics. Previously, as an object, it had reference semantics. |
Also, the isset() checks should probably be array_key_exists($key, $array) checks. I'd expect them to work incorrectly when the value is null. I think that's an existing bug with the upstream implementation.
externals/jsonlint/src/Seld/JsonLint/JsonParser.php | ||
---|---|---|
386 | This should probably become array_key_exists() as well. |