¿Cómo debo escapar de cadenas en JSON?
Al crear datos JSON manualmente, ¿cómo debo escapar de los campos de cadena? ¿Debo usar algo como Apache Commons Lang's StringEscapeUtilities.escapeHtml
, StringEscapeUtilities.escapeXml
o debería usar java.net.URLEncoder
?
El problema es que cuando uso SEU.escapeHtml
, no escapa de las comillas y cuando envuelvo toda la cadena en un par de '
s, se generará un JSON con formato incorrecto.
Lo ideal es encontrar una biblioteca JSON en su idioma a la que pueda alimentar alguna estructura de datos adecuada y dejar que se preocupe por cómo escapar de las cosas . Te mantendrá mucho más cuerdo. Si por alguna razón no tienes una biblioteca en tu idioma, no quieres usar una (no sugeriría esto¹), o estás escribiendo una biblioteca JSON, sigue leyendo.
Escaparlo según el RFC. JSON es bastante liberal: los únicos caracteres de los que debes escapar son \
, "
y códigos de control (cualquier cosa menos que U+0020).
Esta estructura de escape es específica de JSON. Necesitará una función JSON específica. Todos los escapes se pueden escribir como ¿ \uXXXX
dónde XXXX
está la unidad de código UTF-16¹ para ese carácter? Hay algunos atajos, como \\
, que también funcionan. (Y dan como resultado un resultado más pequeño y claro).
Para obtener detalles completos, consulte el RFC .
¹El escape de JSON se basa en JS, por lo que utiliza \uXXXX
, donde XXXX
es una unidad de código UTF-16. Para puntos de código fuera del BMP, esto significa codificar pares sustitutos, lo que puede resultar un poco complicado. (O bien, puede simplemente generar el carácter directamente, ya que el código JSON es texto Unicode y permite estos caracteres en particular).
Extracto de Jettison :
public static String quote(String string) {
if (string == null || string.length() == 0) {
return "\"\"";
}
char c = 0;
int i;
int len = string.length();
StringBuilder sb = new StringBuilder(len + 4);
String t;
sb.append('"');
for (i = 0; i < len; i += 1) {
c = string.charAt(i);
switch (c) {
case '\\':
case '"':
sb.append('\\');
sb.append(c);
break;
case '/':
// if (b == '<') {
sb.append('\\');
// }
sb.append(c);
break;
case '\b':
sb.append("\\b");
break;
case '\t':
sb.append("\\t");
break;
case '\n':
sb.append("\\n");
break;
case '\f':
sb.append("\\f");
break;
case '\r':
sb.append("\\r");
break;
default:
if (c < ' ') {
t = "000" + Integer.toHexString(c);
sb.append("\\u" + t.substring(t.length() - 4));
} else {
sb.append(c);
}
}
}
sb.append('"');
return sb.toString();
}
Prueba esto org.codehaus.jettison.json.JSONObject.quote("your string")
.
Descárgalo aquí: http://mvnrepository.com/artifact/org.codehaus.jettison/jettison
Ahora hay un método StringEscapeUtils#escapeJson(String) en la biblioteca de texto Apache Commons .
Los métodos de interés son los siguientes:
- StringEscapeUtils#escapeJson(Cadena)
- StringEscapeUtils#unescapeJson(Cadena)
Esta funcionalidad se lanzó inicialmente como parte de Apache Commons Lang versión 3.2, pero desde entonces quedó obsoleta y se trasladó a Apache Commons Text . Entonces, si el método está marcado como obsoleto en su IDE, está importando la implementación de la biblioteca incorrecta (ambas bibliotecas usan el mismo nombre de clase: StringEscapeUtils ).
La implementación no es Json puro. Según el Javadoc :
Escapa de los caracteres en una cadena usando reglas de cadena Json.
Escapa de cualquier valor que encuentre en su forma Json String. Trata correctamente las comillas y los caracteres de control (tabulación, barra invertida, cr, ff, etc.)
Entonces una pestaña se convierte en los caracteres '\' y 't'.
La única diferencia entre las cadenas Java y las cadenas Json es que en Json, se escapa la barra diagonal (/).
Consulte http://www.ietf.org/rfc/rfc4627.txt para obtener más detalles.