Spring: escapeBody приводит к недействительности JSON

Я пытаюсь избежать строки в JSP, чтобы возвращать действительный JSON в вызове AJAX, однако тег spring: escapeBody неправильно экранирует одиночные кавычки для JSON. Действительный JSON не должен избегать одиночных кавычек.

<%@ page trimDirectiveWhitespaces="true" contentType="json/application"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
{
"status": "success",
"body" : "<spring:escapeBody javaScriptEscape="true"> 
           if you don't have "user" an account
           </spring:escapeBody>"
 }

поэтому этот код оценивается как:

{
"status": "success",
"body" : "if you don\'t have \"user\" an account"
 }

но действительный JSON нуждается в этом:

{
"status": "success",
"body" : "if you don't have \"user\" an account"
 }

В любом случае я не могу избежать одиночной цитаты с тегом escapeBody? Или есть другой тег, который я могу использовать? возможно, функция JSTL?

Ответ 1

Как отметил Райан в (очень хороших) комментариях Sotirios Delimanolis, ответьте:

  • Javascript Object Notation указывает, что Any character may be escaped. Очевидно, это означает, что даже одиночные кавычки могут быть.
  • Однако, как указал Райан (опять же в тех же комментариях), это возникает как ошибка при реализации jQuery Ajax. см. одинарная кавычка jQuery в ответе JSON

Итак, похоже, что это просто выбор реализации, который теперь оставляет нас со стандартом, который на самом деле не выполняется последовательно... sigh

В любом случае, вот работа, которую вы можете использовать, чтобы заставить ваш код работать

<%@ page trimDirectiveWhitespaces="true" contentType="json/application"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%-- 
    [1] Removing the escape of the single quote character: jQuery Ajax cannot handle it
            stackoverflow.com/questions/25491391/springescapebody-results-in-invalid-json
            stackoverflow.com/questions/2275359/jquery-single-quote-in-json-response
--%>
<c:set var="someJsonData" >
    <spring:escapeBody javaScriptEscape="true"> 
               if you don't have "user" an account
    </spring:escapeBody>
</c:set>    
{
    "status": "success",
    "body" : "${fn:replace(someJsonData, "\\\'","'")}" , <%-- [1] --%>
}

Вот документация JSTL fn

Наверное, не чистое/лучшее решение, если честно. Но он выполняет эту работу, пока вы не найдете лучшего.

Ответ 2

Спецификация обозначений объектов Javascript утверждает, что

Любой символ может быть экранирован.

Таким образом,

{
    "status": "success",
    "body" : "if you don\'t have \"user\" an account"
}

действует JSON.

Если вам нужно создать действительно настраиваемый текст, вам нужно создать его самостоятельно в методе обработчика контроллера или другом компоненте.

В идеале вы бы использовали аннотированный метод @ResponseBody с POJO, который представляет ваш объект JSON вашего статуса/тела.