codecutout / JsonApiSerializer

JsonApiSerializer supports configurationless serializing and deserializing objects into the json:api format (http://jsonapi.org).
MIT License
113 stars 46 forks source link

Question: JsonInputFormatter and JsonOutputFormatter #59

Closed chrisketelaar closed 6 years ago

chrisketelaar commented 6 years ago

Hi!

First off thanks for creating this library it works great!

I got a question about the implementation; Correct me if I'm wrong but from the examples I understand that, in order to use the JsonApi serialization, I need to overwrite the existing dotnet JsonInput- and JsonOutput formatters.

If I'm correct (I tested it) this means that I loose the option to do content negotiation (https://docs.microsoft.com/en-us/aspnet/core/web-api/advanced/formatting?view=aspnetcore-2.0#content-negotiation).

Is this intentionally or could I do a PR to reintroduce content negotiation?

alex-davies commented 6 years ago

The serialiser actually has almost nothing to do with jsonInput/output serialiser. Library is a configuration for json.net (JsonApiSerializerSettings extends json.net’s JsonSerializerSettings). It just so happens that the standard MVC jsonInput/output serialisers use Json.net so it is very easy to swap out the serialiser settings to allow you accept and produce json:api formats

You can do content negotiation in a very similar way, configure a json input/output serialiser using JsonApiSerializerSettings and associate it with ‘application/your-json-api-content-type’. Negotiation part is then handled by MVC

chrisketelaar commented 6 years ago

Maybe I'm missing something here, please bear with me so I can understand what is happening.

But I my case I need to be able to do content negotiation for both Json and JsonAPI (backwards compatibility) application/json should return json and application/vnd.api+json should return Json api.

If I now would swap out the standard MVC jsonInput/output formatters and put in new ones with the JsonApiSerializer settings, then I'm doing JsonApiSerialization for all supported media types, which includes application/json, registered in the standard formatters. This is the point where I lose support for content negotiation for application/json because it always returns application/vnd.api+json format.

alex-davies commented 6 years ago

The MVC pipeline has a list of OutputFormatters and each formatter has a list of supported media types. By default there is a JsonOutputFormatter that uses the standard json.net serialiser settings and is configured to be used with the media type application/json

In the readme had an example of replacing the default one with a new one that has different serialiser settings. But it is just as easy to leave the default one there and add a new one with JsonApiSerializerSettings then configure it to be used only for applicaiton/vnd.api+json

            services.AddMvc(opt => {

                //create a new formatter to handle json:api requests
                var jsonApiFormatter = new JsonOutputFormatter(new JsonApiSerializerSettings(), ArrayPool<Char>.Shared);

                //make our formatter handle ONLY `application/vnd.api+json` mediatypes
                jsonApiFormatter.SupportedMediaTypes.Clear();
                jsonApiFormatter.SupportedMediaTypes.Add("application/vnd.api+json");

                //add to list of formatters (default json formatter is still present and servicing other media types)
                opt.OutputFormatters.Add(jsonApiFormatter);
            });