-1
I’m having problems returning a third party API (I don’t have access to the code) that I’m consuming, more specifically in the section below:
var result = client.SendAsync(request).Result;
var resultContent = result.Content.ReadAsStringAsync().Result;
if (result.StatusCode == HttpStatusCode.OK)
{
return JsonConvert.DeserializeObject<PaymentDTO>(resultContent);
}
The error occurs in the return
when I deserializo the json resultContent
in my object PaymentDTO
.
This is my PaymentDTO
:
public class PaymentDTO
{
public IEnumerable<ItemDTO> Itens { get; set; }
[...]
}
This is my ItemDTO
:
public class ItemDTO
{
[...]
public RecordDTO Cadastro { get; set; }
}
This is my RecordDTO
:
public class RecordDTO
{
[...]
public AddressDTO Endereco { get; set; }
}
And this is mine AddressDTO
:
public class AddressDTO
{
public string Id { get; set; }
public string Cep { get; set; }
public string Logradouro { get; set; }
public string Numero { get; set; }
public string Complemento { get; set; }
public string Bairro { get; set; }
public string Cidade { get; set; }
public string Uf { get; set; }
}
The problem occurs when returning the API when the address object changes, it changes according to whether the person has a registered address or not. Below is an example of a return for a person with an address:
"itens": [
{
"id": "1193053",
[...]
"cadastro": {
"id": "230009543",
"nome_completo": "xxxx xxx",
"endereco": {
"id": "151032",
"cep": "xxxxxx",
"logradouro": "RUA XXXX",
"numero": "777",
"complemento": "blá blá",
"bairro": "bairro tal",
"cidade": "XXXXX",
"uf": "SP"
}
}
}
]
Now an example of a return for a person with no address registered in the API:
"itens": [
{
"id": "879432",
"cadastro": {
"id": "43264",
"nome_completo": "xxxx xxx",
"endereco": []
}
}
]
You can tell when the person no address, the object endereco
is returned as an array: endereco: []
instead of being returned as endereco: null
, for example. But when the person has address, the object is not returned as endereco: [{...}]
. When the person has address, it is returned as a single object. This causes, at the time of deserializar, if the person has no address, the process bursts the following exception:
Cannot deserialize the Current JSON array (e.g. [1,2,3]) into type 'Domnomedomeuassembly.DTO.Addressdto' because the type requires a JSON Object (e.g. {"name":"value"}) to deserialize correctly. To fix this error either change the JSON to a JSON Object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that Implements a Collection interface (e.g. Icollection, Ilist) like List that can be deserialized from a JSON array. Jsonarrayattribute can also be Added to the type to force it to deserialize from a JSON array. Path 'items[1].Address', line 671, position 29. |
Because, I imagine, Newtonsoft’s deserializer understands that the object endereco
returned is an array, but it is not. So the error asks me to define my object AddressDTO
as a list. Example:
public class RecordDTO
{
[...]
public IEnumerable<AddressDTO> Endereco { get; set; }
}
When I do this, the error pops right into the first person who has the address filled in, and the error message is pretty much the same, but this time it speaks the opposite of the previous one: asks me to define my AddressDTO
as a normal object, because the endereco
returned from API is not a list.
I’ve tried to treat it right on the property Endereco
of RecordDTO
, expanding the { get; set; }
to make some logic, but the error occurs soon in the get
property. Therefore, I do not have access to the parameter value
which brings the values of the object to be assigned by dotnet.
I don’t know what I can do in this situation. The last alternative would be to contact the API maintainers to show the case.
Thank you in advance if you have any solution.
"The problem occurs when returning the API when the address object changes, it changes according to whether the person has a registered address or not" an endpoint that returns multiple objects? this seems quite wrong, a contract must be respected and always return the same thing
– Ricardo Pontual
Yeah, that’s what I think is weird. I can’t confirm that the objects are actually different because I don’t have access to the API code, but that’s what it looks like. Or the serializer is automatically inserting these brackets into the address when it comes null. This occurs both using Insomnia or Postman and debugging the C# project by consuming the API.
– Pedro
I believe that the correct thing would be for you to contact the developers of the API that you are consuming, because even if you manage to get around this problem, it may be that tomorrow or later they change this return because it is a mistake. Then you’d have to go back to fiddling with your code.
– Marcos Junior
If you still want to continue, try manipulating JSON serialization to ignore empty array. using
– Marcos Junior
but vc can make a request by Postman or Curl for example and confirm how the objects are. An endpoint can only return a type, otherwise it is a break change in relation to the contract, it may be the case that one scenario returns not part of the object (null) and another returns, if so would be ok, just take the contract of the most complete class... however, if someone provides an endpoint, need to have an example of the contract, and from there you can build your classes
– Ricardo Pontual
@Marcosjunior opa, I had taken a look at the overloads of Deserializeobject but did not find an option for it. But I think if I do it right in the properties of my object, it might work, I’ll try. Thanks for the tip.
– Pedro
@Ricardopunctual then, I made requests by Postman and Insomnia, the return is the same, as I described in the question and more above in my reply to your first comment. The rest of the process is all ready and tested, just this detail that still gets me. API documentation is very vague.
– Pedro