Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why won't Web API deserialize this but JSON.Net will?

How can Web API fail to deserialize an object that JSON.Net deserializes?

Visual Studio showing Web API's attempt as all nulls but JSON.Net's properly populated

This is the Web API controller:

public void Put(EditorSubmissionMainView ajaxSubmission) {
// ajaxSubmission: EditorSubmissionMainView with all values ('data' also == null)

    string json = "{\"id\":\"row_1377\",\"data\":{\"ROTATION\":\"1\",\"EQUIPMENT\":[{\"id\":\"6\"},{\"id\":\"8\"}],\"NOTES\":\"\"}}";

    EditorSubmissionMainView foo = Newtonsoft.Json.JsonConvert.DeserializeObject<EditorSubmissionMainView>(json) as EditorSubmissionMainView;
// foo is a EditorSubmissionMainView but properly deserialized.
}

This is the JSON, captured by Fiddler and formatted:

{
    "id": "row_1377",
    "data": {
        "ROTATION": "1",
        "EQUIPMENT": [{
            "id": "6"
        },
        {
            "id": "8"
        }],
        "NOTES": ""
    }
}

An example class that serializes with JSON.Net but not with a Web API controller:

[Serializable]
public class EditorSubmissionMainView
{
    public string id { get; set; }
    public EditorSubmissionMainViewData data { get; set; }
}

[Serializable]
public class EditorSubmissionMainViewData
{
    [JsonProperty("ROTATION")]
    public int? rotation { get; set; } // Same problem if everything is a string

    [JsonProperty("EQUIPMENT")]
    public ICollection<Dictionary<string, int?>> equipment { get; set; }

    [JsonProperty("NOTES")]
    public string notes { get; set; }
}

Web API uses JSON.Net, and I am not using any custom JSON formatters -- just passing the JSON to a Web API controller. Why is this not working?

EDIT: As requested, I am calling my Web API controller with this Javascript (part of JQuery DataTables). Note that I am certain the same JSON is getting to my controller regardless because I've captured the raw HTTP packet with Fiddler and ensured that it is correct:

"ajaxUrl": {
    "create": "POST @Url.Content("~/API/MainView")",
    "edit":   "PUT @Url.Content("~/API/MainView")",
    "remove": "DELETE @Url.Content("~/API/MainView")"
},

"ajax": function (method, url, data, successCallback, errorCallback) {
    $.ajax({
        "type": method,
        "url": url,
        "data": JSON.stringify(data), // Requires IE8+
        "contentType": "application/json",
        "dataType": "json",
        "success": function (json) {
            successCallback(json);
        },
        "error": function (xhr, error, thrown) {
            errorCallback(xhr, error, thrown);
        }
    });
},

The raw HTTP request follows:

PUT http://localhost:53367/API/MainView HTTP/1.1
x-requested-with: XMLHttpRequest
Accept-Language: en-us
Referer: http://localhost:53367/Manage/MainView
Accept: application/json, text/javascript, */*; q=0.01
Content-Type: application/json
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
Host: localhost:53367
Content-Length: 306
Connection: Keep-Alive
Pragma: no-cache
Cookie: ASP.NET_SessionId=wqsghjrol20cszrxfzdm0qo4

{"id":"row_1377","data":{"ROTATION":"1","EQUIPMENT":[{"id":"6"},{"id":"8"}],"NOTES":""}}
like image 475
Charles Burns Avatar asked Oct 11 '12 16:10

Charles Burns


People also ask

How do I deserialize a JSON object in Web API?

A common way to deserialize JSON is to first create a class with properties and fields that represent one or more of the JSON properties. Then, to deserialize from a string or a file, call the JsonSerializer. Deserialize method.

How does Newtonsoft JSON deserialize work?

Newtonsoft. Json uses reflection to get constructor parameters and then tries to find closest match by name of these constructor parameters to object's properties. It also checks type of property and parameters to match. If there is no match found, then default value will be passed to this parameterized constructor.

Why we use Newtonsoft JSON DLL?

The Newtonsoft. JSON namespace provides classes that are used to implement the core services of the framework. It provides methods for converting between . NET types and JSON types.


1 Answers

Try removing the [Serializable] attributes from your classes EditorSubmissionMainView and EditorSubmissionMainViewData.

like image 158
Maggie Ying Avatar answered Sep 27 '22 21:09

Maggie Ying