问题
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 Filename
and 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