I'm trying to use RestSharp to get a List from an API and I'm getting this error:
System.Text.Json.JsonException: 'The JSON value could not be converted to System.Collections.Generic.List`1[VP_Sysmac.ConsoleTest.OperariModel]. Path: $ | LineNumber: 0 |
I can access the same API using Postman and I'm getting the payload I posted below and Status 200 OK.
If I set up a breakpoint this is the internal value of the jsonString:
"\"[\\r\\n {\\r\\n \\\"IdOperari\\\": 0,\\r\\n \\\"Operari\\\": \\\"Varis\\\",\\r\\n \\\"TagRfid\\\": \\\"AAA\\\"\\r\\n },\\r\\n {\\r\\n \\\"IdOperari\\\": 38,\\r\\n \\\"Operari\\\": \\\"Pujol Costa, Josep\\\",\\r\\n \\\"TagRfid\\\": \\\"AAA\\\"\\r\\n },\\r\\n {\\r\\n \\\"IdOperari\\\": 41,\\r\\n \\\"Operari\\\": \\\"Barea González, Antonio\\\",\\r\\n \\\"TagRfid\\\": \\\"AAA\\\"\\r\\n },\\r\\n {\\r\\n \\\"IdOperari\\\": 42,\\r\\n \\\"Operari\\\": \\\"Basora Grau, Àngel\\\",\\r\\n \\\"TagRfid\\\": \\\"AAA\\\"\\r\\n },\\r\\n {\\r\\n \\\"IdOperari\\\": 44,\\r\\n \\\"Operari\\\": \\\"Roy Torras, Jordi\\\",\\r\\n \\\"TagRfid\\\": \\\"AAA\\\"\\r\\n }\\r\\n]\""
If I use the JSON visualizer I get exactly the same result than using Postman. If I use a string variable with the json value I can deserialize it without any problem.
The model
internal class OperariModel
{
public int IdOperari { get; set; }
public string? Operari { get; set; }
public string? TagRfid { get; set; }
}
Accessing rest API
static async Task Main(string[] args)
{
string baseUrl = "http://myserver/apisysmac/api";
var options = new RestClientOptions(baseUrl)
{
RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true
};
RestClient client = new RestClient(options);
var request = new RestRequest($"{baseUrl}/Operaris");
var response = await client.GetAsync(request);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
string json = response.Content.ToString();
var operaris = JsonSerializer.Deserialize<List<OperariModel>>(json);
}
}
Payload received using Postman
[
{
"IdOperari": 0,
"Operari": "Varis",
"TagRfid": "AAA"
},
{
"IdOperari": 38,
"Operari": "Pujol Costa, Josep",
"TagRfid": "AAA"
},
{
"IdOperari": 41,
"Operari": "Barea González, Antonio",
"TagRfid": "AAA"
},
{
"IdOperari": 42,
"Operari": "Basora Grau, Àngel",
"TagRfid": "AAA"
},
{
"IdOperari": 44,
"Operari": "Roy Torras, Jordi",
"TagRfid": "AAA"
}
]
CodePudding user response:
System.Text.Json
is much more stringent on how it handles any atypical text that doesn't fit the JSON spec, which includes carriage returns and escape characters.
Before deserializing, you need to sanitize your input string. Regex.Unescape
will do this for you, although you will need to manually strip your leading and trailing escaping \
characters.
string json = response.Content.ToString();
json = json.Remove(0, 1);
json = json.Remove(json.Length - 1, 1);
var sanitizedJsonString = Regex.Unescape(json);
var operaris = JsonSerializer.Deserialize<List<OperariModel>>(sanitizedJsonString);
Ideally however, you should never have to project to a string and then sanitize it.
RestSharp uses System.Text.Json
as its default serializer and will handle deserialization for you if you use the appropriate methods.
var request = new RestRequest($"{baseUrl}/Operaris");
var response = await client.GetAsync<List<OperariModel>>(request);
CodePudding user response:
From testing on DotNet Fiddle targeting .Net 6, I received errors because of the newlines and the extra \ around property names and values as well as the extra double quoatation marks around the [ and ], I stripped these out using regex and it was able to deserialize, perhaps you need to create a custom converter to make your code more clean or perhaps there is some json settings that would handle this, but here is a working example using your example json string:
string exampletext = "\"[\\r\\n {\\r\\n \\\"IdOperari\\\": 0,\\r\\n \\\"Operari\\\": \\\"Varis\\\",\\r\\n \\\"TagRfid\\\": \\\"AAA\\\"\\r\\n },\\r\\n {\\r\\n \\\"IdOperari\\\": 38,\\r\\n \\\"Operari\\\": \\\"Pujol Costa, Josep\\\",\\r\\n \\\"TagRfid\\\": \\\"AAA\\\"\\r\\n },\\r\\n {\\r\\n \\\"IdOperari\\\": 41,\\r\\n \\\"Operari\\\": \\\"Barea González, Antonio\\\",\\r\\n \\\"TagRfid\\\": \\\"AAA\\\"\\r\\n },\\r\\n {\\r\\n \\\"IdOperari\\\": 42,\\r\\n \\\"Operari\\\": \\\"Basora Grau, Àngel\\\",\\r\\n \\\"TagRfid\\\": \\\"AAA\\\"\\r\\n },\\r\\n {\\r\\n \\\"IdOperari\\\": 44,\\r\\n \\\"Operari\\\": \\\"Roy Torras, Jordi\\\",\\r\\n \\\"TagRfid\\\": \\\"AAA\\\"\\r\\n }\\r\\n]\"";
//replace newlines
var obj = Regex.Replace(exampletext, "\\\\r\\\\n", "");
//Console.WriteLine(obj);
//replace the extra \ around property names/values
obj = Regex.Replace(obj, "\\\\\"", "\"");
//Console.WriteLine(obj);
//replace the extra " around opening bracket
obj = Regex.Replace(obj, "\\\"\\[", "[");
//replace the extra " around closing bracket
obj = Regex.Replace(obj, "\\]\\\"", "]");
Console.WriteLine(obj);
var js = System.Text.Json.JsonSerializer.Deserialize<List<OperariModel>>(obj);
Console.WriteLine(js.Count);
CodePudding user response:
What you have there is double serialization.
Basically, the serializer did this:
- Serialize a collection of objects to a string, containing the JSON for that collection
- Serialize that string ... to another string, now containing JSON that represents a string (that contains a JSON representation of the original collection)
So you need to do double deserialization as well. Manually doing unescaping of escaped characters and handling of special characters might look like it's going to work, but it's a sure way to trip it up with a new example.
Instead, do this:
var json2 = JsonSerializer.Deserialize<string>(json);
var operaris = JsonSerializer.Deserialize<List<OperariModel>>(json2);