c# - 反序列化 JSON 错误将值转换为特定类型
问题描述
我有一个带有创建 JSON 的 REST 服务的 Django 后端模型。我得到的 JSON(部分)如下所示:
[
{
"id": 1,
"username": "T1",
"tel": "",
"created_on": "2018-09-03T16:29:20.903315Z",
"last_login": null,
"hasContacts": [
],
"myChanges": [
],
"helpsOnChanges": [
],
"shouldHelpOnChanges": [
1
],
"welldone_set": [
{
"id": 1,
"created_on": "2018-09-03T16:29:20.925327Z",
"comment": "You rock1",
"change": 1,
"helper": 1
}
]
},
{
"id": 2,
"username": "T2",
"tel": "",
"created_on": "2018-09-03T16:29:20.903315Z",
"last_login": null,
"hasContacts": [
],
"myChanges": [
{
"id": 1,
"name": "Stop smoking",
"created_on": "2018-09-03T16:29:20.923315Z",
"change": "I want to stop smoking",
"finished_on": null,
"success": false,
"helpee": 2,
"helper": [
],
"requestedHelpers": [
1
],
"welldone_set": [
{
"id": 1,
"created_on": "2018-09-03T16:29:20.925327Z",
"comment": "You rock1",
"change": 1,
"helper": 1
}
]
}
],
"helpsOnChanges": [
],
"shouldHelpOnChanges": [
],
"welldone_set": [
]
}
]
JSONConvert.Deserialize 现在调用的显式错误是:
2018-09-02T18:57:13.145 错误 反序列化 App.ViewModels.Change 时出错。将值 1 转换为类型“App.ViewModels.User”时出错。路径“[0].myChanges[0].helpee”,第 1 行,位置 275。
这是指“helpee”属性,它是用户类型。Django 框架仅将用户的 id 放在此列表中,这是有道理的,因为在上述结果之前,用户已经在此 JSON 中传输。
那么为什么 Newtonsoft.JSON 不能解决这个问题呢?不能将此 id 与同一 id 的实际用户实例相关联吗?
先感谢您!狼
编辑:为了澄清我的 Django 后端的序列化程序:
class ChangeSerializer(serializers.ModelSerializer):
welldone_set = WellDoneSerializer(many=True)
class Meta:
model = Change
fields = ('id',
'name',
'created_on',
'change',
'finished_on',
'success',
'helpee',
'helper',
'requestedHelpers',
'welldone_set')
ChangeSerializer.helpee = UserSerializer();
ChangeSerializer.helper = UserSerializer(many=True);
ChangeSerializer.requestedHelpers = UserSerializer(many=True);
如您所见,helpee 实际上是一个对象而不仅仅是一个 id
编辑 2:更新 json 以完成
编辑 3:我的反序列化方法。在反序列化器行中抛出异常。
public static async Task<List<T>> getDataListFromService<T>(string queryString)
{
Debug.WriteLine("###Building HttpClient for " + queryString);
HttpClient client = new HttpClient();
Debug.WriteLine("###Building GetAsync...");
HttpResponseMessage response = await client.GetAsync(queryString);
Debug.WriteLine("### HTTP Get Response: " + response.ReasonPhrase);
List<T> data = null;
if (response.IsSuccessStatusCode)
{
string json = response.Content.ReadAsStringAsync().Result;
Debug.WriteLine("### JSON REsult: " + json);
ITraceWriter writer = new MemoryTraceWriter();
JsonSerializerSettings settings = new JsonSerializerSettings
{
TraceWriter = writer
};
try
{
data = JsonConvert.DeserializeObject<List<T>>(json, settings);
}
catch (System.Exception ex)
{
Debug.WriteLine("### Exception " + ex.Message);
Debug.WriteLine("### Trace Results: " + writer);
}
}
return data;
}
解决方案
正如您已经知道的那样,您应该使用自定义IReferenceResolver
.
您在评论中询问如何使用多种类型来完成。您可以使用此处找到的解析器代码来执行此操作。此链接包含一个完整示例:
<script src="https://gist.github.com/carlin-q-scott/4c8a9cce734fa5b10a97.js"></script>
尽管它没有使用多种类型,但很容易演示它在这种情况下的使用方式。
例如,除了Person
,我们还可以添加一个Cat
类型:
public class Cat
{
public string Name {get; set;}
}
然后将其添加为以下属性Person
:
public class Person
{
public string Name { get; set;}
public string PhoneNumber { get; set;}
public Person Partner { get; set;}
public Cat Cat { get; set;}
}
然后将json更改为:
[
{
""$id"": ""Jane Doe"",
""Name"": ""Jane Doe"",
""Cat"": {
""$id"": ""Johny"",
""Name"": ""Johny"",
},
""PhoneNumber"": ""(555)555-5555"",
""Partner"": {
""$id"": ""John Doe"",
""Name"": ""John Doe"",
""PhoneNumber"": ""(555)555-5555"",
""Partner"": {
""$ref"": ""Jane Doe""
},
""Cat"": {
""$ref"": ""Johny""
}
}
},
{
""$ref"": ""John Doe"",
}
]
并且它的工作原理与此小提琴中的相同(请注意,ReferenceResolverProvider
它使用(已过时)而不是使用(如链接中的)ReferenceResolver
,这是因为它在这里引起了一些奇怪的错误;无论如何,您应该使用前者)。
推荐阅读
- python - Sphinx 生成文档中的类路径
- python - 不能用 range() 也不能用 len() 遍历元素
- python - 创建 matplotlib 图时,第一行 fig,ax=plt.subplots() 的相关性是什么?
- c# - 将下拉列表过滤添加到使用存储过程的网格视图
- c# - 如何使用脚本将垂直滚动添加到画布?
- javascript - 从 nodejs 应用程序获取一个值到另一个 nodejs 应用程序的客户端
- unity3d - FSM AI 控制器包中的 fsm 编辑器中缺少“+”号
- php - 基于变量值的颜色表行
- java - 将所有复选框(选中)项目收集到 Array 或 ArrayList
- java - 如何使用 GUI 将 InteliJ 项目导出到可执行文件