KevinDockx / JsonPatch

JSON Patch (JsonPatchDocument) RFC 6902 implementation for .NET
MIT License
173 stars 29 forks source link

Does JsonPatchDocument require additional codes to deserialize properly? #40

Closed funchiat closed 8 years ago

funchiat commented 8 years ago

HTTPPatch document via a hand typed JSON format has been accepted via Fiddler [{"value":false,"path":"/isapprovalaccepted","op":"replace"}]

But, inside my .NET project, JsonConvert deserialize the document into format {"Operations":[{"OperationType":2,"value":false,"path":"/isapprovalaccepted","op":"replace"}]}

Which, patch document passed as null into my controller and causes exception. [HttpPatch] public IHttpActionResult Patch(int ID, [FromBody]JsonPatchDocument patchData) patchData.ApplyTo(approvalItemUpdate); // exception here

My question is, how can I serialize/deserialize correctly? using Marvin.JsonPatch; using Newtonsoft.Json; JsonPatchDocument patchDoc = new JsonPatchDocument(); patchDoc.Replace(b => b.IsApprovalAccepted, false); var serializedItemToUpdate = JsonConvert.SerializeObject(patchDoc);

'ProjekApproval' type is actual model in Entity Framework where IsApprovalAccepted is boolean

funchiat commented 8 years ago

public IHttpActionResult Patch(int ID, JObject patchData) Yes parse into JObject is {{ "Operations": [ { "OperationType": 2, "value": false, "path": "/isapprovalaccepted", "op": "replace" } ] }}

public IHttpActionResult Patch(int ID, [FromBody]JsonPatchDocument patchData)

null

Runtime version from client and API are both v4.0.30319

I need to figure out what to do

KevinDockx commented 8 years ago

Hi,

Have a look at the unit tests in the source code for a ton of examples - you'll notice that when serializing, the "Operations" property is removed from the result.

One thing I do notice in your code: you're trying to deserialize to a non-generic JsonPatchDocument. Maybe you can try having your Patch method at API level accept the correctly typed version?

If all else fails, feel free to send me a demo project - I'll have a look :)

funchiat commented 8 years ago

oh no no there is a generic class to JsonPatchDocument

Try typing this without spaces in this github comment textbox and the projekapproval generic will poof/dissappear

Here's the right signature where JsonPatchDocument does have generic class that matches client. [FromBody]JsonPatchDocument < ProjekApproval > patchData)

This line of code works JsonPatchDocument orderWrapper = JsonConvert.DeserializeObject< JsonPatchDocument < ProjekApproval > >( "[{\"value\": false, \"path\": \"isapprovalaccepted\",\"op\": \"replace\"}]");

So I will look at the unit tests to see how this can be done somehow with custom converter

funchiat commented 8 years ago

Thanks for your suggestion to check out the source project. The codes were straightforward I could not understand what could go wrong internally, at first. Later, I suspect some versioning issue. I do not know the exact cause but I resolved the issue via reinstallation.

First, I downloaded entire fresh source from my source control. In fact, old project referenced in original question in this post can no longer start . Some error Method not found: 'Void Newtonsoft.Json.Serialization.DefaultContractResolver.set_IgnoreSerializableAttribute(Boolean)'. I am going to delete the whole folder later.

I update the package Newtonsoft from version 6 to version 8 inside Marvin.Json project here in GitHub. Compile and rebuild. Copy output Marvin.JsonPatch.dll library into my other project \bin folder and reference it manually via Add-Reference. This means, I did not attempt NuGet the latest Marvin here. This main project here is the one that use JsonConvert on patchDoc.

Marvin.JsonPatch.JsonPatchDocument < ProjekApproval > patchDoc = new Marvin.JsonPatch.JsonPatchDocument < ProjekApproval > (); patchDoc.Replace(b = > b.IsApprovalAccepted, false); var serializedItemToUpdate = JsonConvert.SerializeObject(patchDoc);

In this main project, I NuGet the latest Newtonsoft version 6 into version 8 as well, just like how I did for Marvin.JsonPatch project earlier.

Back in my web api project, public IHttpActionResult Patch(int ID, [FromBody]JsonPatchDocument < ProjekApproval > patchData) is no longer null. There are no fixes needed here

In my old codes, I started with NuGet latest Newtonsoft.Json and latest Marvin.JsonPatch. However, Marvin.JsonPatch comes default old version of Newtonsoft.Json internally.

Do you think that could be potential cause?

KevinDockx commented 8 years ago

Glad to read it worked out :) By default, Marvin.JsonPatch requires an older version indeed, but newer versions should still work. Hard to say what exactly the problem was... :( One thing I can think about: when you're working with different versions of external libraries (like Json.NET) and upgrade/downgrade via NuGet, always check the web.config files: they may contain assembly redirects that aren't automatically adjusted/deleted when changing the version.

funchiat commented 8 years ago

Maybe the exception/problem was rooted in Newtonsoft. So the code has something like try { .... ... } catch { //do nothing }

Finally, just kidding ;)

Actually if I go into step by step debug from old (but corrupted) main project, I notice using Newtonsoft.Json; //is version 8 var serializedItemToUpdate = JsonConvert.SerializeObject(patchDoc);

using Newtonsoft.Json; // but is version 6 here In next line debugger steps into TypedJsonPatchDocumentConverter in MarvinJson.Patch public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)

I wonder the compiler override/resolves into which version