I am using sling post servlet to create a page reading a JSON. The json is valid and structured, but the resulting page that is created by the servlet has the nodes underneath in jumbled order. Is there a way to preserve the order as is in json? Please suggest.
Solved! Go to Solution.
Topics help categorize Community content and increase your ability to discover relevant content.
Views
Replies
Total Likes
HI @ShriSa ,
If I understand the ask correctly. You have a JSON which has all the components data and using that JSON you want to create a page.
If yes, the order of nodes in a JSON object is not guaranteed to be preserved. If maintaining the order is crucial, you should utilize an array to explicitly represent the order.
{
"jcr:primaryType": "cq:Page",
"jcr:content": {
"jcr:primaryType": "cq:PageContent",
"components": [
{ "name": "component1", "sling:resourceType": "your/component/resource/type1", ... },
{ "name": "component2", "sling:resourceType": "your/component/resource/type2", ... },
{ "name": "component3", "sling:resourceType": "your/component/resource/type3", ... }
]
}
}
Now, the "components" property is an array, and the order of components in the array will be preserved when you iterate over it.
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.commons.json.JSONArray;
import org.apache.sling.commons.json.JSONObject;
public class PageCreationService {
public void createPageWithComponents(ResourceResolver resolver, String pagePath, JSONObject json) {
try {
// Get or create the page resource
Resource pageResource = ResourceUtil.getOrCreateResource(resolver, pagePath, "cq:Page", "cq:Page", true);
// Get or create the page content node
Resource contentResource = ResourceUtil.getOrCreateResource(resolver, pagePath + "/jcr:content", "cq:PageContent", "cq:PageContent", true);
// Get the "components" array from the JSON
JSONArray componentsArray = json.getJSONObject("jcr:content").getJSONArray("components");
// Iterate over components array and create components
for (int i = 0; i < componentsArray.length(); i++) {
JSONObject componentJson = componentsArray.getJSONObject(i);
String componentName = componentJson.getString("name");
// Create the component under the page's content node
ResourceUtil.getOrCreateResource(resolver, contentResource.getPath() + "/" + componentName, componentJson);
}
// Commit the changes
resolver.commit();
} catch (Exception e) {
// Handle exceptions appropriately
resolver.refresh();
// Log or handle the exception as needed
} finally {
if (resolver.isLive()) {
resolver.close();
}
}
}
}
Thanks
Preserving the order of JSON nodes in AEM using the Sling Post Servlet can be achieved by submitting the POST request using multipart/form-data encoding. This preserves the order of parameter application according to the original HTML form.
Here’s how you can do it:
Ensure you are submitting the POST request using multipart/form-data encoding. This preserves the order of parameter application according to the original HTML form. To this avail, ensure to always include the enctype="multipart/form-data" attribute with the <form> tag.
https://sling.apache.org/documentation/bundles/manipulating-content-the-slingpostservlet-servlets-po...
Use .harray selector in GET requests: If you’re dealing with GET requests, you can use the .harray selector which causes child nodes to be output as arrays instead of objects, to preserve their order.
https://sling.apache.org/documentation/bundles/rendering-content-default-get-servlets.html
Thanks for the suggestion @pulkitvashisth . In my case, I don't have a form. It is more of a post api call to my servlet which takes JSON as the input, verifies the structure and invokes sling request processor's process request to import the json to create nodes. In this process, I am not sure how to indicate that order needs to be preerved.
HI @ShriSa ,
If I understand the ask correctly. You have a JSON which has all the components data and using that JSON you want to create a page.
If yes, the order of nodes in a JSON object is not guaranteed to be preserved. If maintaining the order is crucial, you should utilize an array to explicitly represent the order.
{
"jcr:primaryType": "cq:Page",
"jcr:content": {
"jcr:primaryType": "cq:PageContent",
"components": [
{ "name": "component1", "sling:resourceType": "your/component/resource/type1", ... },
{ "name": "component2", "sling:resourceType": "your/component/resource/type2", ... },
{ "name": "component3", "sling:resourceType": "your/component/resource/type3", ... }
]
}
}
Now, the "components" property is an array, and the order of components in the array will be preserved when you iterate over it.
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.commons.json.JSONArray;
import org.apache.sling.commons.json.JSONObject;
public class PageCreationService {
public void createPageWithComponents(ResourceResolver resolver, String pagePath, JSONObject json) {
try {
// Get or create the page resource
Resource pageResource = ResourceUtil.getOrCreateResource(resolver, pagePath, "cq:Page", "cq:Page", true);
// Get or create the page content node
Resource contentResource = ResourceUtil.getOrCreateResource(resolver, pagePath + "/jcr:content", "cq:PageContent", "cq:PageContent", true);
// Get the "components" array from the JSON
JSONArray componentsArray = json.getJSONObject("jcr:content").getJSONArray("components");
// Iterate over components array and create components
for (int i = 0; i < componentsArray.length(); i++) {
JSONObject componentJson = componentsArray.getJSONObject(i);
String componentName = componentJson.getString("name");
// Create the component under the page's content node
ResourceUtil.getOrCreateResource(resolver, contentResource.getPath() + "/" + componentName, componentJson);
}
// Commit the changes
resolver.commit();
} catch (Exception e) {
// Handle exceptions appropriately
resolver.refresh();
// Log or handle the exception as needed
} finally {
if (resolver.isLive()) {
resolver.close();
}
}
}
}
Thanks
Many Thanks for the suggestion @Madhur-Madan . This sounds to be a promising approach. I shall check and update.
JSONObject componentsChildJSon = new JSONObject();
Field field = componentsChildJSon.getClass().getDeclaredField("map");
field.setAccessible(true);
field.set(componentsChildJSon, new LinkedHashMap<>());
field.setAccessible(false);
while (childsOfChild.hasNext()) {
Resource child = childsOfChild.next();
JSONObject itemsJson = new JSONObject();
for (Map.Entry<String, Object> entrySet : child.getValueMap().entrySet()) {
itemsJson.put(entrySet.getKey(), entrySet.getValue().toString());
}
componentsChildJSon.put(child.getName(), itemsJson);
}
componentsChildJSon.remove("jcr:primaryType");
componentsJson.put(childResource.getName(), componentsChildJSon);
You will have to ask json to use LinkedHashMap to solve your issue.
Hope the above code snippet will help to understand.
TUmesh THakur
Views
Likes
Replies