Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set JSON CamelCase per Web API request

Web API uses the Json.Net formatter to serialise its JSON responses which allows you to customise the format of the generated JSON very easily for the entire application at startup using:

config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();

This allows you resolve the issues between C# syntax preferring PascalCase and javascript based clients preferring camelCase. However setting this globally on the API without taking into consideration who the client request is actually coming from seems to assume that an API will only have 1 type of client and whatever you set for your API is just the way it has to be.

With multiple client types for my API's (javascript, iOS, Android, C#), I'm looking for a way to set the Json.Net SerializerSettings per request such that the client can request their preferred format by some means (perhaps a custom header or queryString param) to override the default.

What would be the best way to set per-request Json.Net SerializerSettings in Web API?

like image 429
Casey Avatar asked Nov 02 '15 08:11

Casey


People also ask

Should I use camelCase in JSON?

Use camel case for all JSON property names The camel case property naming policy: Applies to serialization and deserialization.

Should JSON be camelCase or Pascal case?

While lowerCamelCase and snake_case might be the two most popular formats for JSON object keys, some programming languages might have different conventions. For example, C# uses PascalCase for property names, and it's common for C# APIs to return JSON in this format.

Which line of code can you use to format JSON data in camel case?

If you want JsonSerializer class to use camel casing you can do the following: var options = new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy. CamelCase }; string json = JsonSerializer. Serialize(empList, options); return Ok(json);

What is Camelcasepropertconamescontractresolver?

CamelCasePropertyNamesContractResolver Class. Resolves member mappings for a type, camel casing property names.


1 Answers

With a bit of help from Rick Strahl's blog post on creating a JSONP media type formatter, I have come up with a solution that allows the API to dynamically switch from camelCase to PascalCase based on the client request.

Create a MediaTypeFormatter that derives from the default JsonMediaTypeFormatter and overrides the GetPerRequestFormatterInstance method. This is where you can implement your logic to set your serializer settings based on the request.

public class JsonPropertyCaseFormatter : JsonMediaTypeFormatter
{
    private readonly JsonSerializerSettings globalSerializerSettings;

    public JsonPropertyCaseFormatter(JsonSerializerSettings globalSerializerSettings)
    {
        this.globalSerializerSettings = globalSerializerSettings;
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/javascript"));
    }

    public override MediaTypeFormatter GetPerRequestFormatterInstance(
        Type type,
        HttpRequestMessage request,
        MediaTypeHeaderValue mediaType)
    {
        var formatter = new JsonMediaTypeFormatter
        {
            SerializerSettings = globalSerializerSettings
        };

        IEnumerable<string> values;

        var result = request.Headers.TryGetValues("X-JsonResponseCase", out values)
            ? values.First()
            : "Pascal";

        formatter.SerializerSettings.ContractResolver = 
            result.Equals("Camel", StringComparison.InvariantCultureIgnoreCase)
                ? new CamelCasePropertyNamesContractResolver()
                : new DefaultContractResolver();

        return formatter;
    }
}

Note that I take a JsonSerializerSettings argument as a constructor param so that we can continue to use WebApiConfig to set up whatever other json settings we want to use and have them still applied here.

To then register this formatter, in your WebApiConfig:

config.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new StringEnumConverter());
config.Formatters.JsonFormatter.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
config.Formatters.JsonFormatter.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Local;

config.Formatters.Insert(0,
    new JsonPropertyCaseFormatter(config.Formatters.JsonFormatter.SerializerSettings));

Now requests that have a header value of X-JsonResponseCase: Camel will receive camel case property names in the response. Obviously you could change that logic to use any header or query string param you like.

like image 138
Casey Avatar answered Nov 15 '22 10:11

Casey