Need Jackson Exporter JSON response within SlingModel Class | Community
Skip to main content
Level 2
December 22, 2020
Solved

Need Jackson Exporter JSON response within SlingModel Class

  • December 22, 2020
  • 5 replies
  • 6059 views

Hi Team,

Usecase:  Need to utilize model JSON response in the component sightly file. 

 

Basically, we use Jackson Exporter to get JSON response for SlingModel but it's a servlet call on the component resource. But my requirement is to get the JSON response for SlingModel from one of the getter functions of the Sling Model. 

something like - 

 

 

 

 

@Model(adaptables = { SlingHttpServletRequest.class }, adapters = { Button2.class, ComponentExporter.class }, resourceType = Button2Impl.RESOURCE_TYPE) @Exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, extensions = ExporterConstants.SLING_MODEL_EXTENSION) public class Button2Impl implements Button2 { @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL) private String label; public String getJsonString() { String json = "logic to get model json response like sling model exporter; return json; } }<sly data-sly-use.buttonProvider="${'com.sample.general.models.Button2'}"> <span> ${buttonProvider.jsonString} </span> </sly>

 

 

 

 

Could anyone suggest how to achieve the above scenario? 

 

Thanks,

Aman

 

SlingModel Implementation Class -

 

 

import com.adobe.cq.export.json.ComponentExporter; import com.adobe.cq.export.json.ExporterConstants; import com.day.cq.wcm.api.Page; import com.day.cq.wcm.api.PageManager; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import com.sample.sample.data_providers.general.models.Button2; import com.sample.sample.services.utils.LinkUtils; import org.apache.commons.lang3.StringUtils; import org.apache.felix.scr.annotations.Reference; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ResourceResolver; import org.apache.sling.api.resource.ResourceResolverFactory; import org.apache.sling.models.annotations.Exporter; import org.apache.sling.models.annotations.Model; import org.apache.sling.models.annotations.injectorspecific.InjectionStrategy; import org.apache.sling.models.annotations.injectorspecific.OSGiService; import org.apache.sling.models.annotations.injectorspecific.SlingObject; import org.apache.sling.models.annotations.injectorspecific.ValueMapValue; import org.apache.sling.models.factory.ExportException; import org.apache.sling.models.factory.MissingExporterException; import org.apache.sling.models.factory.ModelFactory; import java.util.HashMap; import java.util.Map; @Model(adaptables = { SlingHttpServletRequest.class }, adapters = { Button2.class, ComponentExporter.class }, resourceType = Button2Impl.RESOURCE_TYPE) @Exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, extensions = ExporterConstants.SLING_MODEL_EXTENSION) public class Button2Impl implements Button2 { public static final String RESOURCE_TYPE = "sample/components/general/button-2-0"; private ResourceResolverFactory resourceResolverFactory; @SlingObject private ResourceResolver resourceResolver; @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL) private String iconAlignment; @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL) private String buttonAlignment; @ValueMapValue(injectionStrategy = InjectionStrategy.OPTIONAL) private String marginBottom; @SlingObject private Resource resource; @SlingObject private SlingHttpServletRequest request; @OSGiService ModelFactory modelFactory; public String getIconAlignment() { return iconAlignment; } public String getButtonAlignment() { return buttonAlignment; } @JsonIgnore public String getMarginBottom() { return marginBottom; } public String getExportedType() { return resource.getResourceType(); } public String getJsonString() { Button2 buttonModel = request.adaptTo(Button2Impl.class); // tried adapting with resource as well but no luck Map<String,String> options = new HashMap(); String s = null; try { s = modelFactory.exportModel(buttonModel,ExporterConstants.SLING_MODEL_EXPORTER_NAME,String.class,options); } catch (ExportException e) { e.printStackTrace(); } catch (MissingExporterException e) { e.printStackTrace(); } return s; } }

 

 

The solution to this query - 

@JsonIgnore public String getJsonString() { ObjectMapper mapper = new ObjectMapper().configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); JsonNode node = mapper.valueToTree(this); String jsonString =null; try { jsonString = mapper.writeValueAsString(node); } catch (JsonProcessingException e) { e.getMessage(); } return jsonString; }
This post is no longer active and is closed to new replies. Need help? Start a new post to ask your question.
Best answer by shelly-goel

