Десериализовать JSON и присвоить модели - PullRequest
1 голос
/ 25 февраля 2020

Как часть моего веб-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; }
}

Тогда мой текстовый лог c будет таким:

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

}

Когда я отлаживаю вышеупомянутое в моем проверьте, что он говорит мне следующее:

Значение JSON не может быть преобразовано в MyProject.HangfireTestDTO

Затем мое мышление заставило меня попробовать еще раз, изменив десериализацию строка к следующему:

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

Но при запуске с новой строкой я получаю следующую ошибку:

Значение JSON не может быть преобразовано в систему. Collections.Generi c .List

Что я делаю не так?

Ответы [ 3 ]

1 голос
/ 25 февраля 2020

во-первых, ваш 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 должен быть целым или двойным, IsSuccess - это логическое значение, et c

наконец, в вашем JSON есть много полей, которые не находятся на вашем объекте, вам нужно объяснить c#, что с ними делать, либо создать дополнительные свойства, либо предоставить KeyValue сохранить его можно поместить в ie

[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);
1 голос
/ 25 февраля 2020

Ваша текущая строка 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);
    }
}
0 голосов
/ 25 февраля 2020

Первая ошибка из-за 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);
...