Strange JSON.parse problem when calling CFC with Ajax

I’m converting a large ACF system to lucee and have a lot of javascript code calling cfc’s on the server and parsing the json returned. I’m having trouble getting that to work. I don’t think i need ajaxproxy or stuff like that. This is simple javascript calling a cfc on the server, getting the string response which is in JSON format. It parses it using JSON.parse() but ends up with a string object and not a real object.
My test page has a simple example where i do this using a variable defined on the page that is a duplicate of what the cfc returns. That works perfectly. I then call my cfc and try to do the same thing but no good. after the parse the code still thinks it is dealing with a string and fails.

The cfc:

component output=false  {

remote function testFunction() returnformat="JSON" {

	getData = QueryNew("firstName,lastName,age","varchar,varchar,numeric",["Joe","Blow",30])

	userObj = {
		"FirstName":getData.firstname,
		"LastName":getData.lastname,
		"Age":getData.age};
	 
	return serializeJSON(userObj,"struct");
}
}

the cfm page:

<!DOCTYPE html>
<html lang="en">
<head> 
    <title>Testing JSON parsing</title> 
</head> 
<body> 

<button onclick="runit();">click me</button>

<br/>

<span id="cfcResult"></span>
<br/>
<span id="varResult"></span>

<script language="JavaScript">
	function get(url) {
	  // Return a new promise.
	  return new Promise(function(resolve, reject) {
	    var req = new XMLHttpRequest();
	    req.open('GET', url);
	
	    req.onload = function() {
	      if (req.status == 200) {
	        resolve(req.response);
	      }
	      else {
	        reject(Error(req.statusText));
	      }
	    };
	
	    // Handle network errors
	    req.onerror = function() {
	      	reject(Error("Network Error"));
	    };
	
	    // Make the request
	    req.send();
	  });
	}
	
	function runit() {
		
		// first parse a simple string which is what we get back from cfc
		
		var testVar = "{\"LastName\":\"Blow\",\"FirstName\":\"Joe\",\"Age\":30}";
		var theObj = JSON.parse(testVar);
		document.getElementById("varResult").innerHTML = 
			'<br/>using variable:<br/>' + testVar +
			'<br/>typeof testVar: ' + typeof testVar + 
		 	'<br/>typeof theObj: ' + typeof theObj + 
		 	'<br/>name: ' + theObj.FirstName + " age: " + theObj.Age;

		// then call the cfc and parse it ... should be same output.. 
		
		get('test.cfc?method=testFunction').then(function(detailResponseJSON) {
			
			console.log('typeof detailResponseJSON: ' + typeof detailResponseJSON);
			console.log('detailResponseJSON: ' + detailResponseJSON);
			
			const detailResponse = JSON.parse(detailResponseJSON);
			console.log('typeof detailResponse (should be object): ' + typeof detailResponse);
			console.log('detailResponse.length: ' + detailResponse.length);
			console.log('detailResponse: ' + detailResponse);

			document.getElementById('cfcResult').innerHTML = 
				'<br/>using cfc:<br/>' + detailResponse + 
				'<br/>typeof detailResponseJSON: ' + typeof detailResponseJSON +
				'<br/>typeof detailResponse (should be object): <strong>' + typeof detailResponse + '</strong>' +
				'<br/>name:' + detailResponse.FirstName + ' age: ' + detailResponse.Age;
			
		}
		, function(err) {
			console.log(err); // Error:
		});
	}
</script>
</body> 
</html>

what i see:

using cfc:
{"LastName":"Blow","FirstName":"Joe","Age":30}
typeof detailResponseJSON: string
typeof detailResponse (should be object): string
name:undefined age: undefined

using variable:
{"LastName":"Blow","FirstName":"Joe","Age":30}
typeof testVar: string
typeof theObj: object
name: Joe age: 30

the detailResponse variable should be ‘object’ not ‘string’… what’s up?

It appears you’re double encoding your response. Your running the string through serializeJSON() AND you have also put returnFormat="JSON" in the function which is redundant. Hit the Ajax directly in your browser and view source to see the raw response. I have a feeling it’s something like

"{\"LastName\":\"Blow\",\"FirstName\":\"Joe\",\"Age\":30}"

which is a string, not a struct.

Also, on this line:

	return serializeJSON(userObj,"struct");

The second argument ,"struct" doesn’t do anything when using it with an input of a struct. That’s only for when you are serializing a query object.

1 Like

aha! thank you so much for pointing that out. I changed the returnFormat to be “plain” (was wddx initially) i get the correct object.

test.cfc:

component output=false  {

remote function testFunction() returnformat="plain"      {

	getData = QueryNew("firstName,lastName,age","varchar,varchar,numeric",["Joe","Blow",30])

	userObj = {
		"FirstName":getData.firstname,
		"LastName":getData.lastname,
		"Age":getData.age};
	 
	return serializeJSON(userObj);
}
}

shows:

using cfc:
[object Object]
typeof detailResponseJSON: string
typeof detailResponse (should be object):  **object**
name:Joe age: 30

oh and i was originally was returning the query so that’s why i had that “strct” in the serializeJSON function. Thanks for the nudge in the right direction.

1 Like