How to deserialize escape quotes in JSON?

267    Asked by DavidEDWARDS in Salesforce , Asked on Feb 8, 2023

JSON(I am working with): JSONLinter confirms this is a valid JSON.


{
    "errors": [
        {
            "params": {
                "password": "size must be between 4 and 30",
                "loginId": "must match "^[a-zA-Z0-9_]*$""
            }
        }
    ]
}

Attempt 1(Using JSONParser:

String str = '{ "errors": [ { "params": { "password": "size must be between 4 and 30", "loginId": "must match "^[a-zA-Z0-9_]*$"" } } ] }';
JSONParser parser = JSON.createParser(str);
while(parser.nextToken() != null){
    parser.nextToken();
}

Fails:

▸ ERROR: System.JSONException: Unexpected character ('^' (code 94)): was ▸ expecting comma to separate OBJECT entries at input location [1,99] ▸ ERROR: Class.System.JSONParser.nextToken: line 94, column 1 ▸ AnonymousBlock: line 3, column 1 ▸
AnonymousBlock: line 3, column 1
Attempt 2(JSON2Apex option):
public class JSON2Apex {
    public class Errors {
            public Params params;
    }
    public List errors;
    public class Params {
            public String password;
            public String loginId;
    }
}


String str = '{ "errors": [ { "params": { "password": "size must be between 4 and 30", "loginId": "must match "^[a-zA-Z0-9_]*$"" } } ] }';
JSON2Apex obj = (JSON2Apex)JSON.deserialize(str, JSON2Apex.class);
Fails:
▸ ERROR: System.JSONException: Unexpected character ('^' (code 94)): was ▸ expecting comma to separate OBJECT entries at [line:1, column:99] ▸ ERROR: Class.System.JSON.deserialize: line 15, column 1 ▸ AnonymousBlock: line 2, column 1 ▸ AnonymousBlock: line 2, column 1
Attempt 3(deserializeUntyped):
String str = '{ "errors": [ { "params": { "password": "size must be between 4 and 30", "loginId": "must match "^[a-zA-Z0-9_]*$"" } } ] }';
Map jsonObj = (Map)JSON.deserializeUntyped(str);
Fails:
▸ ERROR: System.JSONException: Unexpected character ('^' (code 94)): was ▸ expecting comma to separate OBJECT entries at [line:1, column:99] ▸ ERROR: Class.System.JSON.deserializeUntyped: line 11, column 1 ▸ AnonymousBlock: line 2, column 1 ▸ AnonymousBlock: line 2, column 1
Attempt 4(replace the problem causing double quote in JSON):
String str = '{ "errors": [ { "params": { "password": "size must be between 4 and 30", "loginId": "must match "^[a-zA-Z0-9_]*$"" } } ] }';
Map jsonObj = (Map)JSON.deserializeUntyped(str.replaceAll('"', '\"'));
Still fails:
▸ ERROR: System.JSONException: Unexpected character ('^' (code 94)): was ▸ expecting comma to separate OBJECT entries at [line:1, column:99] ▸ ERROR: Class.System.JSON.deserializeUntyped: line 11, column 1 ▸ AnonymousBlock: line 2, column 1 ▸ AnonymousBlock: line 2, column 1
Answered by Diya tomar

I'll try to illustrate the deserialization of escape quotes in JSON. .


This is valid JSON.

{
    "errors": [
        {
            "params": {
                "password": "size must be between 4 and 30",
                "loginId": "must match "^[a-zA-Z0-9_]*$""
            }
        }
    ]
}

This is not:

String str = '{ "errors": [ { "params": { "password": "size must be between 4 and 30", "loginId": "must match "^[a-zA-Z0-9_]*$"" } } ] }';
Why? Because in Apex, backslash is an escape character in a string literal. If you want that backslash to carry through to the in-memory representation of the string (your JSON), you must escape it in your source code:
String str = '{ "errors": [ { "params": { "password": "size must be between 4 and 30", "loginId": "must match \"^[a-zA-Z0-9_]*$\"" } } ] }';
Otherwise, Apex removes it, yielding an in-memory string that is not valid JSON because nested quote marks are not escaped:
"loginId": "must match "^[a-zA-Z0-9_]*$""

You don't need to use replaceAll() or anything fancy to fix this (and in fact, you can't - by the time you could call replaceAll(), the string's already broken and has no backslashes in it).

The problem is not in your logic. It's just in how you're writing string literals in your source code.



Your Answer

Interviews

Parent Categories