-
Notifications
You must be signed in to change notification settings - Fork 8k
RFC - json_validate() #9399
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC - json_validate() #9399
Changes from 4 commits
0405a86
8f86a67
344687f
cfbee85
85dcc6a
6688e20
47756e9
ae041be
8e97349
52ab14e
1b1b4f3
baf8ec6
d038d1f
722303b
f02c89c
70467bc
8b528bd
7331b47
2e92c03
d71b16f
9223115
a08d066
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -161,7 +161,7 @@ PHP_JSON_API zend_result php_json_decode_ex(zval *return_value, const char *str, | |
{ | ||
php_json_parser parser; | ||
|
||
php_json_parser_init(&parser, return_value, str, str_len, (int)options, (int)depth); | ||
php_json_parser_init(&parser, return_value, str, str_len, (int)options, (int)depth, false); | ||
|
||
if (php_json_yyparse(&parser)) { | ||
php_json_error_code error_code = php_json_parser_error_code(&parser); | ||
|
@@ -178,6 +178,28 @@ PHP_JSON_API zend_result php_json_decode_ex(zval *return_value, const char *str, | |
} | ||
/* }}} */ | ||
|
||
/* {{{ */ | ||
PHP_JSON_API zend_result php_json_validate_ex(zval *return_value, const char *str, size_t str_len, zend_long options, zend_long depth) | ||
{ | ||
php_json_parser parser; | ||
|
||
php_json_parser_init(&parser, return_value, str, str_len, (int)options, (int)depth, true); | ||
|
||
if (php_json_yyparse(&parser)) { | ||
php_json_error_code error_code = php_json_parser_error_code(&parser); | ||
if (!(options & PHP_JSON_THROW_ON_ERROR)) { | ||
JSON_G(error_code) = error_code; | ||
} else { | ||
zend_throw_exception(php_json_exception_ce, php_json_get_error_msg(error_code), error_code); | ||
} | ||
RETVAL_FALSE; | ||
return FAILURE; | ||
} | ||
|
||
return SUCCESS; | ||
} | ||
/* }}} */ | ||
|
||
/* {{{ Returns the JSON representation of a value */ | ||
PHP_FUNCTION(json_encode) | ||
{ | ||
|
@@ -270,6 +292,66 @@ PHP_FUNCTION(json_decode) | |
} | ||
/* }}} */ | ||
|
||
/* {{{ Validates if an string contains a valid json */ | ||
juan-morales marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
PHP_FUNCTION(json_validate) | ||
{ | ||
char *str; | ||
size_t str_len; | ||
zend_long depth = PHP_JSON_PARSER_DEFAULT_DEPTH; | ||
zend_long options = 0; | ||
|
||
ZEND_PARSE_PARAMETERS_START(1, 3) | ||
Z_PARAM_STRING(str, str_len) | ||
Z_PARAM_OPTIONAL | ||
Z_PARAM_LONG(depth) | ||
Z_PARAM_LONG(options) | ||
ZEND_PARSE_PARAMETERS_END(); | ||
|
||
|
||
if (options != 0) { | ||
zend_long tmp_options = options; | ||
tmp_options ^= (PHP_JSON_INVALID_UTF8_IGNORE | PHP_JSON_THROW_ON_ERROR); | ||
|
||
if (tmp_options != 0) { | ||
if (!((tmp_options == PHP_JSON_INVALID_UTF8_IGNORE) || (tmp_options == PHP_JSON_THROW_ON_ERROR))) { | ||
juan-morales marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
zend_argument_value_error(3, "must be a valid flag (JSON_THROW_ON_ERROR, JSON_INVALID_UTF8_IGNORE)"); | ||
RETURN_THROWS(); | ||
} | ||
} | ||
} | ||
|
||
if (!str_len) { | ||
if (!(options & PHP_JSON_THROW_ON_ERROR)) { | ||
JSON_G(error_code) = PHP_JSON_ERROR_SYNTAX; | ||
} else { | ||
zend_throw_exception(php_json_exception_ce, php_json_get_error_msg(PHP_JSON_ERROR_SYNTAX), PHP_JSON_ERROR_SYNTAX); | ||
juan-morales marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
} | ||
|
||
RETURN_FALSE; | ||
} | ||
|
||
if (!(options & PHP_JSON_THROW_ON_ERROR)) { | ||
JSON_G(error_code) = PHP_JSON_ERROR_NONE; | ||
|
||
} | ||
|
||
if (depth <= 0) { | ||
zend_argument_value_error(2, "must be greater than 0"); | ||
RETURN_THROWS(); | ||
} | ||
|
||
if (depth > INT_MAX) { | ||
zend_argument_value_error(2, "must be less than %d", INT_MAX); | ||
RETURN_THROWS(); | ||
} | ||
|
||
if (php_json_validate_ex(return_value, str, str_len, options, depth) == SUCCESS) { | ||
RETURN_TRUE; | ||
} | ||
|
||
RETURN_FALSE; | ||
} | ||
/* }}} */ | ||
|
||
/* {{{ Returns the error code of the last json_encode() or json_decode() call. */ | ||
PHP_FUNCTION(json_last_error) | ||
{ | ||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
--TEST-- | ||
json_validate() - General usage | ||
--FILE-- | ||
<?php | ||
|
||
var_dump( | ||
json_validate(""), | ||
json_validate("."), | ||
json_validate("<?>"), | ||
json_validate(";"), | ||
json_validate("руссиш"), | ||
json_validate("blah"), | ||
json_validate('{ "": "": "" } }'), | ||
json_validate('{ "": { "": "" }'), | ||
json_validate('{ "test": {} "foo": "bar" }, "test2": {"foo" : "bar" }, "test2": {"foo" : "bar" } }'), | ||
|
||
json_validate('{ "test": { "foo": "bar" } }'), | ||
juan-morales marked this conversation as resolved.
Show resolved
Hide resolved
|
||
json_validate('{ "test": { "foo": "" } }'), | ||
json_validate('{ "": { "foo": "" } }'), | ||
json_validate('{ "": { "": "" } }'), | ||
json_validate('{ "test": {"foo": "bar"}, "test2": {"foo" : "bar" }, "test2": {"foo" : "bar" } }'), | ||
json_validate('{ "test": {"foo": "bar"}, "test2": {"foo" : "bar" }, "test3": {"foo" : "bar" } }'), | ||
); | ||
|
||
?> | ||
--EXPECTF-- | ||
bool(false) | ||
bool(false) | ||
bool(false) | ||
bool(false) | ||
bool(false) | ||
bool(false) | ||
bool(false) | ||
bool(false) | ||
bool(false) | ||
bool(true) | ||
bool(true) | ||
bool(true) | ||
bool(true) | ||
bool(true) | ||
bool(true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A validation routine should not have side effects, such as setting a global
error_code
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will check this and will be back to you
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@derickr
The reason I kept that code, was because of the usage of json_last_error() function.
I , and other developers in the mailing list find it useful to have such information, to know why a validation failed so we can have messages like:
etc.
I think is good thing to have, also some other devs from mailing list.
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is a legit solution; an alternative could be to return the error code as int (instead of a bool).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wrote this down in the RFC as an open question