Yes... I believe so..
I pasted the code I used below in a paste bin and straight. Not sure which is easier. This code is direct from my XPages.TV site.
I actually have no idea how helpful this is for you... but I was able to make some json from SSJS using the toJson() function. The json did some of that "nested" stuff that I thought you were asking about.
Hopefully this helps at least a little. :)
Dave
http://pastebin.com/nSRCtgnJ
<xe:restService id="restService3" pathInfo="json">
<xe:this.service>
<xe:customRestService>
<xe:this.doGet><![CDATA[#{javascript:// Since we can't use compositeData to set vars, and don't want to use the URL Parameters...
// We're going to need to use scoped Variables.
// Using viewScope so everything can be controlled set via the current page.
var showAd = sessionScope.get("ssShowAd" || false);
var adUrl = sessionScope.get("ssAdUrl");
var adType = sessionScope.get("ssAdType");
var mainUrl = sessionScope.get("ssMainUrl");
var mainType = sessionScope.get("ssMainType");
// Now start setting up the playList Array. Projekktor wants an Array of JSON Objects.
// playList is the Master Array that gets turned into JSON and returned.
var playList = new Array();
// We need an object for the first video. Typically an Ad
// Since this is optional then let's use an if statement.
if (showAd == 'true') {
// We're going to show a Pre-Roll Ad
// This object is called "PlayListVideo1". It needs to hold the URL and type as well as config parameters
var playListVideo1 = {};
// Now let's create the config object for the first video.
var adConfig = {};
// finally one more object to hold the URL and type of the first video.
var adVideo = {};
adVideo["src"] = adUrl;
adVideo["type"] = adType;
// Now put the adVideo Object into the overal Playlist Object
playListVideo1[0] = adVideo;
// /////////playList.push(playListVideo1)
// Now create the configuration of the first video
adConfig["disablePause"] = true;
adConfig["disallowSkip"] = true;
// and put that config unto the first Video object
playListVideo1["config"] = adConfig;
// Now put this completed playListVideo1 object which contains the "adVideo" object and the "adConfig" object
// into the array.
playList.push(playListVideo1)
}
// Now do the REAL video
var mainVideo = {};
mainVideo["src"] = mainUrl
mainVideo["type"] = mainType
// Ad the mainVideo object to a new playListVideo2 object
var playListVideo2 = {};
playListVideo2[0] = mainVideo
// Ad the second video to the overall Array
playList.push(playListVideo2)
//Convert it all into JSON
// this can be testest by looking at the URL:
//http://my.domain.com/myDatabase.nsf/myPage.xsp/json
return toJson(playList)
}]]></xe:this.doGet>
</xe:customRestService>
</xe:this.service>
</xe:restService>