The serial JSON parser creates an empty object when deserialization fails instead of null

At WebAPI, I noticed an inconsistency that messes with our validation methods. If you send a bad body / payload using POST in xml, deserialization fails, and you get a null pointer. If you send a bad body / payload to JSON, you get an empty object instead. This is misleading and I don't like it. Is there a way to force a null pointer with unsuccessful json deserialization?

UPDATE: I have no problem of deserialization. I have a behavior issue, which seems to be the difference between the DataContractSerializer and the Json.net serializer. When xml does not deserialize, the payload is zero. However, when Json does not deserialize, it seems to create an instance of the expected default payload.

An example of a bad xml payload: enter image description here

An example of the same call using a bad json payload (the payload is not null but the default instance of the payload class)

enter image description here

+5
source share
2 answers

By default, Web.API used the option MissingMemberHandling.Ignorein JsonMediaTypeFormatter.

You need to install it in MissingMemberHandling.Errorwith:

GlobalConfiguration.Configuration
   .Formatters.JsonFormatter
   .SerializerSettings.MissingMemberHandling = MissingMemberHandling.Error;

null JSON, :

{
   "somenotexistingprop": ""
}

, JSON: {}, , null. JsonConvert.DeserializeObject , JSON (. unit test github).

+4

, , , :

  • "MissingMemberHandling.Error" Json, , , . . , Xml.

  • @: "MissingMemberHandling.Error" "ModelState.IsValid", ModelState Keys, , - - .

:

public class Customer
{
    public int Id { get; set; }

    [MaxLength(5)]
    public string Name { get; set; }

    public Address Address { get; set; }
}

public class Address
{
    public string Line1 { get;set;}
}

//action
public void Post([FromBody]Customer customer)
    {
        if (!ModelState.IsValid)
        {
            ModelStateDictionary msd = new ModelStateDictionary();

            foreach (string key in ModelState.Keys)
            {
                if (ModelState[key].Errors.Count > 0)
                {
                    foreach (ModelError error in ModelState[key].Errors)
                    {
                        Exception ex = error.Exception;

                        if (ex != null 
                            && typeof(JsonSerializationException).IsAssignableFrom(ex.GetType()) 
                            && ex.Message.StartsWith("Could not find member"))
                        {
                            msd.AddModelError(key, ex);
                        }
                    }
                }
            }

            if (msd.Count > 0)
            {
                throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.BadRequest, msd));
            }
        }

        //process the supplied customer
    }
+1

All Articles