Your achievements

Level 1

0% to

Level 2

Tip /
Sign in

Sign in to Community

to gain points, level up, and earn exciting badges like the new
BedrockMission!

Learn more

View all

Sign in to view all badges

Splecial characters in RTE are displayed differently after conversion to JSON view

rajareddych
Level 2
Level 2

1. Created a custom component dialog, which has field='Answer Text' with richtext field

1681730_pastedImage_0.png

2. Gave Special characters as input

1681736_pastedImage_3.png

1681731_pastedImage_1.png

3. Create Sling Model Exporter for JSON output

@PostConstruct

public void invokepost() {

if (answerText != null && !answerText.isEmpty()) {

answerText = formatAnswerRTEText(answerText);

}

}

// In this method, rteText is passed as a parameter which needs to be trimmed and covered with double quotes and remove all the new lines in the text

private String formatAnswerRTEText(String rteText) {

String modifiedRteText = null;

modifiedRteText = "\"" + rteText.trim() + "\"";

modifiedRteText = modifiedRteText .replaceAll("\\r|\\n", "");

return modifiedRteText ;

}

4. JSON output is not displaying special characters

1681737_pastedImage_8.png

Please guide me in resolving this issue. (Special characters should be displayed as it is in JSON output)

12 Replies
Gaurav-Behl
Community Advisor
Community Advisor

Make sure to export the content as "UTF-8", check the sling exporter version per below link-

[SLING-7344] Jackson Sling Model Exporter needs correct character encoding - ASF JIRA

test with latest version and revert

rajareddych
Level 2
Level 2

I have followed to crate similar servlet, I am getting error at json = object.writeValueAsString(answerModel); for writeValueAsString

@SlingServlet(

resourceTypes = {AHMJsonServiceConstants.ANSWER_RT},

selectors = "servlet",

extensions = "json",

methods = "GET"

)

public class ContentServlet extends SlingSafeMethodsServlet {

private static final long serialVersionUID = -1765279544984834180L;

private static Logger LOG = LoggerFactory.getLogger(AnswerModel.class);

@Override

    protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {

        Resource answerResource = request.getResource();

        AnswerModel answerModel = answerResource.adaptTo(AnswerModel.class);

       

        Object object = new Object();

        String json = "{}";

        try {

            json = object.writeValueAsString(answerModel);

        } catch (RepositoryException e) {

        LOG.error(AHMJsonServiceConstants.MSG_PROCESSING_ERROR + e.getMessage());

            // Silently die as this is a POC

        }

        // The magic to make localized content work.

            // BOTH ContentType and CharacterEncoding must be set.

            response.setContentType("application/json");

            response.setCharacterEncoding("UTF-8");

            response.getWriter().write(json);

Gaurav-Behl
Community Advisor
Community Advisor

could you share the error trace?

this is incomplete code as I can't interpret a lot of lines-

-resourceTypes = {AHMJsonServiceConstants.ANSWER_RT},

AnswerModel answerModel = answerResource.adaptTo(AnswerModel.class);

rajareddych
Level 2
Level 2

[ERROR] /C:/Users/raja/Desktop/aem-release/core/src/main/java/com/core/servlets/qr/ContentServlet.java:[40,26] cannot find symbol

  symbol:   method writeValueAsString(com.aetna.ahm.core.models.qr.AnswerModel)

  location: variable object of type java.lang.Object

Gaurav-Behl
Community Advisor
Community Advisor

The error you have mentioned 'cannot find symbol' is not related to this JSON-special characters. 

I'll test the special characters issue later and revert acc.

Its most likely related to the default character encoding being set on Sling exporter. There must be a configuration to check/fix, if applicable.

smacdonald2008
Level 10
Level 10

The team believes this is not a RTE issue - but an output issue. Make sure you are setting the encoding properly.

Gaurav-Behl
Community Advisor
Community Advisor

I tested this and it worked fine. As Scott mentioned use encode/decode as applicable.

output:

{":type": "weretail/components/content/text","message": "some junk characters test=€ , Š , Œ , ™ , š , œ , ž{}[]<>=-()@#$&*"}

acs-aem-samples/SampleComponentExporter.java at master · Adobe-Consulting-Services/acs-aem-samples ·...

import org.apache.sling.api.SlingHttpServletRequest;

import org.apache.sling.api.resource.Resource;

import org.apache.sling.api.resource.ResourceResolver;

import org.apache.sling.models.annotations.DefaultInjectionStrategy;

import org.apache.sling.models.annotations.Exporter;

import org.apache.sling.models.annotations.ExporterOption;

import org.apache.sling.models.annotations.Model;

import org.apache.sling.models.annotations.Required;

import org.apache.sling.models.annotations.injectorspecific.Self;

import org.apache.sling.models.annotations.injectorspecific.SlingObject;

import com.adobe.cq.export.json.ComponentExporter;

import com.adobe.cq.export.json.ExporterConstants;

import com.fasterxml.jackson.databind.annotation.JsonSerialize;

/**

* This file focuses on making a Sling Model compatible with AEM Content

* Services (and thus SPA Editor), as this requires: a) Implementing the

* ComponentExporter interface.

*

* Note that these is a sibling interface to ComponentExporter,

* com.adobe.cq.export.json.ContainerExporter, that is used for components that

* included other components (like the Layout Container).

*

* For more detailed examples of Sling Models and Sling Model Exporters, see

* this file's sibling sample files (SampleSlingModel.class and

* SampleSlingModelExporter.class).

*/

@Model(

// This must adapt from a SlingHttpServletRequest, since this is invoked

// directly via a request, and not via a resource.

// If can specify Resource.class as a second adaptable as needed

adaptables = { SlingHttpServletRequest.class },

// This Model should have the specific Model class

// (SampleComponentExporter.class)

// AS WELL AS the ComponentExporter.class. Its required that

// ComponentExporter.class to be set at an adapter

// since this how the AEM Content Services JSON Exporter figures out which

// resources to serialize.

adapters = { SampleComponentExporter.class, ComponentExporter.class },

// The resourceType is required if you want Sling to "naturally" expose this

// model as the exporter for a Resource.

resourceType = SampleComponentExporter.RESOURCE_TYPE,

defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)

// name = the registered name of the exporter (  ExporterConstants.SLING_MODEL_EXPORTER_NAME => jackson )

// extensions = the extensions this exporter is registered to (ExporterConstants.SLING_MODEL_EXTENSION => json)

// selector = defaults to "model", can override as needed; This is helpful if a single resource needs 2 different JSON renditions.

//            (ExporterConstants.SLING_MODEL_SELECTOR => model)

@Exporter(name = ExporterConstants.SLING_MODEL_EXPORTER_NAME, selector = ExporterConstants.SLING_MODEL_SELECTOR,

extensions = ExporterConstants.SLING_MODEL_EXTENSION, options = { // options are optional... this just shows

// that it is possible...

/**

* Jackson options: - Mapper Features:

* http://static.javadoc.io/com.fasterxml.jackson.core/jackson-databind/2.8.5/com/fasterxml/jackson/dat...

* - Serialization Features:

* http://static.javadoc.io/com.fasterxml.jackson.core/jackson-databind/2.8.5/com/fasterxml/jackson/dat...

*/

@ExporterOption(name = "MapperFeature.SORT_PROPERTIES_ALPHABETICALLY", value = "true"),

@ExporterOption(name = "SerializationFeature.WRITE_DATES_AS_TIMESTAMPS", value = "false") })

// Mark as JSON Serializable as the Model's class (SampleComponentExporter.class) or interface if those are used.

@JsonSerialize(as = SampleComponentExporter.class)

// Make sure the Model implementation implements (or the Model interface extends) com.adobe.cq.export.json.ComponentExporter.

public class SampleComponentExporter implements ComponentExporter {

static final String RESOURCE_TYPE = "weretail/components/content/text";

@Self

private SlingHttpServletRequest request;

@Self

private Resource resource;

// Injection will occur over all Injectors based on Ranking;

// Force an Injector using @Source(..)

// If an Injector is not working; ensure you are using the latest version of

// Sling Models

@SlingObject

@Required

private ResourceResolver resourceResolver;

@Override

public String getExportedType() {

// This method is required by ComponentExporter and its value populates the

// `:type` key in the JSON object.

// The resource value is ~always the ResourceType for this model (See @Model(..)

// above).

return RESOURCE_TYPE;

}

/**

* Jackson Annotations on the method level are supported;

* ie. @JsonIgnore, @JsonProperty(..), etc.

*

* For Jackson Annotations:

* https://github.com/FasterXML/jackson-annotations/wiki/Jackson-Annotations

*/

public String getMessage() {

String rteString = "some junk characters test=€ , Š , Œ , ™ , š , œ , ž{}[]<>=-()@#$&*";

// encode/decode as applicable

return String.format(rteString, request.getResource().getPath());

}

}

rajareddych
Level 2
Level 2

Answer Model is a JSON sling model exporter with 3 fields, 2 are RTE fields.

smacdonald2008
Level 10
Level 10

I am checking with the team - I have never seen this use case of wanting to export spec chars in JSON before.

rajareddych
Level 2
Level 2

Thank you guys, I have used replace keyword instead of decoding, and is working as expected.