Skip to main content
 首页 » 编程设计

c#之在 Xamarin.iOS 中使用 EKEvents 将列表序列化为 JSON

2024年04月30日36shanyou

当我尝试序列化一个存储 EKEvent 的简单列表时。我收到此错误:

Newtonsoft.Json.JsonSerializationException: Self referencing loop detected for property 'Self' with type 'Foundation.NSDate'. Path '[0].EndDate'. at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CheckForCircularReference (Newtonsoft.Json.JsonWriter writer, System.Object value, Newtonsoft.Json.Serialization.JsonProperty property, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerProperty) [0x00105] in :0 at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter. CalculatePropertyValues (Newtonsoft.Json.JsonWriter writer, System.Object value, Newtonsoft.Json.Serialization.JsonContainerContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonProperty property, Newtonsoft.Json.Serialization.JsonContract& memberContract, System.Object& memberValue) [0x000c7] in :0 at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject (Newtonsoft.Json.JsonWriter writer, System.Object value, Newtonsoft.Json.Serialization.JsonObjectContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract collectionContract, Newtonsoft.Json.Serialization.JsonProperty containerProperty) [0x0003c] in :0

当我尝试使用 JsonConvert.SerializeObject 方法时会发生这种情况。 序列化 EKEvent 列表的任何解决方法?

编辑

使用 JsonSerializerSettings 有效!

但是,当我尝试反序列化对象时,我遇到了另一个问题:

Newtonsoft.Json.JsonSerializationException:无法找到用于类型 EventKit.EKEvent 的构造函数。 @ 一个类应该有一个默认的构造函数, 一个带参数的构造函数或标有 JsonConstructor 属性的构造函数。 路径“[0].ClassHandle”,第 1 行,位置 16。 在 Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateNewObject (Newtonsoft.Json.JsonReader reader, Newtonsoft.Json.Serialization.JsonObjectContract objectContract, Newtonsoft.Json.Serialization.Json属性容器成员, Newtonsoft.Json.Serialization.JsonProperty容器属性, System.String id, System.Boolean& createdFromNonDefaultCreator) [0x000d6] in :0 在 Newtonsoft.Json.Serialization.JsonSerializerInternalReader。 CreateObject (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty 成员, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, System.Object existingValue) [0x0013b] in :0 在 Newtonsoft.Json.Serialization.JsonSerializerInternalReader。 CreateValueInternal (Newtonsoft.Json.JsonReader reader, System.Type objectType , Newtonsoft.Json.Serialization.JsonContract 合约, Newtonsoft.Json.Serialization.JsonProperty 成员, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, System.Object existingValue) [0x0006d] in :0 在 Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateList(IList 列表, Newtonsoft.Json.JsonReader 阅读器,Newtonsoft.Json.Serialization.JsonArrayContract 契约(Contract), Newtonsoft.Json.Serialization.JsonProperty containerProperty, System.String id) [0x000cb] in :0

请您参考如下方法:

Giorgi 的回答回答了您关于如何序列化数据的问题的第一部分,您似乎已经解决了这个问题。但是,现在您再次反序列化它时遇到问题。

查看您在开篇帖子中提供的堆栈跟踪,它说:

Unable to find a constructor to use for type EventKit.EKEvent. @ A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute

这特别说明了这个错误。现在,查看 EventKit EKEvent API reference ,我们发现以下内容:

  1. 所有的构造函数都被标记为protected
  2. 没有不带参数的构造函数

这意味着,当 DeserializeObject 方法试图创建 EKEvent 的实例时,它没有任何方法可以这样做。它不知道要提供什么参数。

EKEvent 类还存在其他问题。即使它有没有参数的公共(public)构造函数。它的所有属性都被标记为read-only。这意味着当再次反序列化序列化程序时,无法使用序列化事件填充属性。

因此,您有以下两种选择:

  1. 创建一个包装 EKEvent 或模仿 EKEvent 的类并对其进行反序列化
  2. 使用提供的 EKEventStore 来保存 EKEvents。 As the API docs describe : “在 EventKit 中执行任何操作都需要 EventStore。它可以被认为是所有 EventKit 数据的持久存储或数据库引擎。”

开头的帖子没有描述为什么要序列化和反序列化该对象的原因。但是,如果您想将它与某些 API 进行通信,我建议您选择选项 1。因为它不是特定于平台的,您可以这样做,以便您只在应用程序和 API 之间通信相关数据,从而节省宝贵的带宽。