Personalización de la codificación de caracteres con System.Text.Json
De forma predeterminada, el serializador escapa a todos los caracteres que no sean ASCII. Es decir, los reemplaza por \uxxxx
donde xxxx
es el código Unicode del carácter. Por ejemplo, si la propiedad Summary
del siguiente código JSON está establecida en cirílico жарко
, el objeto WeatherForecast
se serializa tal y como se muestra en este ejemplo:
{
"Date": "2019-08-01T00:00:00-07:00",
"TemperatureCelsius": 25,
"Summary": "\u0436\u0430\u0440\u043A\u043E"
}
Serialización de juegos de caracteres de idioma
Para serializar los juegos de caracteres de uno o más idiomas sin escape, especifique intervalos Unicode al crear una instancia de System.Text.Encodings.Web.JavaScriptEncoder, tal y como se muestra en el ejemplo siguiente:
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Unicode;
Imports System.Text.Encodings.Web
Imports System.Text.Json
Imports System.Text.Unicode
var options1 = new JsonSerializerOptions
{
Encoder = JavaScriptEncoder.Create(UnicodeRanges.BasicLatin, UnicodeRanges.Cyrillic),
WriteIndented = true
};
jsonString = JsonSerializer.Serialize(weatherForecast, options1);
options = New JsonSerializerOptions With {
.Encoder = JavaScriptEncoder.Create(UnicodeRanges.BasicLatin, UnicodeRanges.Cyrillic),
.WriteIndented = True
}
jsonString = JsonSerializer.Serialize(weatherForecast1, options)
Este código no escapa a los caracteres cirílicos o griegos. Si la propiedad Summary
está establecida en cirílico жарко
, el objeto WeatherForecast
se serializa tal y como se muestra en este ejemplo:
{
"Date": "2019-08-01T00:00:00-07:00",
"TemperatureCelsius": 25,
"Summary": "жарко"
}
De forma predeterminada, el codificador se inicializa con el intervalo BasicLatin.
Para serializar todos los conjuntos de lenguaje sin escape, use UnicodeRanges.All.
Serialización de caracteres específicos
Una alternativa consiste en especificar caracteres individuales que se quieren dejar pasar sin secuencia de escape. En el ejemplo siguiente se serializan solo los dos primeros caracteres de жарко
:
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Unicode;
Imports System.Text.Encodings.Web
Imports System.Text.Json
Imports System.Text.Unicode
var encoderSettings = new TextEncoderSettings();
encoderSettings.AllowCharacters('\u0436', '\u0430');
encoderSettings.AllowRange(UnicodeRanges.BasicLatin);
var options2 = new JsonSerializerOptions
{
Encoder = JavaScriptEncoder.Create(encoderSettings),
WriteIndented = true
};
jsonString = JsonSerializer.Serialize(weatherForecast, options2);
Dim encoderSettings As TextEncoderSettings = New TextEncoderSettings
encoderSettings.AllowCharacters(ChrW(&H436), ChrW(&H430))
encoderSettings.AllowRange(UnicodeRanges.BasicLatin)
options = New JsonSerializerOptions With {
.Encoder = JavaScriptEncoder.Create(encoderSettings),
.WriteIndented = True
}
jsonString = JsonSerializer.Serialize(weatherForecast1, options)
Aquí se muestra un ejemplo de JSON producido por el código anterior:
{
"Date": "2019-08-01T00:00:00-07:00",
"TemperatureCelsius": 25,
"Summary": "жа\u0440\u043A\u043E"
}
Listas de bloqueos
En las secciones anteriores se muestra cómo especificar las listas de los puntos de código o intervalos permitidos que no desea que se usen como secuencia de escape. Sin embargo, hay listas globales de bloqueos y específicas del codificador que pueden invalidar determinados puntos de código en la lista de permitidos. Los puntos de código de una lista de bloqueos siempre se usan como secuencia de escape, incluso si están incluidos en la lista de permitidos.
Lista global de bloqueos
La lista global de bloqueos incluye elementos como caracteres de uso privado, caracteres de control, puntos de código no definidos y determinadas categorías Unicode, como la categoría Space_Separator, excepto U+0020 SPACE
. Por ejemplo, U+3000 IDEOGRAPHIC SPACE
se usa como carácter de escape incluso si especifica símbolos CJK y puntuación de intervalo de Unicode (U+3000-U+303F) como lista de permitidos.
La lista global de bloques es un detalle de implementación que ha cambiado en cada versión de .NET. No tome ninguna dependencia de un carácter que sea miembro (o no) de la lista global de bloqueos.
Listas de bloqueos específicas del codificador
Algunos ejemplos de puntos de código bloqueados específicos del codificador incluyen '<'
y '&'
para el codificador HTML, '\'
para el codificador JSON y '%'
para el codificador de direcciones URL. Por ejemplo, el codificador HTML siempre usa el carácter "Y comercial" ('&'
), incluso aunque esté en el intervalo BasicLatin
y todos los codificadores se inicialicen con BasicLatin
de forma predeterminada.
Serialización de todos los caracteres
Para minimizar el escape, puede usar JavaScriptEncoder.UnsafeRelaxedJsonEscaping tal y como se muestra en el ejemplo siguiente:
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Unicode;
Imports System.Text.Encodings.Web
Imports System.Text.Json
Imports System.Text.Unicode
var options3 = new JsonSerializerOptions
{
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
WriteIndented = true
};
jsonString = JsonSerializer.Serialize(weatherForecast, options3);
options = New JsonSerializerOptions With {
.Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
.WriteIndented = True
}
jsonString = JsonSerializer.Serialize(weatherForecast1, options)
Precaución
En comparación con el codificador predeterminado, el codificador UnsafeRelaxedJsonEscaping
es más permisivo sobre dejar que los caracteres pasen sin secuencia de escape:
- No escapa a caracteres que distinguen HTML, tales como
<
,>
,&
y'
. - No ofrece ninguna protección adicional de defensa en profundidad contra ataques de divulgación de información y XSS, tales como los que podrían traducirse en un desacuerdo entre el cliente y el servidor sobre el juego de caracteres.
Use el codificador no seguro solo cuando sepa que el cliente va a interpretar la carga resultante como JSON con codificación UTF-8. Por ejemplo, puede utilizarlo si el servidor envía el encabezado de respuesta Content-Type: application/json; charset=utf-8
. No permita nunca que la salida de UnsafeRelaxedJsonEscaping
sin formato se emita en una página HTML o en un elemento <script>
.