Skip to content

Conversation

@juan-morales
Copy link
Contributor

@juan-morales juan-morales commented Dec 2, 2025

This PR pretends to add the location where the error occurs when processing a json string (json_validate()or json_decode()). As the message suggests, is the "nearby location", like MySQL does it when there is an error with a SQL string.

I tried to achieve this many times in the past, but failed, my previous approaches were .... terrible and error-prone.

Now I used a different approach suggested by @bukka . I hope I get closer to a descent implementation. Did my best on this one.

I tested with JSON string with 1GB long, and values were calculated correctly for rows and columns.

Thanks for reviewing and I hope this helps

@juan-morales juan-morales marked this pull request as ready for review December 2, 2025 15:51
@juan-morales juan-morales requested a review from mvorisek December 2, 2025 15:51
@juan-morales juan-morales changed the title WIP - Json last error msg/error message with location error Json last error msg/error message with location error Dec 2, 2025
Copy link
Member

@bukka bukka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks mostly good (nicely taken from jso :) ). Just some minor things.

Other than that I like the new format not exposing the content and just showing the location which I think is acceptable without RFC. Previously I was the only one suggesting a new function but I no longer think it's necessary.

ZEND_PARSE_PARAMETERS_NONE();

RETURN_STRING(php_json_get_error_msg(JSON_G(error_code)));
if (JSON_G(error_line) > 0 && JSON_G(error_column) > 0) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check is not necessary as it is checked in php_json_get_error_msg_with_location. If it was to save creation of zend_string, then it is not necessary because it is created in RETURN_STRING anyway.

Comment on lines +213 to +214
zend_throw_exception(php_json_exception_ce, ZSTR_VAL(error_msg), error_code);
zend_string_release(error_msg);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
zend_throw_exception(php_json_exception_ce, ZSTR_VAL(error_msg), error_code);
zend_string_release(error_msg);
zend_throw_exception_zstr(php_json_exception_ce, error_msg, error_code);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This not a public API (yet), see #20547

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah good catch (I was just searching for something like that but didn't realise it's not in the header...). Let's wait for that first commit in the PR then...

Comment on lines +309 to +313

parser->scanner.errloc.first_column = location->first_column;
parser->scanner.errloc.first_line = location->first_line;
parser->scanner.errloc.last_column = location->last_column;
parser->scanner.errloc.last_line = location->last_line;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this necessary? Just checking because I don't have this in jso and it seems to still work so wondering why it's added here?


#define PHP_JSON_INT_MAX_LENGTH (MAX_LENGTH_OF_LONG - 1)

#define PHP_JSON_TOKEN_LENGTH(s) ((size_t) ((s)->cursor - (s)->token))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess s is kind of given in other macros so I would omit it here as well for consistency.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants