Balaji Jayasankar
Balaji Jayasankar

Reputation: 43

Spring MVC: Need elegant solution to handle escaping and unescaping of strings passed into Front End

I am building a web application using Spring MVC. The application involves fetching multiple objects containing strings as attributes from the Database. I have no control over the format of these strings entered into the Database.

I ran into a problem where when strings having quotes in them(" and ') are passed into JavaScript as the attributes of JSON Objects, they are not recognized as part of the string, and hence they close the quotes of the string they were part of. I solved this issue by calling the JavaScriptUtils.javaScriptEscape() function on every string fetched from the database in a wrapper function.

This fixes the JavaScript errors, but now I have the problem that when the same strings displayed on the webpage, the escape character '\' is included(i.e " displayed as \" etc). My requirements now are the following:

  1. Need a function to 'unescape' these strings back to normal form so they work as intended

  2. Need a way to apply said function to all the strings fetched into the front end. It is too much of a pain to individually call this function to each attribute of each JSON object fetched in each AJAX call. As more features will be added to the application in the future, the solution should preferably be one that does not require to be hardcoded into every AJAX request.

  3. Need a better way to apply this escaping to the objects fetched from database. Right now, I am having a separate function which Escapes the strings in each object, but the problem with this is that I will need to define a new function every time a new type of object is fetched.

I wonder whether there is a way to make Spring MVC automatically deal with this, as it seems to be an issue most developers would face at some point. Any suggestions that will help make this easier for me are appreciated!

EDIT:

This is the function which is called on every string fetched from the database:

String EscapeJS(String string)
{
    string = JavaScriptUtils.javaScriptEscape(string);
    return string;
}

This is how the objects are returned:

@RequestMapping(value = "/urlToController", method = RequestMethod.POST)
public ResponseEntity<Object> returnObject(@RequestBody String option)
{
    Object object = wrapperFunction(fetchObjectFromBackend(option));

    return new ResponseEntity<>(object, HttpStatus.OK);
}

Here, the 'wrapperFunction()' converts all strings inside the object using EscapeJS()

This is an AJAX call:

$.ajax({
        type: "POST",
        headers:
        {
            'Accept': 'application/json',
            'Content-Type': 'application/json'
        },
        url: '/urlToController',
        data: option,
        success: function(returnedObject)
        {
            console.log(returnedObject);
        },
        error : function(dataString)
        {
            alert("AJAX Call failed");
            console.log(dataString);
        }
    });

Upvotes: 2

Views: 1882

Answers (1)

Joe W
Joe W

Reputation: 2891

There are a couple of ways to make the string escaping more generic. The most capable and advanced way would be to create a custom ObjectMapper where you could handle all of the different escaping and setup that you want to do. Then if you register that ObjectMapper with Spring you'll have full control over how the json is generated. For Spring MVC see here for an example:

http://magicmonster.com/kb/prg/java/spring/webmvc/jackson_custom.html

And for Spring boot it is a bit easier: Configuring ObjectMapper in Spring

Another option that is a bit less capable but maybe easier is to just create a wrapper object that just manages the string escaping for you as part of the bean. So change this:

Object object = wrapperFunction(fetchObjectFromBackend(option));
return new ResponseEntity<>(object, HttpStatus.OK);

To something like this:

Object object = wrapperFunction(fetchObjectFromBackend(option));
//The wrapper would make the escape calls needed and have a single property to 
//return the escaped string for you
MyWrapper wrapped = new MyWrapper(object);
return new ResponseEntity<>(wrapped, HttpStatus.OK);

Where the constructor of MyWrapper does whatever you need done to the data. You could also then just return the escaped string directly if preferred:

return new ResponseEntity<>(wrapped.getEscapedString(), HttpStatus.OK);

The ObjectMapper is probably the better way to go long term but it depends on your system and planned setup.

Upvotes: 1

Related Questions