Deserialize JSON and assign to model

时光毁灭记忆、已成空白 提交于 2021-02-10 18:33:55

问题


As part of my web api, I'm getting the following JSON returned.

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

What I'm wanting to do is grab the value next to Filenameand assign it to my models Filename parameter.

In my project I've created a unit test to experiment with grabbing that value, but each attempt I've making is failing.

In my test I have following DTO Model:

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

Then my text logic is this:

[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());

}

When I debug the above in my test it tells me the following:

The JSON value could not be converted to MyProject.HangfireTestDTO

My thinking then led me to try again by modifying the deserialize line to the following:

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

But when running it with the new line, I get the following error:

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

What is it I'm doing wrong?


回答1:


The first error is because of InputType. It should be int

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

The second error is because of JSON. There is an addition quotation between [ and {. I have tried with below JSON and it worked. Because of this quotation it becomes List<string> and not List<HangfireTestDTO>

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

And looking at the JSON it should be IEnumerable<HangfireTestDTO>

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



回答2:


Your current JSON string is an array of strings. You need to first deserialize the JSON into a list of strings, then deserialize each of those strings as a DTO. Here's a complete example using your 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);
    }
}



回答3:


firstly your JSON is wrong i would expect it too look more like

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

or

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

second you have wrapped your JSON in [] this means a list of docs so Deserialize<HangfireTestDTO>(data); would be Deserialize<List<HangfireTestDTO>>(data); or some other IEnumerable

then you have serveral data mismatches 12 is a number not a string so InputType should be an int or double, IsSuccess is a bool, etc

finally you have lots of fields in your JSON that aren't on your object you need to explain to c# what to do with them either create the extra properties or provide a KeyValue store it can put them in ie

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

EDIT following the comment you made if that is really how the data is coming out your DB then its an array of strings where the strings are JSON encoded

in which case you will need to read the strings then parse them after

var jsonlist = JsonSerializer.Deserialize<List<string>>(data);
foreach(string json in jsonlist )
    var dto = JsonSerializer.Deserialize<HangfireTestDTO>(json);


来源:https://stackoverflow.com/questions/60397175/deserialize-json-and-assign-to-model

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!