反序列化 JSON 并分配给模型

Deserialize JSON and assign to model

作为我的网络 api 的一部分,我得到以下 JSON 返回。

["{\"InputType\":17,\"EngineSubType\":4,\"Filename\":\"targetFile.csv\",\"FileExtensionType\":\".csv\",\"IsLoadFile\":true,\"LoadContextId\":4121,\"ReportingDate\":\"2019-05-31T00:00:00\",\"IsSuccess\":false}"]

我想要做的是获取 Filename 旁边的值并将其分配给我的模型 Filename 参数。

在我的项目中,我创建了一个单元测试来尝试获取该值,但我所做的每次尝试都失败了。

在我的测试中,我有以下 DTO 模型:

public class HangfireTestDTO
{
    public string InputType { get; set; }
    public string Filename { get; set; }
}

那么我的文字逻辑是这样的:

[Fact]
public void TestDTO()
{
    string data =
          "[\"{\\"InputType\\":12,\\"EngineSubType\\":2,\\"Filename\\":\\"targetFile.csv\\",\\"FileExtensionType\\":\\".csv\\",\\"IsLoadFile\\":true,\\"LoadContextId\\":4120,\\"ReportingDate\\":\\"2019-05-31T00:00:00\\",\\"IsSuccess\\":false}\"]";

     // fails here
     var arguments = System.Text.Json.JsonSerializer.Deserialize<HangfireTestDTO>(data);

     // This is wrong - ignore for now
     Assert.Equal("targetFile.csv", arguments.ToString());

}

当我在测试中调试上面的内容时,它告诉我以下内容:

The JSON value could not be converted to MyProject.HangfireTestDTO

然后我的想法让我再次尝试将反序列化行修改为以下内容:

 var arguments = System.Text.Json.JsonSerializer.Deserialize<IEnumerable<HangfireTestDTO>>(data).FirstOrDefault();

但是当 运行 换行时,我得到以下错误:

The JSON value could not be converted to System.Collections.Generic.List

我做错了什么?

第一个错误是因为 InputType。应该是int

public class HangfireTestDTO
{
    public int InputType { get; set; }
    public string Filename { get; set; }
}

第二个错误是因为JSON[{之间有一个加引号。我已经尝试使用以下 JSON 并且它有效。由于这个引用,它变成 List<string> 而不是 List<HangfireTestDTO>

[
    {
        "InputType": 12,
        "EngineSubType": 2,
        "Filename": "targetFile.csv",
        "FileExtensionType": ".csv",
        "IsLoadFile": true,
        "LoadContextId": 4120,
        "ReportingDate": "2019-05-31T00:00:00",
        "IsSuccess": false
    }
]

并且查看 JSON 应该是 IEnumerable<HangfireTestDTO>

var arguments = JsonSerializer.Deserialize<IEnumerable<HangfireTestDTO>>(data);

首先你的JSON是错误的 我希望它看起来更像

string data = @"[{""InputType"":12,""EngineSubType"":2,""Filename"":""targetFile.csv"",""FileExtensionType"":"".csv"",""IsLoadFile"":true,""LoadContextId"":4120,""ReportingDate"":""2019-05-31T00:00:00"",""IsSuccess"":false}]"

string data = "[{\"InputType\":17,\"EngineSubType\":4,\"Filename\":\"targetFile.csv\",\"FileExtensionType\":\".csv\",\"IsLoadFile\":true,\"LoadContextId\":4121,\"ReportingDate\":\"2019-05-31T00:00:00\",\"IsSuccess\":false}]"

其次,您将 JSON 包装在 [] 中,这意味着文档列表,因此 Deserialize<HangfireTestDTO>(data); 将是 Deserialize<List<HangfireTestDTO>>(data); 或其他一些 IEnumerable

然后你有几个数据不匹配 12 是一个数字而不是字符串所以 InputType 应该是一个 int 或 double,IsSuccess 是一个 bool,等等

最后,您的 JSON 中有很多字段不在您的对象中,您需要向 c# 解释如何处理它们,要么创建额外的属性,要么提供一个可以放置它们的 KeyValue 存储在 即

[JsonExtensionData]
public Dictionary<string, object> ExtensionData { get; set; }

如果数据真的是这样从你的数据库中出来的,那么在你发表的评论之后进行编辑,然后它是一个字符串数组,其中的字符串是 JSON 编码的

在这种情况下,您将需要读取字符串然后在

之后解析它们
var jsonlist = JsonSerializer.Deserialize<List<string>>(data);
foreach(string json in jsonlist )
    var dto = JsonSerializer.Deserialize<HangfireTestDTO>(json);

您当前的 JSON 字符串是一个字符串数组。您需要首先将 JSON 反序列化为 字符串列表,然后将这些字符串中的每一个反序列化为 DTO。这是使用 JSON:

的完整示例
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;

public class HangfireTestDTO
{
    public int InputType { get; set; }
    public int EngineSubType { get; set; }
    public string Filename { get; set; }
    public string FileExtensionType { get; set; }
}

class Program
{
    static void Main()
    {
        string data =
          "[\"{\\"InputType\\":12,\\"EngineSubType\\":2,\\"Filename\\":\\"targetFile.csv\\",\\"FileExtensionType\\":\\".csv\\",\\"IsLoadFile\\":true,\\"LoadContextId\\":4120,\\"ReportingDate\\":\\"2019-05-31T00:00:00\\",\\"IsSuccess\\":false}\"]";

        // First deserialize the single string to a list of strings
        List<string> jsonStrings = JsonSerializer.Deserialize<List<string>>(data);

        // Then deserialize each of the strings to a DTO.
        List<HangfireTestDTO> dtos = jsonStrings
            .Select(json => JsonSerializer.Deserialize<HangfireTestDTO>(json))
            .ToList();
        Console.WriteLine(dtos.Count);
        Console.WriteLine(dtos[0].Filename);
    }
}