1

I'm attempting to create a Visualforce page that displays Custom Object information (fields) upon clicking a button, like so:

enter image description here

The button click activates a method in my Apex class (which acts as the Visualforce page's controller extension). The method queries the Custom Object and returns a String which contains the information in JSON-formatting.

Then, in the Visualforce page, I have Javascript print the result of that method to the page with JSON.parse(result), but I receive "Unexpected token & in JSON at position 1".

If I try to print the result without JSON.parse(), it will print the string, but it will still be in JSON format (i.e.: with the curly braces, quotes, colons): enter image description here

Visualforce Page:

<apex:page title="VF Page" standardController="case" extensions="ControllerExtension">

<apex:includeScript value="{!$Resource.JQueryJs}"/>


<script type="text/javascript">
    function getRemoteInfoJSON() {
        var var1 = "{!case.Var1__c}";
        var var2 = "{!case.Var2__c}";

        Visualforce.remoting.Manager.invokeAction(
            '{!$RemoteAction.ControllerExtension.getInfoJSON}', var1, var2, 
            function(result, event){
                if(event.status){
                    try {
                        document.getElementById("pushDataHere").innerHTML = JSON.parse(result); //produces error; if we just use 'result' instead of 'JSON.parse(result)', the string is printed in JSON format, with curly braces and such.
                    }catch(err) {
                        document.getElementById("pushDataHere").innerHTML = err.message;
                    }
                }
            }
        );
    };
</script>

<button onclick="getRemoteInfoJSON()">BUTTON</button> <br /> <br />
<div id="pushDataHere">
</div>

</apex:page>

Method from Apex Class (Extension):

@RemoteAction
global static String getInfoJSON(String var1, String var2){
    sObject record = [SELECT <lots of fields> FROM Custom_Object__c WHERE Platform__c = :var1 AND ParentProductId__c = :var2];
    Map<String, Schema.SObjectField> fieldMap = Schema.getGlobalDescribe().get('Custom_Object__c').getDescribe().fields.getMap();

    Map<String, String> contents = new Map<String, String>();
    for(String fieldName : fieldMap.keySet()){
        try{
            String fieldLabel = fieldMap.get(fieldName).getDescribe().getLabel();
            String fieldContents = String.valueOf(record.get(fieldName));
            //We only want to add to our Contents list if the field has something in it
            if (fieldContents != null){
                contents.put(fieldLabel, fieldContents);
            }
        } catch (SObjectException e){
            System.debug('Whoopsie'); //Occurs when we try to retrieve contents of a field we didn't query in the 'record' variable.
        }
    }
    return JSON.serialize(contents); //returns '{"Field1": "Value1","Field2": "Value2", "Field3": "Value3", "Field4": "Value4", "Field5": "Value5", "Field6": "Value6", "Field7": "Value7", "Field8": "Value8", "Field9": "Value9", "Field10": "Value10","Field11": "Value11","Field12": "Value12","Field13": "Value13","Field14": "Value14"}'
}

String returned by Apex Class:

{
    "Field1": "Value1",
    "Field2": "Value2",
    "Field3": "Value3",
    "Field4": "Value4",
    "Field5": "Value5",
    "Field6": "Value6",
    "Field7": "Value7",
    "Field8": "Value8",
    "Field9": "Value9",
    "Field10": "Value10",
    "Field11": "Value11",
    "Field12": "Value12",
    "Field13": "Value13",
    "Field14": "Value14"
}

Error Received on button-click:

Unexpected token & in JSON at position 1

enter image description here

1 Answer 1

0

Judging from one of the links in the sidebar, and the character mentioned in your error message (&), it looks like your json is being escaped in order to prevent XSS attacks.

From Javascript Remoting returning JSON with encoded characters. For example &amp:

The RemoteAction framework auto-escapes the results by default, to prevent accidental XSS injections for developers using innerHTML to render the contents of a callback. This is a security feature, and should not be disabled without considering the consequences.

This is the result when I try console.log(result):

{&quot;Field1&quot;: &quot;Value1&quot;,&quot;Field2&quot;: &quot;Value2&quot;, &quot;Field3&quot;: &quot;Value3&quot;, &quot;Field4&quot;: &quot;Value4&quot;, &quot;Field5&quot;: &quot;Value5&quot;, &quot;Field6&quot;: &quot;Value6&quot;, &quot;Field7&quot;: &quot;Value7&quot;, &quot;Field8&quot;: &quot;Value8&quot;, &quot;Field9&quot;: &quot;Value9&quot;, &quot;Field10&quot;: &quot;Value10&quot;,&quot;Field11&quot;: &quot;Value11&quot;,&quot;Field12&quot;: &quot;Value12&quot;,&quot;Field13&quot;: &quot;Value13&quot;,&quot;Field14&quot;: &quot;Value14&quot;}

By adding {escape:false} to your remoting call, you can change this behavior. Documented here.

    <script type="text/javascript">
        function getRemoteInfoJSON() {

            Visualforce.remoting.Manager.invokeAction(
                '{!$RemoteAction.ControllerExtension.getInfoJSON}', 
                function(result, event){
                    if(event.status){
                        try {
                            console.log(result);
                            document.getElementById("pushDataHere").innerHTML = JSON.parse(result); //produces error; if we just use 'result' instead of 'JSON.parse(result)', the string is printed in JSON format, with curly braces and such.
                        }catch(err) {
                            document.getElementById("pushDataHere").innerHTML = err.message;
                        }
                    }
                },
                {escape:false}
            );
        };
    </script>

To answer the question you didn't ask (since parse just returns a generic object & trying to put it directly onto the page gives you [Object object]), heres some code I wrote to render the output to the page:

try {
    var someData = JSON.parse(result);
    var someHtml = '';

    for (var key in someData) {
        someHtml += '<div><span> ' + key + ' </span> : <span> ' + someData[key] + ' </span></div>';
    }

    document.getElementById("pushDataHere").innerHTML = someHtml;
}

enter image description here

1
  • Thanks a bunch! I added in the {escape:false} and it worked. Also thanks for the code that displays the contents in a pretty way; that helped as well.
    – Rudy
    Apr 30, 2018 at 21:08

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .