【问题标题】:JSON Deserialization Exception (''S' is an invalid start of a value)JSON 反序列化异常(''S' 是值的无效开始)
【发布时间】:2021-02-20 15:52:36
【问题描述】:

我正在将一个简单的对象序列化为 JSON(这工作正常),但我无法反序列化该文件并将其转换为对象。

这是错误:System.Text.Json.JsonException: ''S' is an invalid start of a value. Path: $ | LineNumber: 0 | BytePositionInLine: 0.'

这是代码:

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;
            }
        }
    }

这是我要序列化的类:

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

    [JsonInclude] public bool IsFullScreen = false;
}

我之前没有真正使用过 JSON,所以如果这是一个愚蠢的问题,我很抱歉。

编辑 1

所以我在JsonSerializer.Deserialize&lt;T&gt; 中将stream 作为字符串传递,这导致了我的问题,但我如何保留“OpenOrCreate”功能? (我链接到的帖子是使用 StreamReader 读取文件,但我可能没有文件)

【问题讨论】:

  • 呃,stream.ToString() 将返回"System.IO.Stream",它不会将流的内容转换为字符串。
  • 这与封闭通知中提到的问题不同。你能把你的数据文件的第一行贴出来吗?
  • @john 好的.. 我现在相信我需要眼镜.. 当stream 不适合该功能时,VS 可能会添加它。我的新问题是:如果我不能将 stream 传递给反序列化方法,我该如何保留“OpenOrCreate”功能?

标签: c# json serialization


【解决方案1】:

问题是您正在调用stream.ToString(),它不会将流的内容转换为字符串。它只会返回"System.IO.Stream"(这个确切的文本)。

由于您想维护OpenOrCreate 功能,我建议在您的stream 对象周围构造一个StreamReader,然后使用它来读取文件的内容:

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;
    }
}

【讨论】:

  • 感谢您的时间和耐心
  • 我意识到它来自 OP 但是...@Exodus。在没有awaiting 的情况下调用SerializeAsync 它不会按预期工作。该函数应该是一个Task&lt;T&gt; 返回async 方法,然后使用DeserializeAsync,它直接采用Stream,就像它的序列化对应物一样。或者,使用Serialize 获取string,然后使用StreamWriter同步写入文件
【解决方案2】:

stream.ToString() 不是传递Stream 对象的方式。

只有DeserializeAsync 接受Stream 作为输入。而且您已经在使用 SerializeAsync 但不正确。所以让我们把整个函数转换成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;
            }
        }
    }

【讨论】:

  • 啊,我明白了。对于这个特殊的功能,我只想编写异步(反序列化必须同步),但它以后肯定会派上用场!感谢您的意见!
猜你喜欢
  • 1970-01-01
  • 2023-01-09
  • 1970-01-01
  • 1970-01-01
  • 2016-10-08
  • 2019-08-22
  • 1970-01-01
  • 1970-01-01
  • 2023-03-23
相关资源
最近更新 更多