Expand my Community achievements bar.

Learn about Edge Delivery Services in upcoming GEM session
SOLVED

Complex object in Sling object model

Avatar

Level 3

Hi, I have a component with a dialog like this.

<?xml version="1.0" encoding="UTF-8"?> <jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" jcr:primaryType="cq:Dialog" manageTabs="function(tab,noSwitch){debugger;var tabs={static:1,children:2};if(!Object.keys(tabs).indexOf(tab)==-1){return;}var index=tabs[tab];for(var key in tabs){if(index==tabs[key]){this.unhideTabStripItem(tabs[key]);}else{this.hideTabStripItem(tabs[key]);}}this.doLayout();if(!noSwitch){this.activate(index);}}" xtype="tabpanel"> <items jcr:primaryType="cq:WidgetCollection"> <advanced jcr:primaryType="cq:Widget" title="Mode" xtype="panel"> <items jcr:primaryType="cq:WidgetCollection"> <url jcr:primaryType="cq:Widget" fieldLabel="Url" name="./url" xtype="pathfield" /> <mode jcr:primaryType="cq:Widget" defaultValue="" fieldLabel="Mode" name="./listFrom" type="select" xtype="selection"> <listeners jcr:primaryType="nt:unstructured" loadcontent="function(){this.findParentByType('tabpanel').manageTabs(this.getValue(),false);}" selectionchanged="function(box,value){box.findParentByType('tabpanel').manageTabs(value);}"/> <options jcr:primaryType="cq:WidgetCollection"> <static jcr:primaryType="nt:unstructured" text="Static List of Pages" value="static"/> <dynamic jcr:primaryType="nt:unstructured" text="Dynamic list of Children Pages" value="children"/> </options> </mode> </items> </advanced> <static jcr:primaryType="cq:Panel" title="Links"> <listeners jcr:primaryType="nt:unstructured" render="function() { this.findParentByType('tabpanel').hideTabStripItem(1); }"/> <items jcr:primaryType="cq:WidgetCollection"> <linkspanel jcr:primaryType="cq:Panel" border="false" height="" title="Links" width="100%"> <items jcr:primaryType="cq:WidgetCollection"> <links jcr:primaryType="cq:Widget" fieldDescription="Press + to add more links" fieldLabel="Links" hideLabel="true" name="./links" xtype="multifield"> <fieldConfig jcr:primaryType="nt:unstructured" xtype="linklistfield"/> <listeners jcr:primaryType="nt:unstructured"/> </links> </items> </linkspanel> </items> </static> <children jcr:primaryType="cq:Panel" title="Links Parent"> <listeners jcr:primaryType="nt:unstructured" render="function() { this.findParentByType('tabpanel').hideTabStripItem(2); }"/> <items jcr:primaryType="cq:WidgetCollection"> <parentPage jcr:primaryType="cq:Widget" fieldDescription="Leave empty to use current page" fieldLabel="Parent page" name="./parentPage" xtype="pathfield"/> </items> </children> </items> </jcr:root>

And I am trying to convert this into a sling model object structure.

So this is how I mapped in my JAVA class.

package com.myweb.model; import java.util.List; import org.apache.sling.api.resource.*; import org.apache.sling.models.annotations.*; import javax.inject.*; @Model (adaptables=Resource.class) public class LeftNavigation { @Inject private String listFrom; public String getListFrom() { return listFrom; } @Inject private String url; public String getUrl() { return url; } @Inject private String[] links; public String[] getLinks() { return links; } }

If I output the links, it is like this.Please check the picture.[img]2014-07-03_18-50-35.png[/img]

You can see that this becomes a String array. When I output links[0], it becomes a JSON like String.

<sling:adaptTo adaptable="${resource}" adaptTo="com.myweb.model.LeftNavigation" var="mdl" /> List one of the links ${mdl.links[0]}

The output is like this {"text":"dsdfdsf","url":"/content/mytestweb/en/products","openInNewWindow":false,"level":1}

My questoin is how can I  access $(mdl.link[0].url} ?

I believe this JSON like String needs to be another model, So I tried to create another class called LinkListField with all the @Inject GETTERs, getText(), getUrl(), getOpenInNewWindow(), getLevel(). and Change String[] links to List<LinkListField> links in LeftNavigation class, unfortuantely, it fails and I dont know what problem is.

This is the LinkListField

package com.myweb.model; import org.apache.sling.api.resource.*; import org.apache.sling.models.annotations.*; import javax.inject.*; @Model(adaptables=Resource.class) public class LinkListField { @Inject private String text; public String getUrl() { return url; } public boolean isOpenInNewWindow() { return openInNewWindow; } public int getLevel() { return level; } public String getText() { return text; } @Inject private String url; @Inject private boolean openInNewWindow; @Inject private int level; }

 

Please help.

 

Thank you

1 Accepted Solution

Avatar

Correct answer by
Employee

Hi,

The crux of the problem is that the linklistfield xtype stores data in this JSON structure, not as JCR nodes. And currently Sling Models doesn't have any ability to do JSON->Object mapping (whether ot not it should is a separate subject, one I would suggest discussing on the Sling mailing lists and/or JIRA).

For now, you would need to do the JSON parsing in a post construct method, something like this (warning - untested code):

 

@Inject private String[] links; private JSONObject[] parsedLinks; public JSONObject[] getLinks() { return parsedLinks; } @PostConstruct private void init() { parsedLinks = new JSONObject[links.length]; for (int i = 0; i < links.length; i++) { parsedLinks[i] = new JSONObject=(links[i]); } }

HTH,

Justin

View solution in original post

1 Reply

Avatar

Correct answer by
Employee

Hi,

The crux of the problem is that the linklistfield xtype stores data in this JSON structure, not as JCR nodes. And currently Sling Models doesn't have any ability to do JSON->Object mapping (whether ot not it should is a separate subject, one I would suggest discussing on the Sling mailing lists and/or JIRA).

For now, you would need to do the JSON parsing in a post construct method, something like this (warning - untested code):

 

@Inject private String[] links; private JSONObject[] parsedLinks; public JSONObject[] getLinks() { return parsedLinks; } @PostConstruct private void init() { parsedLinks = new JSONObject[links.length]; for (int i = 0; i < links.length; i++) { parsedLinks[i] = new JSONObject=(links[i]); } }

HTH,

Justin