ASP.Net: isSpecified convention for JSON

André Nobrega 1 Reputation point
2021-02-11T11:53:26.12+00:00

I have an ASP.Net webservice, that uses XML as the input and output format for its API.
I am using the PropertySpecified convention. If, for example, my XML contains a <FirstName> tag, my POCO will contain that tag's value, and the POCO's FirstNameSpecified property will be "true".

Now I'm trying to add support for JSON input as well, but there seems to be a problem with the Specified properties.
I added the following formatter to WebApiConfig.cs:

config.Formatters.Add(new System.Net.Http.Formatting.JsonMediaTypeFormatter());
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.DefaultContractResolver();

JSON objects will be serialized, and the values of the explicitely specified fields will be correctly mapped to my POCO.
The "specified" properties, however, only work correctly for simple types (strings, integers, etc). Complex objects will always have their respective "isSpecified" property set to false.

For example, if I make a PUT call, with the following JSON in the request body:

{
"ID": "abc123",
"Person": {
"FirstName": "John",
"LastName": "Doe"
}}

... my POCO will have the following properties:

ID = "abc123";
IDSpecified = true;
Person = Person;
PersonSpecified = false;
Person.FirstName = "John";
Person.FirstNameSpecified = true;
Person.LastName = "Doe";
Person.LastNameSpecified = true;

Note that this only seems to happen when serializing JSON in ASP.Net, through the default JsonMediaTypeFormatter, that kicks in before your request reaches the controller. If you serialize JSON into an object anywhere else, using JsonConvert, the Specified properties are set as expected (https://dotnetfiddle.net/Iyry36)

Is there some parameter I'm missing for the JSON formatter, or am I doing something wrong?

ASP.NET API
ASP.NET API
ASP.NET: A set of technologies in the .NET Framework for building web applications and XML web services.API: A software intermediary that allows two applications to interact with each other.
298 questions
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Yihui Sun-MSFT 801 Reputation points
    2021-02-12T06:27:41.723+00:00

    Hi @André Nobrega ,

    If you don't set the value of PersonSpecified, its value is false by default.
    You can click on the link about: JSON Media-Type Formatter.
    ▶Edit◀

    I find it strange that I don't need to set the value of "IdSpecified", "FirstNameSpecified" or "LastNameSpecified".
    Complex objects will always have their respective "isSpecified" property set to false.

    ✦As I mentioned earlier, even if you do not make any assignments, the default value of the bool type will be set to false.
    ✦Do you want to not set the default value -false for the bool type?In this case, you can use a nullable value type.

     public bool? DetailsSpecified { get; set; }  
    

    However, if you do not manually assign the value this way, it will still set the default value to null.

    Now I'm trying to add support for JSON input as well

    ✦Web API includes JsonMediaTypeFormatter class that handles JSON format.
    ✦Regarding the above mentioned link (JSON Media-Type Formatter):
    JSON formatter can be configured in WebApiConfig class. You can customize JSON serialization using the JsonMediaTypeFormatter class.


    If the answer is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.
    Best Regards,
    YihuiSun

    0 comments No comments

  2. André Nobrega 1 Reputation point
    2021-02-12T09:24:35.607+00:00

    Hello @Yihui Sun-MSFT , thanks for the reply.

    I find it strange that I don't need to set the value of "IdSpecified", "FirstNameSpecified" or "LastNameSpecified". They will correctly show if their respective counterparts are in the JSON or not, without me having to explicitly declare it.

    Is there a reason why this works for simple objects, but not for complex objects? I looked through the article you linked, but I didn't see anything about the IsSpecified convention.