Comment personnaliser l’encodage de caractères avec System.Text.Json

Par défaut, le sérialiseur échappe tous les caractères non ASCII. Autrement dit, il les remplace par \uxxxx, où xxxx est le code Unicode du caractère. Par exemple, si la propriété Summary dans le code JSON suivant est définie sur cyrillique жарко, l’objet WeatherForecast est sérialisé comme illustré dans cet exemple :

{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25,
  "Summary": "\u0436\u0430\u0440\u043A\u043E"
}

Sérialiser des jeux de caractères d’une langue

Pour sérialiser le ou les jeux de caractères d’une ou plusieurs langues sans échappement, spécifiez la ou les plages Unicode lors de la création d’une instance de System.Text.Encodings.Web.JavaScriptEncoder, comme illustré dans l’exemple suivant :

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)

Ce code n’échappe pas les caractères cyrilliques ou grecs. Si la propriété Summary est définie sur cyrillique жарко, l’objet WeatherForecast est sérialisé comme indiqué dans cet exemple :

{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25,
  "Summary": "жарко"
}

Par défaut, l’encodeur est initialisé avec la plage BasicLatin.

Pour sérialiser tous les jeux de langue sans échappement, utilisez UnicodeRanges.All.

Sérialiser des caractères spécifiques

Une alternative consiste à spécifier des caractères individuels que vous souhaitez autoriser à ne pas être échappés. L’exemple suivant sérialise uniquement les deux premiers caractères 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)

Voici un exemple de JSON produit par le code précédent :

{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25,
  "Summary": "жа\u0440\u043A\u043E"
}

Listes de blocs

Les sections précédentes montrent comment spécifier des listes d’autorisation de points de code ou de plages que vous ne souhaitez pas échapper. Toutefois, il existe des listes de blocs globales et spécifiques à l’encodeur qui peuvent remplacer certains points de code dans votre liste d’autorisation. Les points de code d’une liste bloquée sont toujours placés dans une séquence d’échappement, même s’ils sont inclus dans votre liste d’autorisation.

Liste globale de blocage

La liste globale contient des éléments comme des caractères à usage privé, des caractères de contrôle, des points de code non définis et certaines catégories Unicode, comme Space_Separator category, à l’exclusion de U+0020 SPACE. Par exemple, U+3000 IDEOGRAPHIC SPACE est échappé même si vous spécifiez la plage Unicode Symboles CJK et ponctuation (U+3000-U+303F) comme liste d’autorisation.

La liste globale de blocage est un détail d’implémentation qui a changé dans chaque version de .NET. Ne vous appuyez pas sur le fait qu’un caractère soit membre (ou non membre) de la liste de blocage globale.

Listes de blocage spécifiques à l’encodeur

Des exemples de points de code bloqués spécifiques à l’encodeur incluent '<' et '&' pour l’encodeur HTML, '\' pour l’encodeur JSON et '%' pour l’encodeur d’URL. Par exemple, l’encodeur HTML échappe toujours les esperluettes ('&'), même si l’esperluette se trouve dans la plage BasicLatin et que tous les encodeurs sont initialisés avec BasicLatin par défaut.

Sérialiser tous les caractères

Pour réduire l’échappement, vous pouvez utiliser JavaScriptEncoder.UnsafeRelaxedJsonEscaping, comme illustré dans l’exemple suivant :

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)

Attention

Par rapport à l’encodeur par défaut, l’encodeur UnsafeRelaxedJsonEscaping est plus permissif quant au passage des caractères sans les échapper :

  • Il n’échappe pas les caractères HTML sensibles comme <, >, & et '.
  • Il n’offre pas de protection supplémentaire en profondeur contre les attaques XSS ou de divulgation d’informations, comme celles qui peuvent résulter d’un désaccord entre le client et le serveur sur le jeu de caractères.

Utilisez l’encodeur non sécurisé uniquement lorsqu’il est connu que le client interprétera la charge utile résultante en tant que JSON encodé en UTF-8. Par exemple, vous pouvez l’utiliser si le serveur envoie l’en-tête de réponse Content-Type: application/json; charset=utf-8. N’autorisez jamais l’émission de la sortie brute UnsafeRelaxedJsonEscaping dans une page HTML ou un élément <script>.

Voir aussi