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

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

  • 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 '18 at 21:08

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.