1

I am creating a .net core API, and i am getting strange response from it.

In the API, internal, I am asking another external API and I am using JsonConvert.DeserializeObject when getting the result from the external API. I am able to deserialize to my own class, but when I do a request in Postman to my API, I am getting the fields that I am using for the deserialation.

    public class InvoiceHistoryResponse
    {
        [JsonProperty("results")]
        public IEnumerable<Invoice> Invoices { get; set; }
    }

    public class Invoice
    {
        [JsonProperty("properties")]
        public InvoiceProperty InvoiceProperty { get; set; }

        [JsonProperty("nodes")]
        public InvoiceFile InvoiceFiles { get; set; }
    }

    public class InvoiceFile
    {
        [JsonProperty("file")]
        public string Pdf { get; set; }
    }

    public class InvoiceProperty
    {
        [JsonProperty("invoicenumber")]
        public string InvoiceNumber { get; set; }

        [JsonProperty("totalsum")]
        public decimal InvoiceTotalSum { get; set; }

        [JsonProperty("issuedate")]
        public DateTime InvoiceIssueDate { get; set; }
    }

This is the code when I deserialise:

var invoiceHistoryResponse = JsonConvert.DeserializeObject<InvoiceHistoryResponse>(content);
return invoiceHistoryResponse.Invoices;

This is the result from Postman:

[
    {
        "properties": {
            "invoicenumber": "45293556",
            "totalsum": 1239.55,
            "issuedate": "2000-04-08T00:00:00+02:00"
        },
        "nodes": {
            "file": "https://file.pdf"
        }
    },
    {
        "properties": {
            "invoicenumber": "52095938",
            "totalsum": 989.33,
            "issuedate": "2001-08-18T00:00:00+02:00"
        },
        "nodes": {
            "file": "https://file.pdf"
        }
    },
    {
        "properties": {
            "invoicenumber": "28842180",
            "totalsum": 1504.38,
            "issuedate": "2005-06-06T00:00:00+02:00"
        },
        "nodes": {
            "file": "https://file.pdf"
        }
    }
]

But response should looks like this:

[
    {
        "InvoiceProperty": {
            "InvoiceNumber": "45293556",
            "InvoiceTotalSum": 1239.55,
            "InvoiceIssueDate": "2000-04-08T00:00:00+02:00"
        },
        "InvoiceFiles": {
            "Pdf": "https://file.pdf"
        }
    },
    {
        "InvoiceProperty": {
            "InvoiceNumber": "52095938",
            "InvoiceTotalSum": 989.33,
            "InvoiceIssueDate": "2001-08-18T00:00:00+02:00"
        },
        "InvoiceFiles": {
            "Pdf": "https://file.pdf"
        }
    },
    {
        "InvoiceProperty": {
            "InvoiceNumber": "28842180",
            "InvoiceTotalSum": 1504.38,
            "InvoiceIssueDate": "2005-06-06T00:00:00+02:00"
        },
        "InvoiceFiles": {
            "Pdf": "https://file.pdf"
        }
    }
]

in Controller the endpoint looks like this:

[Produces(typeof(IEnumerable<Invoice>))]
public async Task<IActionResult> GetAllInvoices([FromRoute] string customerId)
{
    var invoices = await _invoiceService.GetCustomerInvoice();
    return Ok(invoices);
}

Any idea why I am getting this strange result?

Don Juan
  • 171
  • 2
  • 17
  • 6
    `[JsonProperty("results")]` overrides the property name... – Andrew Williamson Sep 11 '20 at 00:01
  • Instead of `IActionResult` you can use `ActionResult>` which a) makes it clearer what is actually returned, b) you can omit the Ok wrapper and just do `return invoices;`, and c) you can omit the ProducesAttribute as the return type already specifies this. – ckuri Sep 11 '20 at 03:16

1 Answers1

0

JsonProperty is used to change the names of properties when they are serialized to JSON. So basically when you use JsonProperty attribute you response will take the names from JsonProperty but while deserialization it identifies the JsonProperty names and assigns the right value to the property. Not only postman, all the platform that displays plain response will result into results like this below

[
    {
        "properties": {
            "invoicenumber": "45293556",
            "totalsum": 1239.55,
            "issuedate": "2000-04-08T00:00:00+02:00"
        },
        "nodes": {
            "file": "https://file.pdf"
        }
    },
    {
        "properties": {
            "invoicenumber": "52095938",
            "totalsum": 989.33,
            "issuedate": "2001-08-18T00:00:00+02:00"
        },
        "nodes": {
            "file": "https://file.pdf"
        }
    },
    {
        "properties": {
            "invoicenumber": "28842180",
            "totalsum": 1504.38,
            "issuedate": "2005-06-06T00:00:00+02:00"
        },
        "nodes": {
            "file": "https://file.pdf"
        }
    }
]

JsonProperty use only if you are intended to change the property name while serializing an object. If you like to modify the property names at runtime, I have posted an answer in other question. check this Set different property name for JSON at runtime

Purushothaman
  • 519
  • 4
  • 16
  • 1
    _JsonProperty [is] used only if you are intended to change the property name while serializing an object_ - or of course when deserializing to a different name.. – stuartd Sep 11 '20 at 00:42
  • But the response from the external API has the names that i am specifing in the class, thats why I am putting the [JsonProperty] – Don Juan Sep 11 '20 at 06:39
  • Use contract resolver, you can control serialize and deserialize, see the link in my answer – Purushothaman Sep 11 '20 at 07:12