StackOverflowException on JsonConvert.DeserializeObject
本文关键字:DeserializeObject JsonConvert on StackOverflowException | 更新日期: 2023-09-27 18:12:27
我正在编写一个包含ASP的解决方案。. NET Web API(。. NET 4.6.2)即后端,Web API客户端实现PCL即中间件和Xamarin。窗体项目即前端。在最近对我的web api进行更改后,当我试图在我的前端反序列化JSON响应时,我现在总是得到StackOverflowException。具体行为:
result_ = JsonConvert.DeserializeObject<ObservableCollection<Employee>>(Encoding.UTF8.GetString(responseData_, 0, responseData_.Length));
当我在这里调试时,我看到程序在两行之间跳转,直到发生溢出:
EmployeesManager.cs(在中间件中)
private Image _image = new Image();
ImagesManager.cs(在中间件)
private Employee _employee = new Employee();
下面是更多的代码:
模型(在Web API):
public class Employee
{
public int Id { get; set; }
// OMITTED PROPS
public int? ImageId { get; set; }
public Image Image { get; set; }
public ICollection<Device> Devices { get; set; }
public int? TeamId { get; set; }
public Team Team { get; set; }
}
public class Image
{
[Key]
public int Id { get; set; }
[Required]
public byte[] Data { get; set; }
public int EmployeeId { get; set; }
public Employee Employee { get; set; }
}
客户端实现(中间件)中的模型。它们是用Nswag:
生成的public partial class Employee : INotifyPropertyChanged
{
private int _id;
private int? _imageId;
private Image _image = new Image(); // THIS LINE IS PART OF THE OVERFLOW
private ObservableCollection<Device> _devices;
private int? _teamId;
private Team _team = new Team();
// OMITTED PROPS
[JsonProperty("image", Required = Required.Default, NullValueHandling = NullValueHandling.Ignore)]
public Image Image
{
get { return _image; }
set
{
if (_image != value)
{
_image = value;
RaisePropertyChanged();
}
}
}
public partial class Image : INotifyPropertyChanged
{
private int _id;
private int _employeeId;
private Employee _employee = new Employee(); // THIS LINE IS PART OF THE STACK OVERFLOW
private byte[] _data;
// OMITTED PROPS
[JsonProperty("employee", Required = Required.Default, NullValueHandling = NullValueHandling.Ignore)]
public Employee Employee
{
get { return _employee; }
set
{
if (_employee != value)
{
_employee = value;
RaisePropertyChanged();
}
}
}
我通过Xamarin使用Web API客户端实现。形式的项目。所有平台上的行为都是一样的。不过,只有iOS和UWP能够识别Stack Overflow。在Android上,当我从Web API读取数据时,应用程序只是关闭而没有异常。
如果有人想看到更多的代码,我可以准备一个小包包含所要求的代码。把它们都贴在这里会完全破坏可读性。
我使用Newtonsoft Json。. NET,实体框架6,NSwag 6, Xamarin。v2.3.2.127形式。
我以前也遇到过这种情况;这是由于物体之间的循环引用。你有一个雇员引用图像和图像引用雇员。
尝试在图像类Image的Employee属性上方放置一个[JsonIgnore]
。
我遵循了Oxidda、David和ejoshua的答案。
下面是完整文档的完整解决方案:
我试着把JsonIgnore放在中间件(Web API客户端PCL)内部图像类的Employee属性上。奇怪的是,这并没有解决问题。我仍然有堆栈溢出与私有变量背后的属性。现在我把JsonIgnore放在Web API(后端)中Image类的Employee导航属性上,也放在Device类的Employee导航属性上。然后,我从API客户端(中间件)中完全删除了导航属性(图像类中的Employee和设备类中的Employee),因为这些属性的JSON现在将永远不会被接收,因为API已经忽略了这些属性。现在这个错误已经消失了,最重要的是,我的请求和响应速度得到了显著提升。看起来,尽管Web API(后端)运行良好,关系也没有问题,但可选模型上的那些导航属性带来了大量的开销。类非常小,数据库的表几乎是空的,但影响似乎是巨大的。
TL;DR:消除了源处循环引用的可能性。将更改镜像到客户端。问题解决了,速度也大大提高了。
如果有人对我的解决方案的完整设计感兴趣,这里有一个小总结。我非常喜欢它。
- 创建ASP。. NET Web API(。. NET 4.6.2)项目与实体框架6。添加带有关系的模型,添加DbContext。脚手架式异步控制器。Web API完成了。注意,在使用JSon实体框架时不应该使用延迟加载。相反,我在控制器中使用即时加载。
- 创建与Xamarin PCL使用相同配置文件的PCL。因此,它与Xamarin解决方案兼容,也与所有其他标准。net解决方案兼容。
- 基于Web API,使用NSwag生成中间件API。你只需将你的API.dll加载到程序中,选择你的设置,然后你就会收到一个完整的pcl兼容的c# Web API客户端实现。API是相当高级和异步的,所以你可以在任何。net前端轻松地使用你的API。
- 添加您选择的前端解决方案。通过客户机API轻松地使用数据。
基本上你只需要在Web API中编写一些属性(+配置JSon序列化器和DbContext),整个后端和中间件的其余部分就会生成。我喜欢它。