【问题标题】:Deserialize JSON error converting value to specific type反序列化 JSON 错误将值转换为特定类型
【发布时间】:2018-09-02 19:24:15
【问题描述】:

我有一个带有创建 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;
        }

【问题讨论】:

  • 所以我把 depper 挖进去了。我目前正在寻找的是最好的策略: 1. 自定义 IReferenceResolver:这真的对我的任务有帮助吗?我在stackoverflow.com/questions/38964774/… 看到过那个,但是这个“仅”似乎适用于一种类型,而我有 3 种不同的类型..? 2. 写一个完全自定义的JSON Renderer,由谁解析示例..? 3. 将后端重写为只序列化一个类,然后为子类调用 REST 服务... 4. 其他替代方案?
  • 使用像QuickType 这样的工具会让你的生活变得更轻松。

标签: c# json serialization json.net


【解决方案1】:

正如您已经想到的,您应该使用自定义IReferenceResolver

您在 cmets 中询问如何使用多种类型来完成。您可以使用here 找到的解析器代码来执行此操作。此链接包含一个完整示例:

&lt;script src="https://gist.github.com/carlin-q-scott/4c8a9cce734fa5b10a97.js"&gt;&lt;/script&gt;

虽然它不使用多种类型,但很容易演示它在这种情况下的使用方式。

例如,除了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"",
  }
]

它的工作原理与fiddle 相同(请注意,它不是使用ReferenceResolverProvider(如链接中所示),而是使用ReferenceResolver(已过时),这是因为它会导致一些奇怪的错误这里;无论如何,你应该使用前者)。

【讨论】:

  • 感谢您的帮助! :)
猜你喜欢
  • 2017-05-07
  • 1970-01-01
  • 1970-01-01
  • 2015-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多