1

I am getting a Gziped JSON which I check for a specific start string and if it's correct I deserialize into my object:

await using var decompressionStream = new GZipStream(externalStream, CompressionMode.Decompress);

var streamReader = new StreamReader(decompressionStream);
string eventString = streamReader.ReadToEnd();

if (!eventString.StartsWith("SomeString"))
{
    // Drop it because it can't be deserialized
    return;
}

MyObject item = Utf8Json.JsonSerializer.Deserialize<MyObject>(Encoding.UTF8.GetBytes(eventString));

This approach works but it seems to be wasteful to turn the stream into a string and back into an bytes array when Utf8Json can deserialize directly from a stream.

Because 3/4 of incoming streams contain data that is of a different type and can't be deserialized I don't want to put a try/catch block around it because that many exceptions would be too expensive.

Is there a way to peek into the first ~16 chars without consuming them?

ThisWillDoIt
  • 380
  • 6
  • 24
  • [Read_Char[], Int32, Int32_](https://learn.microsoft.com/en-us/dotnet/api/system.io.streamreader.read?view=netframework-4.8#System_IO_StreamReader_Read_System_Char___System_Int32_System_Int32_) and [peek](https://learn.microsoft.com/en-us/dotnet/api/system.io.streamreader.peek?view=netframework-4.8) – xdtTransform Dec 11 '19 at 10:05
  • Does this answer your question? [Stream reader.Read number of character](https://stackoverflow.com/questions/31173412/stream-reader-read-number-of-character) – xdtTransform Dec 11 '19 at 10:06
  • That read command consumes the read data so after checking the first characters I can't use that stream to deserialize because it's missing the first n characters. Edit: Peek is only possible for 1 char and unfortunately I need some more to determine the type. – ThisWillDoIt Dec 11 '19 at 10:09
  • Peek won't consume data but it won't go as far. Perhaps the first char is enought to reduce the number of throw by a reasonable margin. Perhaps you may want to store that first n char either in a variable or a wrapper class that inherit from StreamReader. But from my understanding you are going to read those 16 char anyway – xdtTransform Dec 11 '19 at 14:09
  • You could read the first N bytes from the stream and compare them with the byte representation of `"SomeString"`. Assuming they match, put the `N` bytes into a `MemoryStream` and use `ConcatenatedStream` from [this answer](https://stackoverflow.com/a/3879231/3744182) to [How do I concatenate two System.Io.Stream instances into one?](https://stackoverflow.com/q/3879152/3744182) to combine it with the remainder of the `GZipStream`. – dbc Dec 11 '19 at 18:07
  • (Incidentally, how can a valid JSON stream start with `"SomeString"`? Maybe you have some [XY problem](https://meta.stackexchange.com/q/66377) where you need `JsonSerializer` to throw an exception on missing data, which is not yet implemented?) – dbc Dec 11 '19 at 18:08
  • Demo of using `ConcatenatedStream` here: https://dotnetfiddle.net/LrfodV. Note that the linked implementation of `ConcatenatedStream` doesn't attempt to do async reading, but the only overloads that `JsonSerializer` has for deserializing from a stream are [async](https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonserializer.deserializeasync?view=netcore-3.0#System_Text_Json_JsonSerializer_DeserializeAsync_System_IO_Stream_System_Type_System_Text_Json_JsonSerializerOptions_System_Threading_CancellationToken_). So there might be an issue there. – dbc Dec 11 '19 at 20:09
  • Maybe adapting `Utf8JsonStreamReader` from [this answer](https://stackoverflow.com/a/55429664) to [Parsing a JSON file with .NET core 3.0/System.text.Json](https://stackoverflow.com/q/54983533) would work better. – dbc Dec 11 '19 at 20:10

0 Answers0