Newtonsoft.JSON 在反序列化数组中被双引号包围的对象时窒息

Posted

技术标签:

【中文标题】Newtonsoft.JSON 在反序列化数组中被双引号包围的对象时窒息【英文标题】:Newtonsoft.JSON chokes on deserializing object that's surrounded by double quotes in an array 【发布时间】:2021-12-16 07:29:42 【问题描述】:

我正在使用 Newtonsoft.JSON 序列化 List<UserDataJson>,然后写入文件。这是课程:

private class UserDataJson

    public UserDataJson()  

    public UserDataJson(string path)
    
        Location = path;
        Opacity = 1;
    

    public UserDataJson(IUserData userData)
    
        Location = userData.Location;
        Opacity = userData.Opacity;
    

    public string Location  get; set; 

    public double Opacity  get; set; 

序列化写入的代码:

private static readonly string _userDataFile = Path.Combine(_programDataFolder, "userdata.json");

...

public void SaveData(IReadOnlyCollection<IUserData> userData)

     File.WriteAllText(_userDataFile, JsonConvert.SerializeObject(userData.Select(Serialize).ToList(), Formatting.Indented));


private static string Serialize(IUserData userData) => JsonConvert.SerializeObject(new UserDataJson(userData));

使用一个元素,这会生成一个 _userDataJson 文件,如下所示:

[
  "\"Location\":\"C:\\\\Users\\\\me\\\\Documents\\\\test.txt\",\"Opacity\":1.0"
]

但是,当我尝试反序列化时,我得到一个 JsonSerializationException

反序列化:

JsonConvert.DeserializeObject<List<UserDataJson>>(File.ReadAllText(_userDataFile).Replace("\\\\", "\\");

例外:

"Error converting value \"\"Location\":\"C:\\Users\\me\\Documents\\test.txt\",\"Opacity\":1.0\" to type 'Company.App.Wpf.MainWindow.UserDataService+UserDataJson'. Path '[0]', line 2, position 73."

内部异常:

"Could not cast or convert from System.String to Company.App.Wpf.MainWindow.UserDataService+UserDataJson."

但是,当我从双引号中删除转义字符 \ 并从整个对象周围删除双引号时,它可以很好地反序列化。

[
  "Location":"C:\\\\Users\\\\me\\\\Documents\\\\test.txt","Opacity":1.0
]

我应该在序列化或反序列化阶段应用任何配置以生成可以反序列化为UserDataJson 列表的字符串吗?

【问题讨论】:

那不是一个对象,那是一个普通的旧字符串。产生这个的代码中有一个错误,而不是在 JSON.NET 中。在 JSON 中用双引号括起来的东西是一个字符串,不管它包含什么 想象你拿一个对象,并将它序列化为 JSON。你得到一个字符串,对吧?因此,如果您将该字符串添加到列表并序列化该列表,您会得到类似于上面的 JSON 的内容。这是因为您的Serialize 代码的这一部分:.Select(Serialize)。这一步似乎根本不需要。 谢谢@Llama,你是对的。如果你这样回答问题,我会接受。 【参考方案1】:

假设您获取一个对象,并将其序列化为 JSON。你得到一个字符串,对吧?因此,如果您将该字符串添加到列表并序列化该列表,您会得到类似于上面的 JSON 的内容。

这是因为您的序列化代码的这一部分:.Select(Serialize)。这一步似乎根本不需要。

去掉那个,我们得到这个:

public void SaveData(IReadOnlyCollection<IUserData> userData)

     File.WriteAllText(_userDataFile, JsonConvert.SerializeObject(userData, Formatting.Indented));


private static string Serialize(IUserData userData) => JsonConvert.SerializeObject(new UserDataJson(userData));

这段代码现在应该可以反序列化生成的 JSON:

var result = JsonConvert.DeserializeObject<List<UserDataJson>>(File.ReadAllText(_userDataFile));

Try it online

【讨论】:

作为注释,我必须将IReadOnlyCollection&lt;IUserData&gt; 更改为IReadOnlyList&lt;IUserData&gt; 才能将userData 直接传递到SerializeObject

以上是关于Newtonsoft.JSON 在反序列化数组中被双引号包围的对象时窒息的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Newtonsoft.Json 正确反序列化数组中的嵌套对象? [复制]

Asp Core 3.1 API JsonIgnore (not) 在反序列化中被忽略

c#开发中使用Newtonsoft.Json反序列化数组求解?

newtonsoft.json 反序列化

一:Newtonsoft.Json 支持序列化与反序列化的.net 对象类型;

Newtonsoft.Json Json.Net02.02序列化指引Serialization Guide