malloc: *** 释放对象指针的错误在 JSON 反序列化期间未分配
malloc: *** error for object pointer being freed was not allocated during JSON deserializing
我正在尝试使用 Visual Studio 中的 C# 将 JSON 字符串反序列化为列表,用于 Xamarin.Mac 项目的 Mac。
我可以毫无问题地进行序列化:
using (StreamWriter file = File.CreateText(filename))
{
var serializer = new JsonSerializer()
{
Formatting = Formatting.Indented,
TypeNameHandling = TypeNameHandling.Auto,
TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};
await Task.Run(() => serializer.Serialize(file, contactroot));
}
但是当我尝试使用此反序列化时出现上述错误:
var contacts = JsonConvert.DeserializeObject<ContactRoot>(json);
联系人根class:
public class ContactRoot
{
public List<Contact> contacts { get; set; }
}
Contact class 继承了 NSObject class 以绑定到 Mac 应用程序中的控件。我也会包括它,但有超过 70 个具有多个属性的属性。这是 class 中的几个片段:
[Register("Contact")]
public class Contact : NSObject
...还有很多这样的属性:
public DateTime? updated_at { get; set; }
[Export("updatedString"), Display(Name = "Updated Date"), Category("Misc"), Description("3"), DefaultValue(TypeOfValue.DateTime)]
public string updatedString
{
get {
if (this.updated_at.HasValue){
return this.updated_at.Value.ToString();
} else{
return string.Empty;
}
}
set
{
WillChangeValue("updatedString");
try
{
if (!String.IsNullOrEmpty(value)) this.updated_at = Convert.ToDateTime(value);
}
catch (Exception)
{
}
DidChangeValue("updatedString");
}
}
我正在使用 DateTime?因为 API 源需要这样做,并且由于 Xamarin 数据绑定似乎不处理 int 或 DateTime 的空值,所以我使用字符串 属性 进行转换。使用该应用程序时效果很好,但不确定反序列化时是否会导致错误。
我是 Mac 的开发新手,所以我可能错过了一些东西。
编辑
哇,感谢您的快速回复!在看到任何评论之前,我尝试了一个更简单的 class 但得到了相同的结果:
[Register("SimpleContact")]
public class SimpleContact : NSObject
{
int _id = 0;
string _first = String.Empty;
string _last = String.Empty;
[Export("id")]
public int id {
get { return _id; }
set {
WillChangeValue("id");
_id = value;
DidChangeValue("id");
}
}
[Export("first")]
public string first {
get { return _first; }
set {
WillChangeValue("first");
_first = value;
DidChangeValue("first");
}
}
[Export("last")]
public string last
{
get { return _last; }
set
{
WillChangeValue("last");
_last = value;
DidChangeValue("last");
}
}
[Export("fullname")]
public string fullname
{
get { return this.first + " " + this.last; }
}
public SimpleContact()
{}
public SimpleContact(int id, string first, string last)
{
this.id = id;
this.first = first;
this.last = last;
}
public override string ToString()
{
return this.fullname;
}
}
接下来我将尝试 POCO 方法并 post 结果。非常感谢!
编辑
这是异常的实质内容。我认为其余的异常没有任何用处:
Crashed Thread: 0 tid_307 Dispatch queue: com.apple.main-thread
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
External Modification Warnings:
Debugger attached to process.
Application Specific Information:
abort() called
WealthBox Addon(6016,0x11d9ae5c0) malloc: *** error for object 0x7fff7f110880: pointer being freed was not allocated
Thread 0 Crashed:: tid_307 Dispatch queue: com.apple.main-thread
0 libsystem_kernel.dylib 0x00007fff7f08223e __pthread_kill + 10
1 libsystem_pthread.dylib 0x00007fff7f138c1c pthread_kill + 285
2 libsystem_c.dylib 0x00007fff7efeb268 __abort + 144
3 libsystem_c.dylib 0x00007fff7efeb1d8 abort + 142
4 libsystem_malloc.dylib 0x00007fff7f0fa6e2 malloc_vreport + 545
5 libsystem_malloc.dylib 0x00007fff7f0fa4a3 malloc_report + 152
6 libsystem_malloc.dylib 0x00007fff7f0f2aff malloc_set_zone_name + 47
7 ??? 0x00000001162ad420 0 + 4666872864
8 ??? 0x000000011616c6a3 0 + 4665558691
9 ??? 0x0000000116275739 0 + 4666644281
10 ??? 0x0000000116265443 0 + 4666577987
11 ??? 0x000000011625cbd3 0 + 4666543059
12 ??? 0x000000011618480b 0 + 4665657355
13 ??? 0x00000001162755bb 0 + 4666643899
14 ??? 0x0000000116265443 0 + 4666577987
15 ??? 0x000000011625cbd3 0 + 4666543059
16 ??? 0x000000011618480b 0 + 4665657355
17 ??? 0x000000011618885b 0 + 4665673819
18 ??? 0x0000000116185c7b 0 + 4665662587
19 ??? 0x000000011618486b 0 + 4665657451
20 ??? 0x000000011609f303 0 + 4664718083
21 ??? 0x000000011609cc03 0 + 4664708099
22 ??? 0x000000011609c84e 0 + 4664707150
23 ??? 0x0000000116095663 0 + 4664677987
24 ??? 0x0000000116087a33 0 + 4664621619
25 Browning-Financial.WealthBox-Addon 0x000000010edc5593 mono_jit_runtime_invoke + 1443 (mini-runtime.c:2806)
26 Browning-Financial.WealthBox-Addon 0x000000010eeaee4f mono_runtime_invoke_checked + 127 (object.c:2887)
27 Browning-Financial.WealthBox-Addon 0x000000010eeb36fc mono_runtime_invoke + 76 (object.c:2941)
28 Browning-Financial.WealthBox-Addon 0x000000010ecadaa2 xamarin_invoke_trampoline + 6018 (trampolines-invoke.m:456)
29 Browning-Financial.WealthBox-Addon 0x000000010ecaec7d xamarin_arch_trampoline + 189 (trampolines-x86_64.m:547)
30 Browning-Financial.WealthBox-Addon 0x000000010ecb00b1 xamarin_x86_64_common_trampoline + 110
31 com.apple.AppKit 0x00007fff4f3deb5a -[NSViewController _sendViewDidLoad] + 97
32 com.apple.AppKit 0x00007fff4f3dbeb5 _noteLoadCompletionForObject + 645
33 com.apple.AppKit 0x00007fff4f24d99f -[NSIBObjectData nibInstantiateWithOwner:options:topLevelObjects:] + 2086
34 com.apple.AppKit 0x00007fff4f3e3114 -[NSNib _instantiateNibWithExternalNameTable:options:] + 679
35 com.apple.AppKit 0x00007fff4f3e2d70 -[NSNib _instantiateWithOwner:options:topLevelObjects:] + 136
36 com.apple.AppKit 0x00007fff4f3e1fdc -[NSViewController loadView] + 343
37 com.apple.AppKit 0x00007fff4f3ddb60 -[NSViewController _loadViewIfRequired] + 75
38 com.apple.AppKit 0x00007fff4f3ddacb -[NSViewController view] + 30
39 com.apple.AppKit 0x00007fff4f4d01da -[NSWindow _contentViewControllerChanged] + 109
40 com.apple.Foundation 0x00007fff540c7450 -[NSObject(NSKeyValueCoding) setValue:forKey:] + 331
41 com.apple.AppKit 0x00007fff4f3da987 -[NSWindow setValue:forKey:] + 111
42 com.apple.AppKit 0x00007fff4f32ce0c -[NSIBUserDefinedRuntimeAttributesConnector establishConnection] + 637
43 com.apple.AppKit 0x00007fff4f24d739 -[NSIBObjectData nibInstantiateWithOwner:options:topLevelObjects:] + 1472
44 com.apple.AppKit 0x00007fff4f3e3114 -[NSNib _instantiateNibWithExternalNameTable:options:] + 679
45 com.apple.AppKit 0x00007fff4f3e2d70 -[NSNib _instantiateWithOwner:options:topLevelObjects:] + 136
46 com.apple.AppKit 0x00007fff4fada64c -[NSStoryboard instantiateControllerWithIdentifier:] + 236
47 com.apple.AppKit 0x00007fff4f23e855 NSApplicationMain + 702
48 ??? 0x00000001151c56b7 0 + 4649146039
49 ??? 0x00000001151c53ab 0 + 4649145259
50 Browning-Financial.WealthBox-Addon 0x000000010edc5593 mono_jit_runtime_invoke + 1443 (mini-runtime.c:2806)
51 Browning-Financial.WealthBox-Addon 0x000000010eeaee4f mono_runtime_invoke_checked + 127 (object.c:2887)
52 Browning-Financial.WealthBox-Addon 0x000000010eeb5c2e mono_runtime_exec_main_checked + 110 (object.c:4782)
53 Browning-Financial.WealthBox-Addon 0x000000010ed1087f mono_jit_exec + 287 (driver.g.c:1210)
54 Browning-Financial.WealthBox-Addon 0x000000010ed1384a mono_main + 11114 (driver.g.c:2418)
55 Browning-Financial.WealthBox-Addon 0x000000010ecb0a8e xamarin_main + 1182 (launcher.m:661)
56 Browning-Financial.WealthBox-Addon 0x000000010ecb1a04 main + 36 (launcher.m:679)
57 libdyld.dylib 0x00007fff7ef42ed9 start + 1
Thread 1:
0 libsystem_pthread.dylib 0x00007fff7f1353f8 start_wqthread + 0
1 ??? 0x0000000054485244 0 + 1414025796
Thread 2:: SGen worker
0 libsystem_kernel.dylib 0x00007fff7f07f7de __psynch_cvwait + 10
1 libsystem_pthread.dylib 0x00007fff7f139593 _pthread_cond_wait + 724
2 Browning-Financial.WealthBox-Addon 0x000000010ef7416e thread_func + 558 (mono-os-mutex.h:173)
3 libsystem_pthread.dylib 0x00007fff7f136305 _pthread_body + 126
4 libsystem_pthread.dylib 0x00007fff7f13926f _pthread_start + 70
5 libsystem_pthread.dylib 0x00007fff7f135415 thread_start + 13
Thread 3:: Finalizer
0 libsystem_kernel.dylib 0x00007fff7f07c1b6 semaphore_wait_trap + 10
1 Browning-Financial.WealthBox-Addon 0x000000010ee4c7a5 finalizer_thread + 293 (mono-os-semaphore.h:90)
2 Browning-Financial.WealthBox-Addon 0x000000010ef01b50 start_wrapper + 704 (threads.c:1004)
3 libsystem_pthread.dylib 0x00007fff7f136305 _pthread_body + 126
4 libsystem_pthread.dylib 0x00007fff7f13926f _pthread_start + 70
5 libsystem_pthread.dylib 0x00007fff7f135415 thread_start + 13
Thread 4:: Debugger agent
0 libsystem_kernel.dylib 0x00007fff7f07f3e6 __recvfrom + 10
1 Browning-Financial.WealthBox-Addon 0x000000010ed0515e socket_transport_recv + 78 (debugger-agent.c:1153)
2 Browning-Financial.WealthBox-Addon 0x000000010ecf5a7c debugger_thread + 28588 (debugger-agent.c:1558)
3 Browning-Financial.WealthBox-Addon 0x000000010ef01b50 start_wrapper + 704 (threads.c:1004)
4 libsystem_pthread.dylib 0x00007fff7f136305 _pthread_body + 126
5 libsystem_pthread.dylib 0x00007fff7f13926f _pthread_start + 70
6 libsystem_pthread.dylib 0x00007fff7f135415 thread_start + 13
Thread 5:
0 libsystem_pthread.dylib 0x00007fff7f1353f8 start_wqthread + 0
1 ??? 0x0000000054485244 0 + 1414025796
Thread 0 crashed with X86 Thread State (64-bit):
rax: 0x0000000000000000 rbx: 0x000000011d9ae5c0 rcx: 0x00007ffee0f81a18 rdx: 0x0000000000000000
rdi: 0x0000000000000307 rsi: 0x0000000000000006 rbp: 0x00007ffee0f81a50 rsp: 0x00007ffee0f81a18
r8: 0x0000000000000000 r9: 0x0000000000989680 r10: 0x0000000000000000 r11: 0x0000000000000206
r12: 0x0000000000000307 r13: 0x000000011597b000 r14: 0x0000000000000006 r15: 0x000000000000002d
rip: 0x00007fff7f08223e rfl: 0x0000000000000206 cr2: 0x00007fffb1d2c188
Logical CPU: 0
Error Code: 0x02000148
Trap Number: 133
当 serializing/deserializing 数据是 POD(普通旧数据,即仅包含 get/set 没有业务逻辑的字段属性时,最好坚持使用普通 DTO(数据传输对象)关联)。
从这个意义上说,您的 ContactRoot 类型是 POD,但是 Contact 类型不是 POD(由于 NSObject 的继承)。对于这种情况,我将为 Contact 引入一个单独的 DTO 类型,它将遵循 POD 标准。您可以为联系人列表创建替代 属性,并尝试使用 JsonIgnore 和 JsonProperty 属性来模仿所需的行为。
快速摘要:
public class ContactDto
{
/* List relevant properties here */
}
public class ContactRoot
{
[JsonIgnore] // Do not serialize this
public List<Contact> Contacts { get; set; }
[JsonProperty(Propertyname = nameof(Contacts)]
public List<ContactDto> SerializableContacts {
get => Contacts?.Select(x => /* data extraction */).ToList();
set => Contacts = value?.Select(x => /* data extraction */)?.ToList();
}
}
补充:对于 CLR 语言,POD 似乎被称为 POCO
好的,感谢 Evengy Nazarov 为我指明了正确的方向,我有了一个可行的解决方案。
首先,这是我简化后的 POCO 版本 class:
public class ContactDto
{
private string _fullname = String.Empty;
public int id { get; set; }
public string first { get; set; }
public string last { get; set; }
[JsonIgnore]
public string fullname {
get { return this.first + " " + this.last; }
set { _fullname = value; }
}
}
注意没有 NSObject 继承或 属性 修饰(除了 [JsonIgnore]
.
将 ContactRoot 更改为:
public class ContactRoot
{
[JsonIgnore] // Do not serialize this
public List<SimpleContact> SimpleContacts { get; set; }
[JsonProperty(PropertyName = nameof(Contacts))]
public List<ContactDto> SerializableContacts { get; set; }
}
然后我创建了转换方法,使用 System.Reflection:
在 DTO 和 NSObject 版本之间进行转换
public ContactDto ConvertToDto(SimpleContact simpleContact)
{
var contactdto = new ContactDto();
foreach (PropertyInfo prop in simpleContact.GetType().GetProperties().Where(t => t.DeclaringType == typeof(SimpleContact)))
{
var value = prop.GetValue(simpleContact);
if (value != null)
{
var prop2 = contactdto.GetType().GetProperty(prop.Name);
prop2.SetValue(contactdto, value);
}
}
return contactdto;
}
public SimpleContact ConvertToContact(ContactDto contactDto)
{
var simplecontact = new SimpleContact();
foreach (PropertyInfo prop in contactDto.GetType().GetProperties())
{
var value = prop.GetValue(contactDto);
if (value != null)
{
var prop2 = simplecontact.GetType().GetProperty(prop.Name);
prop2.SetValue(simplecontact, value);
}
}
return simplecontact;
}
然后是我的新序列化方法:
var contactroot = new ContactRoot
{
SimpleContacts = DataSource.SimpleContacts,
SerializableContacts = new List<ContactDto>()
};
foreach (var simplecontact in contactroot.SimpleContacts)
{
contactroot.SerializableContacts.Add(ConvertToDto(simplecontact));
}
var desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
var filename = Path.Combine(desktop, "WBAddon.json");
if (File.Exists(filename))
{
File.Delete(filename);
}
using (StreamWriter file = File.CreateText(filename))
{
var serializer = new JsonSerializer()
{
Formatting = Formatting.Indented,
TypeNameHandling = TypeNameHandling.Auto,
TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};
await Task.Run(() => serializer.Serialize(file, contactroot));
}
反序列化:
var jsettings = new JsonSerializerSettings
{
Formatting = Formatting.Indented,
TypeNameHandling = TypeNameHandling.Auto,
TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};
string json = string.Empty;
using (StreamReader file = new StreamReader(filename))
{
json = file.ReadToEnd();
}
var contactroot = JsonConvert.DeserializeObject<ContactRoot>(json);
DataSource.SimpleContacts = new List<SimpleContact>();
foreach (var contactdto in contactroot.SerializableContacts)
{
DataSource.SimpleContacts.Add(ConvertToContact(contactdto));
}
如我所愿!现在我只需要创建一个包含所有 70 多个属性的完整联系人 class 的 dto 版本。可能有更好的方法,但这可以完成工作。
我正在尝试使用 Visual Studio 中的 C# 将 JSON 字符串反序列化为列表,用于 Xamarin.Mac 项目的 Mac。
我可以毫无问题地进行序列化:
using (StreamWriter file = File.CreateText(filename))
{
var serializer = new JsonSerializer()
{
Formatting = Formatting.Indented,
TypeNameHandling = TypeNameHandling.Auto,
TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};
await Task.Run(() => serializer.Serialize(file, contactroot));
}
但是当我尝试使用此反序列化时出现上述错误:
var contacts = JsonConvert.DeserializeObject<ContactRoot>(json);
联系人根class:
public class ContactRoot
{
public List<Contact> contacts { get; set; }
}
Contact class 继承了 NSObject class 以绑定到 Mac 应用程序中的控件。我也会包括它,但有超过 70 个具有多个属性的属性。这是 class 中的几个片段:
[Register("Contact")]
public class Contact : NSObject
...还有很多这样的属性:
public DateTime? updated_at { get; set; }
[Export("updatedString"), Display(Name = "Updated Date"), Category("Misc"), Description("3"), DefaultValue(TypeOfValue.DateTime)]
public string updatedString
{
get {
if (this.updated_at.HasValue){
return this.updated_at.Value.ToString();
} else{
return string.Empty;
}
}
set
{
WillChangeValue("updatedString");
try
{
if (!String.IsNullOrEmpty(value)) this.updated_at = Convert.ToDateTime(value);
}
catch (Exception)
{
}
DidChangeValue("updatedString");
}
}
我正在使用 DateTime?因为 API 源需要这样做,并且由于 Xamarin 数据绑定似乎不处理 int 或 DateTime 的空值,所以我使用字符串 属性 进行转换。使用该应用程序时效果很好,但不确定反序列化时是否会导致错误。 我是 Mac 的开发新手,所以我可能错过了一些东西。
编辑
哇,感谢您的快速回复!在看到任何评论之前,我尝试了一个更简单的 class 但得到了相同的结果:
[Register("SimpleContact")]
public class SimpleContact : NSObject
{
int _id = 0;
string _first = String.Empty;
string _last = String.Empty;
[Export("id")]
public int id {
get { return _id; }
set {
WillChangeValue("id");
_id = value;
DidChangeValue("id");
}
}
[Export("first")]
public string first {
get { return _first; }
set {
WillChangeValue("first");
_first = value;
DidChangeValue("first");
}
}
[Export("last")]
public string last
{
get { return _last; }
set
{
WillChangeValue("last");
_last = value;
DidChangeValue("last");
}
}
[Export("fullname")]
public string fullname
{
get { return this.first + " " + this.last; }
}
public SimpleContact()
{}
public SimpleContact(int id, string first, string last)
{
this.id = id;
this.first = first;
this.last = last;
}
public override string ToString()
{
return this.fullname;
}
}
接下来我将尝试 POCO 方法并 post 结果。非常感谢!
编辑 这是异常的实质内容。我认为其余的异常没有任何用处:
Crashed Thread: 0 tid_307 Dispatch queue: com.apple.main-thread
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
External Modification Warnings:
Debugger attached to process.
Application Specific Information:
abort() called
WealthBox Addon(6016,0x11d9ae5c0) malloc: *** error for object 0x7fff7f110880: pointer being freed was not allocated
Thread 0 Crashed:: tid_307 Dispatch queue: com.apple.main-thread
0 libsystem_kernel.dylib 0x00007fff7f08223e __pthread_kill + 10
1 libsystem_pthread.dylib 0x00007fff7f138c1c pthread_kill + 285
2 libsystem_c.dylib 0x00007fff7efeb268 __abort + 144
3 libsystem_c.dylib 0x00007fff7efeb1d8 abort + 142
4 libsystem_malloc.dylib 0x00007fff7f0fa6e2 malloc_vreport + 545
5 libsystem_malloc.dylib 0x00007fff7f0fa4a3 malloc_report + 152
6 libsystem_malloc.dylib 0x00007fff7f0f2aff malloc_set_zone_name + 47
7 ??? 0x00000001162ad420 0 + 4666872864
8 ??? 0x000000011616c6a3 0 + 4665558691
9 ??? 0x0000000116275739 0 + 4666644281
10 ??? 0x0000000116265443 0 + 4666577987
11 ??? 0x000000011625cbd3 0 + 4666543059
12 ??? 0x000000011618480b 0 + 4665657355
13 ??? 0x00000001162755bb 0 + 4666643899
14 ??? 0x0000000116265443 0 + 4666577987
15 ??? 0x000000011625cbd3 0 + 4666543059
16 ??? 0x000000011618480b 0 + 4665657355
17 ??? 0x000000011618885b 0 + 4665673819
18 ??? 0x0000000116185c7b 0 + 4665662587
19 ??? 0x000000011618486b 0 + 4665657451
20 ??? 0x000000011609f303 0 + 4664718083
21 ??? 0x000000011609cc03 0 + 4664708099
22 ??? 0x000000011609c84e 0 + 4664707150
23 ??? 0x0000000116095663 0 + 4664677987
24 ??? 0x0000000116087a33 0 + 4664621619
25 Browning-Financial.WealthBox-Addon 0x000000010edc5593 mono_jit_runtime_invoke + 1443 (mini-runtime.c:2806)
26 Browning-Financial.WealthBox-Addon 0x000000010eeaee4f mono_runtime_invoke_checked + 127 (object.c:2887)
27 Browning-Financial.WealthBox-Addon 0x000000010eeb36fc mono_runtime_invoke + 76 (object.c:2941)
28 Browning-Financial.WealthBox-Addon 0x000000010ecadaa2 xamarin_invoke_trampoline + 6018 (trampolines-invoke.m:456)
29 Browning-Financial.WealthBox-Addon 0x000000010ecaec7d xamarin_arch_trampoline + 189 (trampolines-x86_64.m:547)
30 Browning-Financial.WealthBox-Addon 0x000000010ecb00b1 xamarin_x86_64_common_trampoline + 110
31 com.apple.AppKit 0x00007fff4f3deb5a -[NSViewController _sendViewDidLoad] + 97
32 com.apple.AppKit 0x00007fff4f3dbeb5 _noteLoadCompletionForObject + 645
33 com.apple.AppKit 0x00007fff4f24d99f -[NSIBObjectData nibInstantiateWithOwner:options:topLevelObjects:] + 2086
34 com.apple.AppKit 0x00007fff4f3e3114 -[NSNib _instantiateNibWithExternalNameTable:options:] + 679
35 com.apple.AppKit 0x00007fff4f3e2d70 -[NSNib _instantiateWithOwner:options:topLevelObjects:] + 136
36 com.apple.AppKit 0x00007fff4f3e1fdc -[NSViewController loadView] + 343
37 com.apple.AppKit 0x00007fff4f3ddb60 -[NSViewController _loadViewIfRequired] + 75
38 com.apple.AppKit 0x00007fff4f3ddacb -[NSViewController view] + 30
39 com.apple.AppKit 0x00007fff4f4d01da -[NSWindow _contentViewControllerChanged] + 109
40 com.apple.Foundation 0x00007fff540c7450 -[NSObject(NSKeyValueCoding) setValue:forKey:] + 331
41 com.apple.AppKit 0x00007fff4f3da987 -[NSWindow setValue:forKey:] + 111
42 com.apple.AppKit 0x00007fff4f32ce0c -[NSIBUserDefinedRuntimeAttributesConnector establishConnection] + 637
43 com.apple.AppKit 0x00007fff4f24d739 -[NSIBObjectData nibInstantiateWithOwner:options:topLevelObjects:] + 1472
44 com.apple.AppKit 0x00007fff4f3e3114 -[NSNib _instantiateNibWithExternalNameTable:options:] + 679
45 com.apple.AppKit 0x00007fff4f3e2d70 -[NSNib _instantiateWithOwner:options:topLevelObjects:] + 136
46 com.apple.AppKit 0x00007fff4fada64c -[NSStoryboard instantiateControllerWithIdentifier:] + 236
47 com.apple.AppKit 0x00007fff4f23e855 NSApplicationMain + 702
48 ??? 0x00000001151c56b7 0 + 4649146039
49 ??? 0x00000001151c53ab 0 + 4649145259
50 Browning-Financial.WealthBox-Addon 0x000000010edc5593 mono_jit_runtime_invoke + 1443 (mini-runtime.c:2806)
51 Browning-Financial.WealthBox-Addon 0x000000010eeaee4f mono_runtime_invoke_checked + 127 (object.c:2887)
52 Browning-Financial.WealthBox-Addon 0x000000010eeb5c2e mono_runtime_exec_main_checked + 110 (object.c:4782)
53 Browning-Financial.WealthBox-Addon 0x000000010ed1087f mono_jit_exec + 287 (driver.g.c:1210)
54 Browning-Financial.WealthBox-Addon 0x000000010ed1384a mono_main + 11114 (driver.g.c:2418)
55 Browning-Financial.WealthBox-Addon 0x000000010ecb0a8e xamarin_main + 1182 (launcher.m:661)
56 Browning-Financial.WealthBox-Addon 0x000000010ecb1a04 main + 36 (launcher.m:679)
57 libdyld.dylib 0x00007fff7ef42ed9 start + 1
Thread 1:
0 libsystem_pthread.dylib 0x00007fff7f1353f8 start_wqthread + 0
1 ??? 0x0000000054485244 0 + 1414025796
Thread 2:: SGen worker
0 libsystem_kernel.dylib 0x00007fff7f07f7de __psynch_cvwait + 10
1 libsystem_pthread.dylib 0x00007fff7f139593 _pthread_cond_wait + 724
2 Browning-Financial.WealthBox-Addon 0x000000010ef7416e thread_func + 558 (mono-os-mutex.h:173)
3 libsystem_pthread.dylib 0x00007fff7f136305 _pthread_body + 126
4 libsystem_pthread.dylib 0x00007fff7f13926f _pthread_start + 70
5 libsystem_pthread.dylib 0x00007fff7f135415 thread_start + 13
Thread 3:: Finalizer
0 libsystem_kernel.dylib 0x00007fff7f07c1b6 semaphore_wait_trap + 10
1 Browning-Financial.WealthBox-Addon 0x000000010ee4c7a5 finalizer_thread + 293 (mono-os-semaphore.h:90)
2 Browning-Financial.WealthBox-Addon 0x000000010ef01b50 start_wrapper + 704 (threads.c:1004)
3 libsystem_pthread.dylib 0x00007fff7f136305 _pthread_body + 126
4 libsystem_pthread.dylib 0x00007fff7f13926f _pthread_start + 70
5 libsystem_pthread.dylib 0x00007fff7f135415 thread_start + 13
Thread 4:: Debugger agent
0 libsystem_kernel.dylib 0x00007fff7f07f3e6 __recvfrom + 10
1 Browning-Financial.WealthBox-Addon 0x000000010ed0515e socket_transport_recv + 78 (debugger-agent.c:1153)
2 Browning-Financial.WealthBox-Addon 0x000000010ecf5a7c debugger_thread + 28588 (debugger-agent.c:1558)
3 Browning-Financial.WealthBox-Addon 0x000000010ef01b50 start_wrapper + 704 (threads.c:1004)
4 libsystem_pthread.dylib 0x00007fff7f136305 _pthread_body + 126
5 libsystem_pthread.dylib 0x00007fff7f13926f _pthread_start + 70
6 libsystem_pthread.dylib 0x00007fff7f135415 thread_start + 13
Thread 5:
0 libsystem_pthread.dylib 0x00007fff7f1353f8 start_wqthread + 0
1 ??? 0x0000000054485244 0 + 1414025796
Thread 0 crashed with X86 Thread State (64-bit):
rax: 0x0000000000000000 rbx: 0x000000011d9ae5c0 rcx: 0x00007ffee0f81a18 rdx: 0x0000000000000000
rdi: 0x0000000000000307 rsi: 0x0000000000000006 rbp: 0x00007ffee0f81a50 rsp: 0x00007ffee0f81a18
r8: 0x0000000000000000 r9: 0x0000000000989680 r10: 0x0000000000000000 r11: 0x0000000000000206
r12: 0x0000000000000307 r13: 0x000000011597b000 r14: 0x0000000000000006 r15: 0x000000000000002d
rip: 0x00007fff7f08223e rfl: 0x0000000000000206 cr2: 0x00007fffb1d2c188
Logical CPU: 0
Error Code: 0x02000148
Trap Number: 133
当 serializing/deserializing 数据是 POD(普通旧数据,即仅包含 get/set 没有业务逻辑的字段属性时,最好坚持使用普通 DTO(数据传输对象)关联)。
从这个意义上说,您的 ContactRoot 类型是 POD,但是 Contact 类型不是 POD(由于 NSObject 的继承)。对于这种情况,我将为 Contact 引入一个单独的 DTO 类型,它将遵循 POD 标准。您可以为联系人列表创建替代 属性,并尝试使用 JsonIgnore 和 JsonProperty 属性来模仿所需的行为。
快速摘要:
public class ContactDto
{
/* List relevant properties here */
}
public class ContactRoot
{
[JsonIgnore] // Do not serialize this
public List<Contact> Contacts { get; set; }
[JsonProperty(Propertyname = nameof(Contacts)]
public List<ContactDto> SerializableContacts {
get => Contacts?.Select(x => /* data extraction */).ToList();
set => Contacts = value?.Select(x => /* data extraction */)?.ToList();
}
}
补充:对于 CLR 语言,POD 似乎被称为 POCO
好的,感谢 Evengy Nazarov 为我指明了正确的方向,我有了一个可行的解决方案。
首先,这是我简化后的 POCO 版本 class:
public class ContactDto
{
private string _fullname = String.Empty;
public int id { get; set; }
public string first { get; set; }
public string last { get; set; }
[JsonIgnore]
public string fullname {
get { return this.first + " " + this.last; }
set { _fullname = value; }
}
}
注意没有 NSObject 继承或 属性 修饰(除了 [JsonIgnore]
.
将 ContactRoot 更改为:
public class ContactRoot
{
[JsonIgnore] // Do not serialize this
public List<SimpleContact> SimpleContacts { get; set; }
[JsonProperty(PropertyName = nameof(Contacts))]
public List<ContactDto> SerializableContacts { get; set; }
}
然后我创建了转换方法,使用 System.Reflection:
在 DTO 和 NSObject 版本之间进行转换public ContactDto ConvertToDto(SimpleContact simpleContact)
{
var contactdto = new ContactDto();
foreach (PropertyInfo prop in simpleContact.GetType().GetProperties().Where(t => t.DeclaringType == typeof(SimpleContact)))
{
var value = prop.GetValue(simpleContact);
if (value != null)
{
var prop2 = contactdto.GetType().GetProperty(prop.Name);
prop2.SetValue(contactdto, value);
}
}
return contactdto;
}
public SimpleContact ConvertToContact(ContactDto contactDto)
{
var simplecontact = new SimpleContact();
foreach (PropertyInfo prop in contactDto.GetType().GetProperties())
{
var value = prop.GetValue(contactDto);
if (value != null)
{
var prop2 = simplecontact.GetType().GetProperty(prop.Name);
prop2.SetValue(simplecontact, value);
}
}
return simplecontact;
}
然后是我的新序列化方法:
var contactroot = new ContactRoot
{
SimpleContacts = DataSource.SimpleContacts,
SerializableContacts = new List<ContactDto>()
};
foreach (var simplecontact in contactroot.SimpleContacts)
{
contactroot.SerializableContacts.Add(ConvertToDto(simplecontact));
}
var desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
var filename = Path.Combine(desktop, "WBAddon.json");
if (File.Exists(filename))
{
File.Delete(filename);
}
using (StreamWriter file = File.CreateText(filename))
{
var serializer = new JsonSerializer()
{
Formatting = Formatting.Indented,
TypeNameHandling = TypeNameHandling.Auto,
TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};
await Task.Run(() => serializer.Serialize(file, contactroot));
}
反序列化:
var jsettings = new JsonSerializerSettings
{
Formatting = Formatting.Indented,
TypeNameHandling = TypeNameHandling.Auto,
TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};
string json = string.Empty;
using (StreamReader file = new StreamReader(filename))
{
json = file.ReadToEnd();
}
var contactroot = JsonConvert.DeserializeObject<ContactRoot>(json);
DataSource.SimpleContacts = new List<SimpleContact>();
foreach (var contactdto in contactroot.SerializableContacts)
{
DataSource.SimpleContacts.Add(ConvertToContact(contactdto));
}
如我所愿!现在我只需要创建一个包含所有 70 多个属性的完整联系人 class 的 dto 版本。可能有更好的方法,但这可以完成工作。