[coldbox-4.1.0] event.renderdata() injects vars CONSTRAINTS and $MIXED into the JSON response

I mentioned this in the ColdBox channel in Slug as well, but reposting here since it went by unnoticed (so far).

Assume that I have a basic Bean like this:

models/Task.cfc

`
// transient bean
component accessors=“true” {

// properties
property name=“Code” type=“string”;

// validation
this.constraints = {
};

function init(){
return this;
}

}
`

I am trying to respond with JSON, through an array of Task objects, populated from a query. Like this:

handlers/Task.cfc

`
// all tasks to be returned
var arrTasks = [];

// single task bean to be populated
var oTask = wirebox.getInstance(“Task”);

// example of a set method
oTask.setCode( “whatever” );

// add bean to array
arrayAppend( arrTasks, oTask );

//return as JSON
event.renderData( type=“JSON”, data=arrTasks );
`

However, the resulting JSON is:
`

`

The function seems to add to the JSON response the bean constraints as well as the $MIXED var (not sure what that is). I tried removing those 2 through:

`

`
(where qResults is my query object and row is just a numeric row position) to no effect.

How can I get rid of those two? I would like to be able to easily export to JSON and not have to build a custom response.

Gist here as well:

Don’t have any injection into the bean or make them private.

@Andrew,

Pardon me for not understanding, but can you elaborate? I am not sure how to go about doing any of those 2 options. By default, ColdBox creates a “this.constraints{}” struct for validation, which even though it’s not populated in the example I gave, I do have some rules in there which I use for Validation. Can I make this “private”?

Renderdata serialize all the object property. You should add a method to the object that loop through the property and create a struct of what you need and then only output this as json.

You could look at some sample in the contentbox models folder:

`

function getMemento(){
var pList = listToArray( “roleID,role,description” );
var result = {};

for(var thisProp in pList ){
if( structKeyExists( variables, thisProp ) ){
result[ thisProp ] = variables[ thisProp ];
}
else{
result[ thisProp ] = “”;
}
}

// Do Permissions
if( hasPermission() ){
result[ “permissions” ]= [];
for( var thisPerm in variables.permissions ){
arrayAppend( result[ “permissions” ], thisPerm.getMemento() );
}
}
else{
result[ “permissions” ] = [];
}

return result;
}

`

So you should use it like this:

var oTask = wirebox.getInstance("Task"); var myJson = oTask.getMemento();

@Tropicalista,

I see what you are saying. That would work. Would a function like getMemento() belong in the Bean though, or higher up in the object hierarchy, like in the DAO or Service? I have a hard time trying to understand how a Bean could return a limited structure of itself. Is that a common workaround?

Also, just to verify, I want ALL OF THE BEAN PROPERTIES returned. Those 2 that I mentioned were not created by me, rather by the framework itself.

This seems to offer a temp fix, however I would still like to figure out the “proper way” of handling this.

`
// all tasks to be returned
var arrTasks = [];

// single task bean to be populated
var oTask = wirebox.getInstance(“Task”);

// example of a set method
oTask.setCode( “whatever” );

// delete the 2 vars I don’t need
structDelete(```oTask,“CONSTRAINTS”);** **structDelete(**oTask,"$MIXED"****);**`

// add bean to array
arrayAppend( arrTasks, oTask );

//return as JSON
event.renderData( type=“JSON”, data=arrTasks );

`

As previously mentioned (e.g. Tropicalista’s getMemento() example), if/when you need a custom formatted packet returned, the proper way to handle it is to have a callable method that gives you the desired result. One can argue whether that should be the sole responsibility of the bean or the service layer, but either way, it’s definitely not the responsibility of the framework to know what every app should do. There are simply too many different use cases for that to be possible.

My personal preference is to have the bean decide the what, and have the service decide the how. What do I mean by that?

  1. The bean should have a method that returns either a list of keys (properties) that it permits to be “exported”, or, better yet, as Tropicalista suggested, a memento (struct) of properties/values. This is the what.

  2. The service would have method(s) that return the data in the desired format for “export”. For example, FooService.getCarPropsAsJSON( car ). This is the how.

HTH

Thanks @Andrew, @Tropicalista and @QuackFuzed! I will give that a try.

You could also create a method where you can specify which property do you want include/exclude and then let the handlers decide what to show/hide.

Probably if your app has not a standardized model representation you could go this route…

Yeah when this is called

// single task bean to be populated
var oTask = wirebox.getInstance(“Task”);

It creates a wirebox instance of the bean, hence why you have Mixed:true in the result.

Regards,