2

I'm trying to extract the values from JSON, what is the simple and easy way to do and I have tried few different way but none of the approach works, I looked json2apex but that approach never worked.

Here is the error I'm getting for the below code, how should I deal with this error? and I don't control how the JSON output renders.

Error: Line: 11, Column: 1 System.JSONException: Illegal unquoted character ((CTRL-CHAR, code 10)): has to be escaped using backslash to be included in string value at [line:1, column:586]

Line: 11, Column: 1 System.JSONException: Unexpected character ('V' (code 86)): was expecting comma to separate OBJECT entries at [line:1, column:615]

APEX Code:

 String sessionId = fetchUserSessionId();
    HTTP h = new HTTP();
    HTTPRequest req = new HTTPRequest();
    HttpResponse resp = new HttpResponse();
    req.setMethod('GET');
    req.setHeader('Authorization', 'Bearer ' + sessionId);
    req.setEndpoint(getHostURL() + endpoint);
    resp = h.send(req); 
    String jsonStr = resp.getBody();   

 
String ParserOutput= jsonStr.replaceAll('\n','').replaceAll('\r','');
//String transformedText = ParserOutput.replace('""', '"'); 
String responseText = ParserOutput.trim().replace('\uFEFF', '');
// Parse entire JSON response.

//deserializeUntyped works
Map<String, Object> jsonMap = (Map<String, Object>) JSON.deserializeUntyped(responseText);

     

JSON

{
  "size": 1,
  "totalSize": 1,
  "done": true,
  "queryLocator": null,
  "entityTypeName": "CustomField",
  "records": [
    {
      "attributes": {
        "type": "CustomField",
        "url": "/services/data/v46.0/tooling/sobjects/CustomField/00N6g00000TAlZNEA1"
      },
      "Metadata1": {
        "businessOwnerGroup": null,
        "businessOwnerUser": null,
        "formula": "IMAGE( \nCASE(Rating__c, \n\"Very Bad\", \"/img/samples/stars_100.gif\",\n\"Bad\", \"/img/samples/stars_200.gif\",\n\"Okay\", \"/img/samples/stars_300.gif\", \n\"Good\", \"/img/samples/stars_400.gif\", \n\"Very Good\", \"/img/samples/stars_500.gif\", \n\"/img/samples/stars_000.gif\"), \n\"rating\")",
        "formulaTreatBlanksAs": "BlankAsZero"
      }
    }
  ]
}
1
  • which is the endpoint you are hitting in salesforce ? Jun 9 '20 at 4:06
1

To elaborate more, one way to actually apply and store the changes to jsonMap, we could do the following.

if (response.getStatusCode() == 200) {
  // Deserialize the JSON string into collections of primitive data types.
  Map<String, Object> jsonMap = (Map<String, Object>) JSON.deserializeUntyped(response.getBody());

  // Iterate over the keys in the map
  for (String key : jsonMap.keySet()) {
    Object value = jsonMap.get(key);
    if(value != null){
      value = String.valueOf(value).replaceAll('\n','').replaceAll('\r','').replace('\uFEFF', '');
    }
    jsonMap.put(key, value);
  }

  System.debug(jsonMap);
}
3

Your main issue is here:

String ParserOutput= jsonStr.replaceAll('\n','').replaceAll('\r','');

In Apex code, \ is an escape character, so you're actually trying to remove the CR+LF bytes from the code, which is not the same as removing the literal \n in the string. To do that, you'd need to double up on the escape sequences. In addition, the replaceAll function is using a regular expression, so the \ itself must be escaped again:

String ParserOutput= jsonStr.replaceAll('\\\\n','').replaceAll('\\\\r','');

However, this is apparently pointless. I actually just copy-pasted your response JSON into a Static Resource, and parsed it directly in Apex, without modification, and it parsed just fine. I don't think you need to do all the extra work you're doing at that phase in the code.

StaticResource s = [select body from staticresource where name = 'q308772'];
System.debug(
    json.deserializeuntyped(s.body.tostring())
);
4
  • How do I extract values from ParserOutput like attributes, type, url...
    – Nick Kahn
    Jun 9 '20 at 15:11
  • See the other answer, but you start with a Map<String, Object> values = (Map<String, Object>)JSON.deserializeUntyped(parserOutput), then you can: values.get('size'), etc. For nested objects, they will be Map<String, Object> as well, and you can read those elements the same way.
    – sfdcfox
    Jun 9 '20 at 15:14
  • I tried to do Map<String, Object> values = (Map<String, Object>)JSON.deserializeUntyped(parserOutput) and I get the size by doing values.get('size') but when I try to read the value for the url I tried something like this Map<String, Object> values2 = (Map<String, Object>)values.get('records') then I get this error system.typeexception: invalid conversion from runtime type LIST<ANY> TO mAP<STRING, ANY>
    – Nick Kahn
    Jun 9 '20 at 17:07
  • @NickKahn It's a List<Object>, which you then cast each element in to a Map<String, Object>.
    – sfdcfox
    Jun 9 '20 at 18:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.