3

i am Serializing a simple Object into JSON (this works fine) but i am having trouble deserializing that file and converting it into an Object.

This is the error: System.Text.Json.JsonException: ''S' is an invalid start of a value. Path: $ | LineNumber: 0 | BytePositionInLine: 0.'

This is the code:

public static T DeserializeJson<T>(string path) where T : new()
    {
        var options = new JsonSerializerOptions
        {
            WriteIndented = true,
            IncludeFields = true
        };

        using (Stream stream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite))
        {
            if (File.Exists(path) && stream.Length > 0)
            {
                T obj = JsonSerializer.Deserialize<T>(stream.ToString(), options);
                return obj;
            }
            else
            {
                T obj = new T();
                JsonSerializer.SerializeAsync(stream, obj, options);
                return obj;
            }
        }
    }

And this is the class i am trying to serialize:

class Settings
{
    [JsonInclude]
    public int ScreenWidth { get; set; } = 1280;
    [JsonInclude]
    public int ScreenHeight { get; set; } = 800;

    [JsonInclude] public bool IsFullScreen = false;
}

I haven't really worked with JSON before so i appologise if this is a dumb question.

Edit 1

So i was passing the stream as a String in the JsonSerializer.Deserialize<T> which was causing my issues, but how do i keep the "OpenOrCreate" functionality? (the post i've been linked to is reading the file using StreamReader but i may not have the file)

Cuvin Stefan
  • 43
  • 1
  • 1
  • 6
  • 1
    Uh, `stream.ToString()` will return `"System.IO.Stream"`, it won't convert the contents of the stream to a string. – ProgrammingLlama Feb 20 '21 at 15:58
  • This is not the same question as the one referred to in the closed notice. Can you post the first line of your data file please? – stemixrf Feb 20 '21 at 16:02
  • @john ok.. i now believe i need glasses.. that might have been added by VS when `stream` didn't fit in that function. My new question is: How do i keep my "OpenOrCreate" functionality if i can't pass the `stream` to the Deserialization method? – Cuvin Stefan Feb 20 '21 at 16:07

2 Answers2

3

The issue is that you're calling stream.ToString() which will not convert the contents of the stream to a string. It will simply return "System.IO.Stream" (this exact text).

Since you want to maintain the OpenOrCreate functionality, I suggest constructing a StreamReader around your stream object, and then use that to read the contents of the file:

using (Stream stream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite))
{
    if (File.Exists(path) && stream.Length > 0)
    {
        // read the entire file using a `StreamReader`
        string fileContents;
        using (StreamReader reader = new StreamReader(stream))
        {
            fileContents = reader.ReadToEnd();
        }
        // deserialize the contents of the file
        T obj = JsonSerializer.Deserialize<T>(fileContents, options);
        return obj;
    }
    else
    {
        T obj = new T();
        JsonSerializer.SerializeAsync(stream, obj, options);
        return obj;
    }
}
ProgrammingLlama
  • 36,677
  • 7
  • 67
  • 86
  • 1
    I realize it's from the OP but...@Exodus. calling `SerializeAsync` without `await`ing it isn't going to work as expected. The function should be a `Task` returning `async` method and then use `DeserializeAsync` which takes a `Stream` directly like it's serializing counterpart. Alternatively, use `Serialize` to get a `string` and then use a `StreamWriter` to write **synchronously** to the file – pinkfloydx33 Feb 20 '21 at 18:23
0

stream.ToString() is not how you pass a Stream object.

Only DeserializeAsync accepts a Stream as input. And you are already using SerializeAsync but incorrectly. So let's convert the whole function to async/await:

public static async Task<T> DeserializeJson<T>(string path) where T : new()
    {
        var options = new JsonSerializerOptions
        {
            WriteIndented = true,
            IncludeFields = true
        };

        using (Stream stream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite))
        {
            if (File.Exists(path) && stream.Length > 0)
            {
                T obj = await JsonSerializer.DeserializeAsync<T>(stream, options);
                return obj;
            }
            else
            {
                T obj = new T();
                await JsonSerializer.SerializeAsync(stream, obj, options);
                return obj;
            }
        }
    }
Charlieface
  • 52,284
  • 6
  • 19
  • 43
  • ah, i see. For this perticular function i only wanted to write Async (deserialization has to be in Sync) but it will definetly come in handy later! Thank you for the input! – Cuvin Stefan Feb 20 '21 at 21:06