debugsqlMinor
Why does this throw a JSON parsing error and why can't I trap it?
Viewed 0 times
thiswhyerrorcanandjsontrapparsingdoesthrow
Problem
Consider the below function which returns a portion of a well-formatted JSON object. It will return "Bad JSON" when the JSON is not well-formatted. Importantly, it will not error when the JSON is not well-formatted.
Results:
So far, so good.
Now I want to use this function in a procedure and feed it the same bad JSON:
Results:
-
Why does this error occur? The evaluation of JSON_VALUE should not take place because ISJSON should be 0 and therefore the row is filtered from the results.
-
Why isn't this error caught by the BEGIN TRY?
I found a suggestion online that this was some sort of a compilation error. Some support for that conclusion is provided by the behavior when the first call of the procedure after creation is with valid JSON:
```
CREATE OR ALTER PROCEDURE TestJSONParseProc
(
@nv nvarchar(max)
)
AS
BEGIN
BEGIN TRY
DECLARE
CREATE OR ALTER FUNCTION TestJSONParse
(
@nv nvarchar(max)
)
RETURNS TABLE
AS
RETURN
(
SELECT
v3 = isNull(t2.v2,t1.v1)
FROM (
SELECT
v1 = 'Bad JSON'
) AS t1
LEFT JOIN (
SELECT
v2 = JSON_VALUE(@nv,'$.prop')
WHERE ISJSON(@nv) <> 0
) AS t2
ON 1 = 1
);
GO
SELECT * FROM TestJSONParse('{"prop": "Good JSON"}');
SELECT * FROM TestJSONParse('zzzz');
GOResults:
v3
Good JSON
v3
Bad JSONSo far, so good.
Now I want to use this function in a procedure and feed it the same bad JSON:
CREATE OR ALTER PROCEDURE TestJSONParseProc
(
@nv nvarchar(max)
)
AS
BEGIN
BEGIN TRY
DECLARE @v nvarchar(max);
SELECT
@v = v3
FROM TestJSONParse(@nv);
END TRY
BEGIN CATCH
SELECT
Result = N'I have caught an error.';
END CATCH
END
GO
EXEC TestJSONParseProc
@nv = N'zzzz';
GOResults:
Msg 13609, Level 16, State 2, Procedure TestJSONParseProc, Line 10 [Batch Start Line 45]
JSON text is not properly formatted. Unexpected character 'z' is found at position 0.-
Why does this error occur? The evaluation of JSON_VALUE should not take place because ISJSON should be 0 and therefore the row is filtered from the results.
-
Why isn't this error caught by the BEGIN TRY?
I found a suggestion online that this was some sort of a compilation error. Some support for that conclusion is provided by the behavior when the first call of the procedure after creation is with valid JSON:
```
CREATE OR ALTER PROCEDURE TestJSONParseProc
(
@nv nvarchar(max)
)
AS
BEGIN
BEGIN TRY
DECLARE
Solution
You need to use the
So inside your
ISJSON() function to verify the column is valid JSON in the SELECT clause regardless of the WHERE clause. The reasoning for this is because contrary to popular belief, sometimes the SQL Engine generates an execution plan where it finds it more efficient to evaluate the SELECT clause before the WHERE clause is applied. That results in these odd cases where an exception is thrown unbeknownst to the average developer why.So inside your
TestJSONParse() function you'll need to change the line of code v2 = JSON_VALUE(@nv,'$.prop') to v2 = CASE WHEN ISJSON(@nv) = 1 THEN JSON_VALUE(@nv,'$.prop') ELSE NULL, for example.Context
StackExchange Database Administrators Q#290588, answer score: 3
Revisions (0)
No revisions yet.