Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Bu makalede, özel ayrıştırıcılar ve seri durumdan Utf8JsonReader çıkarıcılar oluşturmak için türünü nasıl kullanabileceğiniz gösterilmektedir.
Utf8JsonReader UTF-8 ile kodlanmış JSON metni için yüksek performanslı, düşük ayırmalı, yalnızca ileriye dönük bir okuyucudur. Metin bir ReadOnlySpan<byte> veya ReadOnlySequence<byte>'den okunur. Utf8JsonReader , özel ayrıştırıcılar ve seri durumdan çıkarıcılar oluşturmak için kullanılabilecek düşük düzeyli bir türdür. (Yöntemler JsonSerializer.Deserialize , kapakların altında kullanılır Utf8JsonReader .)
Aşağıdaki örnekte sınıfının nasıl kullanılacağı gösterilmektedir Utf8JsonReader . Bu kod, değişkenin jsonUtf8Bytes UTF-8 olarak kodlanmış geçerli JSON içeren bir bayt dizisi olduğunu varsayar.
var options = new JsonReaderOptions
{
AllowTrailingCommas = true,
CommentHandling = JsonCommentHandling.Skip
};
var reader = new Utf8JsonReader(jsonUtf8Bytes, options);
while (reader.Read())
{
Console.Write(reader.TokenType);
switch (reader.TokenType)
{
case JsonTokenType.PropertyName:
case JsonTokenType.String:
{
string? text = reader.GetString();
Console.Write(" ");
Console.Write(text);
break;
}
case JsonTokenType.Number:
{
int intValue = reader.GetInt32();
Console.Write(" ");
Console.Write(intValue);
break;
}
// Other token types elided for brevity
}
Console.WriteLine();
}
' This code example doesn't apply to Visual Basic. For more information, go to the following URL:
' https://learn.microsoft.com/dotnet/standard/serialization/system-text-json-how-to#visual-basic-support
Not
Utf8JsonReader doğrudan Visual Basic kodundan kullanılamaz. Daha fazla bilgi için bkz . Visual Basic desteği.
Kullanarak verileri filtreleme Utf8JsonReader
Aşağıdaki örnekte, bir dosyanın zaman uyumlu bir şekilde nasıl okunduğu ve bir değerin nasıl aranduğu gösterilmektedir.
using System.Text;
using System.Text.Json;
namespace SystemTextJsonSamples
{
public class Utf8ReaderFromFile
{
private static readonly byte[] s_nameUtf8 = Encoding.UTF8.GetBytes("name");
private static ReadOnlySpan<byte> Utf8Bom => new byte[] { 0xEF, 0xBB, 0xBF };
public static void Run()
{
// ReadAllBytes if the file encoding is UTF-8:
string fileName = "UniversitiesUtf8.json";
ReadOnlySpan<byte> jsonReadOnlySpan = File.ReadAllBytes(fileName);
// Read past the UTF-8 BOM bytes if a BOM exists.
if (jsonReadOnlySpan.StartsWith(Utf8Bom))
{
jsonReadOnlySpan = jsonReadOnlySpan.Slice(Utf8Bom.Length);
}
// Or read as UTF-16 and transcode to UTF-8 to convert to a ReadOnlySpan<byte>
//string fileName = "Universities.json";
//string jsonString = File.ReadAllText(fileName);
//ReadOnlySpan<byte> jsonReadOnlySpan = Encoding.UTF8.GetBytes(jsonString);
int count = 0;
int total = 0;
var reader = new Utf8JsonReader(jsonReadOnlySpan);
while (reader.Read())
{
JsonTokenType tokenType = reader.TokenType;
switch (tokenType)
{
case JsonTokenType.StartObject:
total++;
break;
case JsonTokenType.PropertyName:
if (reader.ValueTextEquals(s_nameUtf8))
{
// Assume valid JSON, known schema
reader.Read();
if (reader.GetString()!.EndsWith("University"))
{
count++;
}
}
break;
}
}
Console.WriteLine($"{count} out of {total} have names that end with 'University'");
}
}
}
' This code example doesn't apply to Visual Basic. For more information, go to the following URL:
' https://learn.microsoft.com/dotnet/standard/serialization/system-text-json-how-to#visual-basic-support
Yukarıdaki kod:
JSON'un bir nesne dizisi içerdiğini ve her nesnenin dize türünde bir "name" özelliği içerebileceğini varsayar.
"Üniversite" ile biten nesneleri ve "name" özellik değerlerini sayar.
Dosyanın UTF-16 olarak kodlanmış olduğunu varsayar ve dosyayı UTF-8'e çevirir.
UTF-8 olarak kodlanmış bir dosya, aşağıdaki kod kullanılarak doğrudan içinde
ReadOnlySpan<byte>okunabilir:ReadOnlySpan<byte> jsonReadOnlySpan = File.ReadAllBytes(fileName);Dosya bir UTF-8 bayt sipariş işareti (BOM) içeriyorsa, okuyucu metin beklediğinden baytları öğesine
Utf8JsonReadergeçirmeden önce dosyayı kaldırın. Aksi takdirde, BOM geçersiz JSON olarak kabul edilir ve okuyucu bir özel durum oluşturur.
Yukarıdaki kodun okuyabileceği bir JSON örneği aşağıda verilmiştır. Sonuçta elde edilen özet ileti "4'ün 2'sinde "Üniversite" ile biten adlar var" şeklindedir:
[
{
"web_pages": [ "https://contoso.edu/" ],
"alpha_two_code": "US",
"state-province": null,
"country": "United States",
"domains": [ "contoso.edu" ],
"name": "Contoso Community College"
},
{
"web_pages": [ "http://fabrikam.edu/" ],
"alpha_two_code": "US",
"state-province": null,
"country": "United States",
"domains": [ "fabrikam.edu" ],
"name": "Fabrikam Community College"
},
{
"web_pages": [ "http://www.contosouniversity.edu/" ],
"alpha_two_code": "US",
"state-province": null,
"country": "United States",
"domains": [ "contosouniversity.edu" ],
"name": "Contoso University"
},
{
"web_pages": [ "http://www.fabrikamuniversity.edu/" ],
"alpha_two_code": "US",
"state-province": null,
"country": "United States",
"domains": [ "fabrikamuniversity.edu" ],
"name": "Fabrikam University"
}
]
İpucu
Bu örneğin zaman uyumsuz sürümü için bkz . .NET örnekleri JSON projesi.
Kullanarak bir akıştan okuma Utf8JsonReader
Büyük bir dosyayı (örneğin, gigabayt veya daha büyük boyutlu) okurken, dosyanın tamamını aynı anda belleğe yüklemekten kaçınmak isteyebilirsiniz. Bu senaryo için bir FileStreamkullanabilirsiniz.
bir akıştan okumak için kullanırken Utf8JsonReader aşağıdaki kurallar geçerlidir:
- Okuyucunun ilerleme kaydedebilmesi için kısmi JSON yükünü içeren arabellek en az içindeki en büyük JSON belirteci kadar büyük olmalıdır.
- Arabellek en az JSON içindeki en büyük boşluk dizisi kadar büyük olmalıdır.
- Okuyucu, JSON yükünde bir sonrakini TokenType tamamen okuyana kadar okuduğu verileri izlemez. Bu nedenle, arabellekte kalan baytlar olduğunda, bunları okuyucuya yeniden geçirmeniz gerekir. Kaç bayt kaldığını belirlemek için kullanabilirsiniz BytesConsumed .
Aşağıdaki kodda bir akıştan nasıl okunduğu gösterilmektedir. Örnekte bir MemoryStreamgösterilir. Başlangıçta UTF-8 ürün reçetesi içermesi FileStream dışında benzer kod ile FileStreamçalışır. Bu durumda, kalan baytları öğesine geçirmeden önce bu üç baytı Utf8JsonReaderarabellekten ayırmanız gerekir. Aksi takdirde, ürün reçetesi JSON'un geçerli bir parçası olarak kabul edilmediğinden okuyucu bir özel durum oluşturur.
Örnek kod 4 KB arabellekle başlar ve boyutun tam bir JSON belirtecine sığacak kadar büyük olmadığını her bulduğunda arabellek boyutunu iki katına çıkartır. Bu, okuyucunun JSON yükünde ileriye doğru ilerlemesi için gereklidir. Kod parçacığında sağlanan JSON örneği, yalnızca 10 bayt gibi çok küçük bir başlangıç arabellek boyutu ayarladığınızda arabellek boyutu artışı tetikler. İlk arabellek boyutunu 10 olarak ayarlarsanız, Console.WriteLine deyimler arabellek boyutu artışlarının nedenini ve etkisini gösterir. 4 KB ilk arabellek boyutunda, örnek JSON'un tamamı için Console.WriteLineyapılan her çağrı tarafından gösterilir ve arabellek boyutunun hiçbir zaman artırılması gerekmez.
using System.Text;
using System.Text.Json;
namespace SystemTextJsonSamples
{
public class Utf8ReaderPartialRead
{
public static void Run()
{
var jsonString = @"{
""Date"": ""2019-08-01T00:00:00-07:00"",
""Temperature"": 25,
""TemperatureRanges"": {
""Cold"": { ""High"": 20, ""Low"": -10 },
""Hot"": { ""High"": 60, ""Low"": 20 }
},
""Summary"": ""Hot"",
}";
byte[] bytes = Encoding.UTF8.GetBytes(jsonString);
var stream = new MemoryStream(bytes);
var buffer = new byte[4096];
// Fill the buffer.
// For this snippet, we're assuming the stream is open and has data.
// If it might be closed or empty, check if the return value is 0.
stream.Read(buffer);
// We set isFinalBlock to false since we expect more data in a subsequent read from the stream.
var reader = new Utf8JsonReader(buffer, isFinalBlock: false, state: default);
Console.WriteLine($"String in buffer is: {Encoding.UTF8.GetString(buffer)}");
// Search for "Summary" property name
while (reader.TokenType != JsonTokenType.PropertyName || !reader.ValueTextEquals("Summary"))
{
if (!reader.Read())
{
// Not enough of the JSON is in the buffer to complete a read.
GetMoreBytesFromStream(stream, ref buffer, ref reader);
}
}
// Found the "Summary" property name.
Console.WriteLine($"String in buffer is: {Encoding.UTF8.GetString(buffer)}");
while (!reader.Read())
{
// Not enough of the JSON is in the buffer to complete a read.
GetMoreBytesFromStream(stream, ref buffer, ref reader);
}
// Display value of Summary property, that is, "Hot".
Console.WriteLine($"Got property value: {reader.GetString()}");
}
private static void GetMoreBytesFromStream(
MemoryStream stream, ref byte[] buffer, ref Utf8JsonReader reader)
{
int bytesRead;
if (reader.BytesConsumed < buffer.Length)
{
ReadOnlySpan<byte> leftover = buffer.AsSpan((int)reader.BytesConsumed);
if (leftover.Length == buffer.Length)
{
Array.Resize(ref buffer, buffer.Length * 2);
Console.WriteLine($"Increased buffer size to {buffer.Length}");
}
leftover.CopyTo(buffer);
bytesRead = stream.Read(buffer.AsSpan(leftover.Length));
}
else
{
bytesRead = stream.Read(buffer);
}
Console.WriteLine($"String in buffer is: {Encoding.UTF8.GetString(buffer)}");
reader = new Utf8JsonReader(buffer, isFinalBlock: bytesRead == 0, reader.CurrentState);
}
}
}
' This code example doesn't apply to Visual Basic. For more information, go to the following URL:
' https://learn.microsoft.com/dotnet/standard/serialization/system-text-json-how-to#visual-basic-support
Yukarıdaki örnek, arabelleğin ne kadar büyüyebileceğiyle ilgili bir sınır ayarlamaz. Belirteç boyutu çok büyükse kod bir OutOfMemoryException özel durumla başarısız olabilir. JSON boyutu yaklaşık 1 GB veya daha büyük bir belirteç içeriyorsa bu durum oluşabilir çünkü 1 GB boyutu ikiye katlama, arabelleğe sığamayacak kadar büyük bir int32 boyuta neden olur.
başvuru yapısı sınırlamaları
Utf8JsonReader türü bir ref structolduğundan, belirli sınırlamaları vardır. Örneğin, sınıfı veya yapısı dışında ref structbir alan olarak depolanamaz.
Yüksek performans elde etmek için, Utf8JsonReader girişin ReadOnlySpan<baytını >(kendisi bir ) önbelleğe alması gerektiğinden bir ref structolmalıdırref struct. Buna ek olarak, Utf8JsonReader durum barındırdığı için türü değişebilir. Bu nedenle, değere göre değil başvuruya göre geçirin. değerinin Utf8JsonReader geçirilmesi bir yapı kopyasına neden olur ve durum değişiklikleri çağıran tarafından görünmez.
Başvuru yapılarını kullanma hakkında daha fazla bilgi için bkz . Ayırmalardan kaçınma.
UTF-8 metnini okuma
kullanırken Utf8JsonReadermümkün olan en iyi performansı elde etmek için, UTF-16 dizeleri yerine zaten UTF-8 metni olarak kodlanmış JSON yüklerini okuyun. Kod örneği için bkz . Utf8JsonReader kullanarak verileri filtreleme.
Çok segmentli ReadOnlySequence ile okuma
JSON girişiniz bir ReadOnlySpan<bayt> ise, okuma döngüsü boyunca her JSON öğesine okuyucudaki özelliğinden ValueSpan erişilebilir. Ancak, girişiniz bir ReadOnlySequence<bayt> ise (bu, bir PipeReader'den okumanın sonucudur), bazı JSON öğeleri nesnenin birden çok kesimine ReadOnlySequence<byte> karışabilir. Bu öğelere bitişik bir bellek bloğundan erişilemez ValueSpan . Bunun yerine, giriş olarak çok segmentli ReadOnlySequence<byte> bir öğeniz olduğunda, geçerli JSON öğesine nasıl erişeceklerini öğrenmek için okuyucuda özelliğini yoklayın HasValueSequence . Önerilen desen aşağıdadır:
while (reader.Read())
{
switch (reader.TokenType)
{
// ...
ReadOnlySpan<byte> jsonElement = reader.HasValueSequence ?
reader.ValueSequence.ToArray() :
reader.ValueSpan;
// ...
}
}
Birden çok JSON belgesini okuma
.NET 9 ve sonraki sürümlerinde, tek bir arabellekten veya akıştan birden çok boşlukla ayrılmış JSON belgesini okuyabilirsiniz. Varsayılan olarak, Utf8JsonReader ilk üst düzey belgenin sonunda boşluk olmayan karakterler algılarsa bir özel durum oluşturur. Ancak, bayrağını JsonReaderOptions.AllowMultipleValues kullanarak bu davranışı yapılandırabilirsiniz.
JsonReaderOptions options = new() { AllowMultipleValues = true };
Utf8JsonReader reader = new("null {} 1 \r\n [1,2,3]"u8, options);
reader.Read();
Console.WriteLine(reader.TokenType); // Null
reader.Read();
Console.WriteLine(reader.TokenType); // StartObject
reader.Skip();
reader.Read();
Console.WriteLine(reader.TokenType); // Number
reader.Read();
Console.WriteLine(reader.TokenType); // StartArray
reader.Skip();
Console.WriteLine(reader.Read()); // False
AllowMultipleValues olarak ayarlandığındatrue, JSON'ı geçersiz JSON'un sonundaki verileri içeren yüklerden de okuyabilirsiniz.
JsonReaderOptions options = new() { AllowMultipleValues = true };
Utf8JsonReader reader = new("[1,2,3] <NotJson/>"u8, options);
reader.Read();
reader.Skip(); // Succeeds.
reader.Read(); // Throws JsonReaderException.
Birden çok üst düzey değerin akışını yapmak için veya DeserializeAsyncEnumerable<TValue>(Stream, JsonTypeInfo<TValue>, Boolean, CancellationToken) aşırı yüklemesini DeserializeAsyncEnumerable<TValue>(Stream, Boolean, JsonSerializerOptions, CancellationToken) kullanın. Varsayılan olarak, DeserializeAsyncEnumerable tek bir en üst düzey JSON dizisinde yer alan öğelerin akışını yapmaya çalışır. Birden çok üst düzey değerin topLevelValues akışını yapmak için parametresini geçirintrue.
ReadOnlySpan<byte> utf8Json = """[0] [0,1] [0,1,1] [0,1,1,2] [0,1,1,2,3]"""u8;
using var stream = new MemoryStream(utf8Json.ToArray());
var items = JsonSerializer.DeserializeAsyncEnumerable<int[]>(stream, topLevelValues: true);
await foreach (int[] item in items)
{
Console.WriteLine(item.Length);
}
/* This snippet produces the following output:
*
* 1
* 2
* 3
* 4
* 5
*/
Özellik adı aramaları
Özellik adlarını aramak için komutunu çağırarak SequenceEqualbayt bayt karşılaştırmaları yapmak için kullanmayınValueSpan. Bunun yerine çağrısı ValueTextEqualsyapın çünkü bu yöntem, JSON'da kaçış yapılan tüm karakterlerin çıkışını kaldırıyor. "name" adlı bir özelliğin nasıl arandığını gösteren bir örnek aşağıda verilmiştir:
private static readonly byte[] s_nameUtf8 = Encoding.UTF8.GetBytes("name");
while (reader.Read())
{
switch (reader.TokenType)
{
case JsonTokenType.StartObject:
total++;
break;
case JsonTokenType.PropertyName:
if (reader.ValueTextEquals(s_nameUtf8))
{
count++;
}
break;
}
}
Null değerleri null değer türlerine okuma
Yerleşik API'ler System.Text.Json yalnızca null atanamayan değer türleri döndürür. Örneğin, Utf8JsonReader.GetBoolean bir booldöndürür. JSON içinde bulursa Null bir özel durum oluşturur. Aşağıdaki örneklerde, biri null değer türü döndürerek, diğeri varsayılan değeri döndürerek olmak üzere null değerleri işlemenin iki yolu gösterilmektedir:
public bool? ReadAsNullableBoolean()
{
_reader.Read();
if (_reader.TokenType == JsonTokenType.Null)
{
return null;
}
if (_reader.TokenType != JsonTokenType.True && _reader.TokenType != JsonTokenType.False)
{
throw new JsonException();
}
return _reader.GetBoolean();
}
public bool ReadAsBoolean(bool defaultValue)
{
_reader.Read();
if (_reader.TokenType == JsonTokenType.Null)
{
return defaultValue;
}
if (_reader.TokenType != JsonTokenType.True && _reader.TokenType != JsonTokenType.False)
{
throw new JsonException();
}
return _reader.GetBoolean();
}
Belirtecin alt öğelerini atla
Utf8JsonReader.Skip() Geçerli JSON belirtecinin alt öğelerini atlamak için yöntemini kullanın. Belirteç türü ise JsonTokenType.PropertyName, okuyucu özellik değerine geçer. Aşağıdaki kod parçacığında, okuyucuyu bir özelliğin değerine taşımak için kullanma Utf8JsonReader.Skip() örneği gösterilmektedir.
var weatherForecast = new WeatherForecast
{
Date = DateTime.Parse("2019-08-01"),
TemperatureCelsius = 25,
Summary = "Hot"
};
byte[] jsonUtf8Bytes = JsonSerializer.SerializeToUtf8Bytes(weatherForecast);
var reader = new Utf8JsonReader(jsonUtf8Bytes);
int temp;
while (reader.Read())
{
switch (reader.TokenType)
{
case JsonTokenType.PropertyName:
{
if (reader.ValueTextEquals("TemperatureCelsius"))
{
reader.Skip();
temp = reader.GetInt32();
Console.WriteLine($"Temperature is {temp} degrees.");
}
continue;
}
default:
continue;
}
}
Kodu çözülen JSON dizelerini kullanma
.NET 7'den başlayarak, kodu çözülen bir JSON dizesi kullanmak yerine Utf8JsonReader.GetString() yöntemini kullanabilirsinizUtf8JsonReader.CopyString. sürümünden farklı olarak GetString(), her zaman yeni bir dize ayırır, CopyString boş dizeyi sahip olduğunuz bir arabelleğe kopyalamanıza olanak tanır. Aşağıdaki kod parçacığında kullanarak CopyStringUTF-16 dizesi kullanma örneği gösterilmektedir.
var reader = new Utf8JsonReader( /* jsonReadOnlySpan */ );
int valueLength = reader.HasValueSequence
? checked((int)reader.ValueSequence.Length)
: reader.ValueSpan.Length;
char[] buffer = ArrayPool<char>.Shared.Rent(valueLength);
int charsRead = reader.CopyString(buffer);
ReadOnlySpan<char> source = buffer.AsSpan(0, charsRead);
// Handle the unescaped JSON string.
ParseUnescapedString(source);
ArrayPool<char>.Shared.Return(buffer, clearArray: true);
void ParseUnescapedString(ReadOnlySpan<char> source)
{
// ...
}
İlgili API'ler
Bir örnekten özel bir türü seri durumdan
Utf8JsonReaderçıkarmak için veya JsonSerializer.Deserialize<TValue>(Utf8JsonReader, JsonTypeInfo<TValue>)çağrısında JsonSerializer.Deserialize<TValue>(Utf8JsonReader, JsonSerializerOptions) bulunur. Örnek için bkz . UTF-8'den seri durumdan çıkarma.JsonNode ve ondan türetilen sınıflar, değiştirilebilir bir DOM oluşturma olanağı sağlar. çağrısı JsonNode.Parse(Utf8JsonReader, Nullable<JsonNodeOptions>)yaparak bir
Utf8JsonReaderörneği'neJsonNodedönüştürebilirsiniz. Aşağıdaki kod parçacığı bir örnek gösterir.using System.Text.Json; using System.Text.Json.Nodes; namespace Utf8ReaderToJsonNode { public class WeatherForecast { public DateTimeOffset Date { get; set; } public int TemperatureCelsius { get; set; } public string? Summary { get; set; } } public class Program { public static void Main() { var weatherForecast = new WeatherForecast { Date = DateTime.Parse("2019-08-01"), TemperatureCelsius = 25, Summary = "Hot" }; byte[] jsonUtf8Bytes = JsonSerializer.SerializeToUtf8Bytes(weatherForecast); var utf8Reader = new Utf8JsonReader(jsonUtf8Bytes); JsonNode? node = JsonNode.Parse(ref utf8Reader); Console.WriteLine(node); } } }JsonDocument kullanarak
Utf8JsonReadersalt okunur bir DOM oluşturma olanağı sağlar. Bir örnekten JsonDocument.ParseValue(Utf8JsonReader) ayrıştırmakJsonDocumentUtf8JsonReaderiçin yöntemini çağırın. Yükü oluşturan JSON öğelerine türü aracılığıyla JsonElement erişebilirsiniz. kullanan JsonDocument.ParseValue(Utf8JsonReader)kodlar için bkz. RoundtripDataTable.cs ve deserialize inserialize inferred types to object properties içindeki kod parçacığı.Ayrıca, çağırarak JsonElement.ParseValue(Utf8JsonReader)belirli bir JsonElementJSON değerini temsil eden bir örneği olarak ayrıştırabilirsiniz
Utf8JsonReader.