Hi@aman_goyal_15 

Another option is to use 'ObjectMapper' (com.fasterxml.jackson.databind.ObjectMapper) to map the model object as json. Add below method in your sling model class and either map the Button resource object or custom map object (with the specific value you need in json).

public String getJsonString() {
ObjectMapper mapper = new ObjectMapper();
JsonNode node = mapper.valueToTree(<button object>);
String jsonString ="no value";
try {
jsonString = mapper.writeValueAsString(node);
} catch (JsonProcessingException e) {
LOG.error("Cannot output json", e);
}
return jsonString;
}

You need to have the 'Button' object in the model

@Self @Via(type = ResourceSuperType.class)
private Button2 button;

 

5 replies

Kunal_Gaba_
December 22, 2020

You can use below code reference. Its a JSP code, you can convert it to Java and use in your sling model. The code uses Sling ModelFactory API to export a sling model. 

 

<% //Get reference to model factory org.apache.sling.models.factory.ModelFactory mf = sling.getService(org.apache.sling.models.factory.ModelFactory.class); //Get sling model Title title = slingRequest.adaptTo(com.adobe.cq.wcm.core.components.models.Title.class); Map<String,String> options = new HashMap(); //Export and print json String s = mf.exportModel(title,"jackson",String.class,options); out.println(s); %>

 

 

 

Output-

{"id":"title-d61980eb4b","linkDisabled":false,"type":"h3","text":"Standard",":type":"core/wcm/components/title/v2/title"}

 

Level 2
December 23, 2020
Thanks for your response. I tried the above approach but looks like it is not working. It is giving the null response while exporting model - String s = modelFactory.exportModel(buttonModel,ExporterConstants.SLING_MODEL_EXPORTER_NAME,String.class,options);
BrianKasingli
Community Advisor and Adobe Champion
Community Advisor and Adobe Champion
December 22, 2020

@aman_goyal_15 

Another way is to do something like this within the servlet.

1. Set the response content-type.

2. Using business logic, locate the Sling resource you need.

3. Adapt the Sling resource to Button2Impl.

4. output the JSON string.

Example:

 

@Override protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException { response.setContentType(APPLICATION_JSON_UTF8); Resource buttonResource = request.getResourceResolver().getResource("/content/my-page/jcr:content/par/button"); BUtton2 button2 = buttonResource.adaptTo(Button2Impl.class); if (button2 != null) { response.getWriter().write(button2.getJsonString()); } ... }

 

Level 2
December 23, 2020
Thanks for your response. Servlet is fine to expose the json once we get it. But I want to check for the approach to get the jsonString for Button2 model.
shelly-goel
Adobe Employee
shelly-goelAdobe EmployeeAccepted solution
Adobe Employee
December 22, 2020

Hi@aman_goyal_15 

Another option is to use 'ObjectMapper' (com.fasterxml.jackson.databind.ObjectMapper) to map the model object as json. Add below method in your sling model class and either map the Button resource object or custom map object (with the specific value you need in json).

public String getJsonString() {
ObjectMapper mapper = new ObjectMapper();
JsonNode node = mapper.valueToTree(<button object>);
String jsonString ="no value";
try {
jsonString = mapper.writeValueAsString(node);
} catch (JsonProcessingException e) {
LOG.error("Cannot output json", e);
}
return jsonString;
}

You need to have the 'Button' object in the model

@Self @Via(type = ResourceSuperType.class)
private Button2 button;

 

Level 2
December 23, 2020
Thanks for your response. Sling Model is not working when we are trying to get the Button2 object with @1961677 and @2434638. I was checking on the @2434638(type = ResourceSuperType.class), it is basically when we want to override the core component sling model. https://github.com/adobe/aem-core-wcm-components/wiki/Delegation-Pattern-for-Sling-Models#step-2-create-a-custom-sling-model-for-the-page-headline-component
Anudeep_Garnepudi
Community Advisor
Community Advisor
December 23, 2020

@aman_goyal_15 

Can you try 

@ScriptVariable Resource resource;

and then

resource.adaptTo(Button2Impl.class);

 

kautuk_sahni
Community Manager
Community Manager
January 11, 2021
Thank you for sharing the solution with community.
Kautuk Sahni