This repository has been archived by the owner on May 31, 2020. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 424
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #586 from abonie/json_decoding
Json decoding
- Loading branch information
Showing
7 changed files
with
630 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
var types = require('../../types') | ||
var core = require('../../core') | ||
var PyObject = core.Object | ||
var exceptions = core.exceptions | ||
var callables = core.callables | ||
var validateParams = require('./utils').validateParams | ||
|
||
function JSONDecoder() { | ||
PyObject.call(this) | ||
} | ||
|
||
core.create_pyclass(JSONDecoder, 'JSONDecoder') | ||
|
||
// TODO(abonie): actual defaults? | ||
const decoder_defaults = { | ||
'object_hook': null, | ||
'parse_float': null, | ||
'parse_int': null, | ||
'parse_constant': null, | ||
'object_pairs_hook': null | ||
} | ||
|
||
function _JSONDecoder(args = [], kwargs = {}) { | ||
var keywords = [ | ||
'object_hook', | ||
'parse_float', | ||
'parse_int', | ||
'parse_constant', | ||
'strict', | ||
'object_pairs_hook' | ||
] | ||
var params = validateParams({ | ||
args: args, | ||
kwargs: kwargs, | ||
names: keywords, | ||
defaults: Object.assign({'strict': true}, decoder_defaults), | ||
funcName: 'JSONDecoder' | ||
}) | ||
|
||
var dec = new JSONDecoder() | ||
Object.assign(dec, params) | ||
|
||
return dec | ||
} | ||
|
||
_JSONDecoder.$pyargs = true | ||
|
||
JSONDecoder.prototype.decode = function(s) { | ||
// TODO(abonie): what if call to object_hook changes decoder's object_hook property? | ||
var object_hook = this.object_hook | ||
var reviver = (k, v) => types.js2py(v) | ||
if (object_hook !== null && !types.isinstance(object_hook, types.NoneType)) { | ||
reviver = function(k, v) { | ||
var o = types.js2py(v) | ||
if (types.isinstance(o, types.Dict)) { | ||
o = callables.call_function(object_hook, [o], null) | ||
} | ||
return o | ||
} | ||
} | ||
|
||
var ret | ||
try { | ||
ret = JSON.parse(s, reviver) | ||
} catch (e) { | ||
throw new exceptions.ValueError.$pyclass(e.message) | ||
} | ||
return ret | ||
} | ||
|
||
var loads = function(args, kwargs) { | ||
var keywords = [ | ||
's', | ||
'encoding', | ||
'cls', | ||
'object_hook', | ||
'parse_float', | ||
'parse_int', | ||
'parse_constant', | ||
'object_pairs_hook' | ||
] | ||
var params = validateParams({ | ||
args: args, | ||
kwargs: kwargs, | ||
names: keywords, | ||
defaults: Object.assign({'encoding': null, 'cls': _JSONDecoder}, decoder_defaults), | ||
numRequired: 1, | ||
funcName: 'loads' | ||
}) | ||
var cls = params['cls'] | ||
var s = params['s'] | ||
delete params['cls'] | ||
delete params['s'] | ||
delete params['encoding'] | ||
params['strict'] = true | ||
|
||
// TODO(abonie): possible bug here? see test_cls in tests | ||
var dec = callables.call_function(cls, [], params) | ||
return callables.call_method(dec, 'decode', [s]) | ||
} | ||
|
||
loads.$pyargs = true | ||
|
||
var load = function(args, kwargs) { | ||
var keywords = [ | ||
'fp', | ||
'cls', | ||
'object_hook', | ||
'parse_float', | ||
'parse_int', | ||
'parse_constant', | ||
'object_pairs_hook' | ||
] | ||
var params = validateParams({ | ||
args: args, | ||
kwargs: kwargs, | ||
names: keywords, | ||
defaults: Object.assign({'cls': _JSONDecoder}, decoder_defaults), | ||
numRequired: 1, | ||
funcName: 'load' | ||
}) | ||
|
||
var fp = params['fp'] | ||
delete params['fp'] | ||
|
||
var s = callables.call_method(fp, 'read', []) | ||
return loads([s], params) | ||
} | ||
|
||
load.$pyargs = true | ||
|
||
module.exports = { | ||
'loads': loads, | ||
'load': load, | ||
'JSONDecoder': _JSONDecoder | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
# from http://json.org/JSON_checker/test/pass1.json | ||
pass1 = r''' | ||
[ | ||
"JSON Test Pattern pass1", | ||
{"object with 1 member":["array with 1 element"]}, | ||
{}, | ||
[], | ||
-42, | ||
true, | ||
false, | ||
null, | ||
{ | ||
"integer": 1234567890, | ||
"real": -9876.543210, | ||
"e": 0.123456789e-12, | ||
"E": 1.234567890E+34, | ||
"": 23456789012E66, | ||
"zero": 0, | ||
"one": 1, | ||
"space": " ", | ||
"quote": "\"", | ||
"backslash": "\\", | ||
"controls": "\b\f\n\r\t", | ||
"slash": "/ & \/", | ||
"alpha": "abcdefghijklmnopqrstuvwyz", | ||
"ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ", | ||
"digit": "0123456789", | ||
"0123456789": "digit", | ||
"special": "`1~!@#$%^&*()_+-={':[,]}|;.</>?", | ||
"hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A", | ||
"true": true, | ||
"false": false, | ||
"null": null, | ||
"array":[ ], | ||
"object":{ }, | ||
"address": "50 St. James Street", | ||
"url": "http://www.JSON.org/", | ||
"comment": "// /* <!-- --", | ||
"# -- --> */": " ", | ||
" s p a c e d " :[1,2 , 3 | ||
, | ||
4 , 5 , 6 ,7 ],"compact":[1,2,3,4,5,6,7], | ||
"jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}", | ||
"quotes": "" \u0022 %22 0x22 034 "", | ||
"\/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?" | ||
: "A key can be any string" | ||
}, | ||
0.5 ,98.6 | ||
, | ||
99.44 | ||
, | ||
1066, | ||
1e1, | ||
0.1e1, | ||
1e-1, | ||
1e00,2e+00,2e-00 | ||
,"rosebud"] | ||
''' | ||
|
||
# from http://json.org/JSON_checker/test/pass2.json | ||
pass2 = r''' | ||
[[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]] | ||
''' | ||
|
||
# from http://json.org/JSON_checker/test/pass3.json | ||
pass3 = r''' | ||
{ | ||
"JSON Test Pattern pass3": { | ||
"The outermost value": "must be an object or array.", | ||
"In this test": "It is an object." | ||
} | ||
} | ||
''' | ||
|
||
pass_data = [pass1, pass2, pass3] | ||
|
||
fail_data = [ | ||
# http://json.org/JSON_checker/test/fail1.json | ||
'"A JSON payload should be an object or array, not a string."', | ||
# http://json.org/JSON_checker/test/fail2.json | ||
'["Unclosed array"', | ||
# http://json.org/JSON_checker/test/fail3.json | ||
'{unquoted_key: "keys must be quoted"}', | ||
# http://json.org/JSON_checker/test/fail4.json | ||
'["extra comma",]', | ||
# http://json.org/JSON_checker/test/fail5.json | ||
'["double extra comma",,]', | ||
# http://json.org/JSON_checker/test/fail6.json | ||
'[ , "<-- missing value"]', | ||
# http://json.org/JSON_checker/test/fail7.json | ||
'["Comma after the close"],', | ||
# http://json.org/JSON_checker/test/fail8.json | ||
'["Extra close"]]', | ||
# http://json.org/JSON_checker/test/fail9.json | ||
'{"Extra comma": true,}', | ||
# http://json.org/JSON_checker/test/fail10.json | ||
'{"Extra value after close": true} "misplaced quoted value"', | ||
# http://json.org/JSON_checker/test/fail11.json | ||
'{"Illegal expression": 1 + 2}', | ||
# http://json.org/JSON_checker/test/fail12.json | ||
'{"Illegal invocation": alert()}', | ||
# http://json.org/JSON_checker/test/fail13.json | ||
'{"Numbers cannot have leading zeroes": 013}', | ||
# http://json.org/JSON_checker/test/fail14.json | ||
'{"Numbers cannot be hex": 0x14}', | ||
# http://json.org/JSON_checker/test/fail15.json | ||
'["Illegal backslash escape: \\x15"]', | ||
# http://json.org/JSON_checker/test/fail16.json | ||
'[\\naked]', | ||
# http://json.org/JSON_checker/test/fail17.json | ||
'["Illegal backslash escape: \\017"]', | ||
# http://json.org/JSON_checker/test/fail18.json | ||
'[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]', | ||
# http://json.org/JSON_checker/test/fail19.json | ||
'{"Missing colon" null}', | ||
# http://json.org/JSON_checker/test/fail20.json | ||
'{"Double colon":: null}', | ||
# http://json.org/JSON_checker/test/fail21.json | ||
'{"Comma instead of colon", null}', | ||
# http://json.org/JSON_checker/test/fail22.json | ||
'["Colon instead of comma": false]', | ||
# http://json.org/JSON_checker/test/fail23.json | ||
'["Bad value", truth]', | ||
# http://json.org/JSON_checker/test/fail24.json | ||
"['single quote']", | ||
# http://json.org/JSON_checker/test/fail25.json | ||
'["\ttab\tcharacter\tin\tstring\t"]', | ||
# http://json.org/JSON_checker/test/fail26.json | ||
'["tab\\ character\\ in\\ string\\ "]', | ||
# http://json.org/JSON_checker/test/fail27.json | ||
'["line\nbreak"]', | ||
# http://json.org/JSON_checker/test/fail28.json | ||
'["line\\\nbreak"]', | ||
# http://json.org/JSON_checker/test/fail29.json | ||
'[0e]', | ||
# http://json.org/JSON_checker/test/fail30.json | ||
'[0e+]', | ||
# http://json.org/JSON_checker/test/fail31.json | ||
'[0e+-1]', | ||
# http://json.org/JSON_checker/test/fail32.json | ||
'{"Comma instead if closing brace": true,', | ||
# http://json.org/JSON_checker/test/fail33.json | ||
'["mismatch"}', | ||
# control characters | ||
'["A\u001FZ control characters in string"]', | ||
] |
Empty file.
Oops, something went wrong.