Lingua
Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Questo articolo illustra come gestire l'overflow di JSON usando lo spazio dei nomi System.Text.Json. Illustra anche come deserializzare in JsonElement o JsonNode, come alternativa ad altri scenari in cui il tipo di destinazione potrebbe non corrispondere perfettamente a tutti i JSON da deserializzare.
Gestire il JSON di overflow
Durante la deserializzazione, è possibile ricevere dati nel codice JSON che non è rappresentato dalle proprietà del tipo di destinazione. Si supponga, ad esempio, che il tipo di destinazione sia il seguente:
public class WeatherForecast
{
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
}
Public Class WeatherForecast
Public Property [Date] As DateTimeOffset
Public Property TemperatureCelsius As Integer
Public Property Summary As String
End Class
Il codice JSON da deserializzare è il seguente:
{
"Date": "2019-08-01T00:00:00-07:00",
"temperatureCelsius": 25,
"Summary": "Hot",
"DatesAvailable": [
"2019-08-01T00:00:00-07:00",
"2019-08-02T00:00:00-07:00"
],
"SummaryWords": [
"Cool",
"Windy",
"Humid"
]
}
Se si deserializza il codice JSON visualizzato nel tipo visualizzato, le proprietà DatesAvailable e SummaryWords non possono essere spostate e andranno perse. Per acquisire dati aggiuntivi, ad esempio queste proprietà, applicare l'attributo [JsonExtensionData] a una proprietà o a un campo. Usare una di queste dichiarazioni supportate:
- Dichiarare il membro extension-data come JsonObject.
- Dichiarare il membro extension-data come
IDictionary<string, object>. - Dichiarare il membro extension-data come
IDictionary<string, JsonElement>. - Dichiarare il membro extension-data come
IReadOnlyDictionary<string, object>in .NET 11 e versioni successive. - Dichiarare il membro extension-data come
IReadOnlyDictionary<string, JsonElement>in .NET 11 e nelle versioni successive.
Per i dati dell'estensione del dizionario modificabile, usare qualsiasi tipo assegnabile a una delle interfacce supportate IDictionary , ad esempio Dictionary<string, JsonElement>. Le dichiarazioni di sola lettura devono usare uno dei tipi di interfaccia esatti IReadOnlyDictionary elencati in precedenza.
public class WeatherForecastWithExtensionData
{
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
[JsonExtensionData]
public Dictionary<string, JsonElement>? ExtensionData { get; set; }
}
Public Class WeatherForecastWithExtensionData
Public Property [Date] As DateTimeOffset
Public Property TemperatureCelsius As Integer
Public Property Summary As String
<JsonExtensionData>
Public Property ExtensionData As Dictionary(Of String, Object)
End Class
Per un membro dati di estensione IReadOnlyDictionary, .NET 11 materializza un Dictionary<string, object> o un Dictionary<string, JsonElement>. Il membro deve essere scrivibile perché il serializzatore inizializza il nuovo dizionario a partire dai valori esistenti e lo riassegna. Se una proprietà JSON in ingresso duplica una chiave esistente, il valore in ingresso prevale.
La tabella seguente illustra il risultato della deserializzazione del codice JSON illustrato in precedenza in questo tipo di esempio. I dati aggiuntivi diventano coppie chiave-valore della proprietà ExtensionData:
| Proprietà | Valore | Note |
|---|---|---|
Date |
"8/1/2019 12:00:00 AM -07:00" |
|
TemperatureCelsius |
0 |
Mancata corrispondenza dovuta alla distinzione tra maiuscole e minuscole (temperatureCelsius nel JSON), quindi la proprietà non viene impostata. |
Summary |
"Hot" |
|
ExtensionData |
"temperatureCelsius": 25,"DatesAvailable": ["2019-08-01T00:00:00-07:00","2019-08-02T00:00:00-07:00"],"SummaryWords": ["Cool","Windy","Humid"] |
Poiché il caso non corrispondeva, temperatureCelsius è un elemento aggiuntivo e diventa una coppia chiave-valore nel dizionario. Ogni matrice aggiuntiva dal codice JSON diventa una coppia chiave-valore, con una matrice come oggetto valore. |
Quando l'oggetto di destinazione viene serializzato, le coppie di chiave dati di estensione diventano proprietà JSON esattamente come nel codice JSON in ingresso:
{
"Date": "2019-08-01T00:00:00-07:00",
"TemperatureCelsius": 0,
"Summary": "Hot",
"temperatureCelsius": 25,
"DatesAvailable": [
"2019-08-01T00:00:00-07:00",
"2019-08-02T00:00:00-07:00"
],
"SummaryWords": [
"Cool",
"Windy",
"Humid"
]
}
Si noti che il nome della proprietà ExtensionData non viene visualizzato nel codice JSON. Questo comportamento consente al JSON di eseguire un round trip senza perdere dati aggiuntivi che altrimenti non verrebbero deserializzati.
A partire da .NET 11, la serializzazione appiattisce i JsonObject dati di estensione nell'oggetto JSON che li contiene. Le JsonObject proprietà vengono visualizzate direttamente nell'oggetto contenitore, non sotto il nome del membro extension-data.
L'esempio seguente mostra un round trip da JSON a un oggetto deserializzato e nuovamente a JSON:
using System.Text.Json;
using System.Text.Json.Serialization;
namespace RoundtripExtensionData
{
public class WeatherForecast
{
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
[JsonExtensionData]
public Dictionary<string, JsonElement>? ExtensionData { get; set; }
}
public class Program
{
public static void Main()
{
string jsonString =
@"{
""Date"": ""2019-08-01T00:00:00-07:00"",
""temperatureCelsius"": 25,
""Summary"": ""Hot"",
""SummaryField"": ""Hot"",
""DatesAvailable"": [
""2019-08-01T00:00:00-07:00"",
""2019-08-02T00:00:00-07:00""
],
""SummaryWords"": [
""Cool"",
""Windy"",
""Humid""
]
}";
WeatherForecast weatherForecast =
JsonSerializer.Deserialize<WeatherForecast>(jsonString)!;
var serializeOptions = new JsonSerializerOptions { WriteIndented = true };
jsonString = JsonSerializer.Serialize(weatherForecast, serializeOptions);
Console.WriteLine($"JSON output:\n{jsonString}\n");
}
}
}
// output:
//JSON output:
//{
// "Date": "2019-08-01T00:00:00-07:00",
// "TemperatureCelsius": 0,
// "Summary": "Hot",
// "temperatureCelsius": 25,
// "SummaryField": "Hot",
// "DatesAvailable": [
// "2019-08-01T00:00:00-07:00",
// "2019-08-02T00:00:00-07:00"
// ],
// "SummaryWords": [
// "Cool",
// "Windy",
// "Humid"
// ]
//}
Deserializzare in JsonElement o JsonNode
Se si vuole essere flessibili su quale JSON sia accettabile per una particolare proprietà un'alternativa consiste nel deserializzare in JsonElement o JsonNode. Qualsiasi proprietà JSON valida può essere deserializzata in JsonElement o JsonNode. Scegli JsonElement per creare un oggetto immutabile oppure JsonNode per creare un oggetto modificabile.
L'esempio seguente mostra un round trip da JSON e nuovamente a JSON per una classe che include proprietà di tipo JsonElement e JsonNode.
using System.Text.Json;
using System.Text.Json.Nodes;
namespace RoundtripJsonElementAndNode
{
public class WeatherForecast
{
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
public JsonElement DatesAvailable { get; set; }
public JsonNode? SummaryWords { get; set; }
}
public class Program
{
public static void Main()
{
string jsonString =
@"{
""Date"": ""2019-08-01T00:00:00-07:00"",
""TemperatureCelsius"": 25,
""Summary"": ""Hot"",
""DatesAvailable"": [
""2019-08-01T00:00:00-07:00"",
""2019-08-02T00:00:00-07:00""
],
""SummaryWords"": [
""Cool"",
""Windy"",
""Humid""
]
}";
WeatherForecast? weatherForecast =
JsonSerializer.Deserialize<WeatherForecast>(jsonString);
var serializeOptions = new JsonSerializerOptions { WriteIndented = true };
jsonString = JsonSerializer.Serialize(weatherForecast, serializeOptions);
Console.WriteLine(jsonString);
}
}
}
// output:
//{
// "Date": "2019-08-01T00:00:00-07:00",
// "TemperatureCelsius": 25,
// "Summary": "Hot",
// "DatesAvailable": [
// "2019-08-01T00:00:00-07:00",
// "2019-08-02T00:00:00-07:00"
// ],
// "SummaryWords": [
// "Cool",
// "Windy",
// "Humid"
// ]
//}