Deserializing with Json.NET: Requiring a property/key to be present

17,755

Solution 1

Ugh. I should have spend a little more time in the Json.NET documentation...

The answer is the the Required property of the JsonPropertyAttribute, which is of enum type Newtonsoft.Json.Required

[JsonProperty(Required = Newtonsoft.Json.Required.AllowNull)]
public string Description {get; set;}

Solution 2

I think you are looking for the DefaultValueAttribute http://james.newtonking.com/projects/json/help/index.html?topic=html/T_Newtonsoft_Json_DefaultValueHandling.htm

Solution 3

The real question here is: Why do you want to force the sender to set null on some values? While building an app you can never force users to behave, that's the number 1 window for hacking your app.

Always assume users wont do what you want at some point. If that JSON comes from any other app that you own just make it send null, if its an external app or user input assume anything is possible.

And Required doesn't mean the field is required in the input, it means it requires a value. That's your problem.

Share:
17,755
Kerby
Author by

Kerby

Updated on June 11, 2022

Comments

  • Kerby
    Kerby about 2 years

    When using Json.NET to deserialize a JSON string into an object, how do I require a key/property to be present in the JSON stirng, but allow for NULL values?

    For example:

    Lets say I have a class/object...

    [DataContract]
    public class Car
    {
        [DataMember(IsRequired = true)]
        public string Vin {get; set;}
    
        [DataMember(IsRequired = true)]
        public string Color {get; set;}
    
        public string Description {get; ;set}
    }
    

    In the above example, the VIN and Color are required, and an exception would be thrown if either one of them is missing from the JSON string. But lets say that whether or not the Description property has a value after being deserialized is optional. In other words NULL is a valid value. There are two ways to make this happen in the JSON string:

    1)

    {
        "vin": "blahblahblah7",
        "color": "blue",
        "description":  null
    }
    

    or 2)

    {
        "vin": "blahblahblah7",
        "color": "blue"
    }
    

    The problem is that I don't want to assume that the Description value should be NULL just because the key/value pair for the was left out of the JSON string. I want the sender of the JSON to be explicit about setting it to NULL. If scenario #2 were to happen, I want to detect it and respond with an error message. So how do I require the key/value pair to be present, but accept NULL as a value?

    If it helps any, I'm trying to solve this problem within the context of an ASP.NET Web API project.

  • Kerby
    Kerby about 11 years
    I understand what you're saying about users may not always do what I want. But, frankly, it's my API. I define its rules. If someone wants to use it, they play by my rules. My intention is to detect when a "required" key/value pair is missing and then kick back a 400 telling the client that it's missing a description (in this case). I also know what you mean about the [Required] attribute means that a value is required, and not that a key/value pair is required. That's why I'm asking the question in the first place.
  • Francisco Afonso
    Francisco Afonso about 11 years
    That "Is My API" thinking is not very good. I mean, users have to send null just cause you cant solve the problem? Jras gave you the answer, use default values on your side. Never force people to follow rules.
  • Kerby
    Kerby about 11 years
    I want users sending null because I don't want to make assumptions about what they're trying to do. In my experience, making assumptions can cause problems.
  • Francisco Afonso
    Francisco Afonso about 11 years
    I'm not really getting how you're thinking about that. I mean, if users dont send a field it is null... at least for you. There's no magic ball to tell you, the only one that do are the users.
  • Francisco Afonso
    Francisco Afonso about 11 years
    Maybe this is what you're thinking: You have a Car object with a description. A user send a request with no description and if you set it to null you'll lost the value. Is that it? If it is that's wrong. You have a Car object, but the info you'll receive dont need to be mapped to that object. You can just watch the values and use them as you want without updating any missing values.
  • Kerby
    Kerby about 11 years
    Yes, when a "user send a request with no description" is the scenario I'm talking about (like scenario #2 in my post). So I could assume that the value is null but, like you said, that may override a value that was previously there when that isn't what the client intended to do. Your suggestion about watching the values was a little more work than what I was hoping for, but I may not have any other options.
  • Francisco Afonso
    Francisco Afonso about 11 years
    Indeed, but work is required to achieve good results :P Also it makes perfect sense to think about one physic resource as more than one data resource. In your case you have the DB info and the User info. This last one only turns to DB after some processing like ignoring description update if its value is not set. Makes perfect sense. Good luck
  • Kerby
    Kerby about 11 years
    Thanks for your feedback Francisco. I stumbled on the solution in the Json.NET documentation (see my answer). Good news is that there is an easy way to do it!
  • Francisco Afonso
    Francisco Afonso about 11 years
    I see you found a required rule for allow null, but remember, that's one more useless parameter a user have to send, not really practical.
  • Francisco Afonso
    Francisco Afonso about 11 years
    For example, see Google APIs. The Required parameteres mean required values, null parameteres get in the optional pack. Thats cause there's server logic behind. You deserialize to a Car object and then watch the variables and process the data. Not really a big concern but important to realize what you are doing creating that kind of rules
  • jeromej
    jeromej almost 6 years
    Works on serialization but what about deserialization when all members are required by default? [DefaultValue(null)] is ignored. [JsonProperty(Required = Required.Default)] works but is wordy.
  • EKW
    EKW over 3 years
    +1. Stumbled across this, ran into a similarly poorly written API that requires that I send hundreds of properties as "null" instead of just assuming that I'm not wanting to update/change/add the data I'm not sending.