Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Camel-Casing Issue with Web API Using JSON.Net

I would like to return camel-cased JSON data using Web API. I inherited a mess of a project that uses whatever casing the previous programmer felt like using at the moment (seriously! all caps, lowercase, pascal-casing & camel-casing - take your pick!), so I can't use the trick of putting this in the WebApiConfig.cs file because it will break the existing API calls:

// Enforce camel-casing for the JSON objects being returned from API calls.
config.Formatters.OfType<JsonMediaTypeFormatter>().First().SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();

So I'm using a custom class that uses the JSON.Net serializer. Here is the code:

using System.Web.Http;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

public class JsonNetApiController : ApiController
{
    public string SerializeToJson(object objectToSerialize)
    {
        var settings = new JsonSerializerSettings
        {
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        };

        if (objectToSerialize != null)
        {
            return JsonConvert.SerializeObject(objectToSerialize, Formatting.None, settings);
        }

        return string.Empty;
    }
}

The problem is that the raw data returned looks like this:

"[{\"average\":54,\"group\":\"P\",\"id\":1,\"name\":\"Accounting\"}]"

As you can see, the backslashes mess things up. Here is how I'm calling using the custom class:

public class Test
{
    public double Average { get; set; }
    public string Group { get; set; }
    public int Id { get; set; }
    public string Name { get; set; }
}

public class SomeController : JsonNetApiController
{
    public HttpResponseMessage Get()

    var responseMessage = new List<Test>
    {
        new Test
        {
            Id = 1,
            Name = "Accounting",
            Average = 54,
            Group = "P",
        }
    };

    return Request.CreateResponse(HttpStatusCode.OK, SerializeToJson(responseMessage), JsonMediaTypeFormatter.DefaultMediaType);

}

What can I do differently to get rid of the backslashes? Is there an alternative way to enforcing camel-casing?

like image 965
Halcyon Avatar asked May 06 '14 21:05

Halcyon


People also ask

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);

How do you turn off or handle Camelcasing in JSON response in asp net core?

You have to change the DefaultContractResolver which uses camelCase by default. Just set the NamingStatergy as null . This should be done in the StartUp.

What is camel case example?

Meaning of camel case in English. the use of a capital letter to begin the second word in a compound name or phrase, when it is not separated from the first word by a space: Examples of camel case include "iPod" and "GaGa".

What is serialization in Web API?

Within the application memory, the state of an object resides in complicated data structures which is unsuitable for storage or exchange over the network. So, serialization converts the object into a shareable format. With serialization, we can transfer objects: Between client and server via REST APIs or GRPC.


2 Answers

Thanks to all the references to other Stackoverflow pages, I'm going to post three solutions so anyone else having a similar issue can take their pick of the code. The first code example is one that I created after looking at what other people were doing. The last two are from other Stackoverflow users. I hope this helps someone else!

// Solution #1 - This is my solution. It updates the JsonMediaTypeFormatter whenever a response is sent to the API call.
// If you ever need to keep the controller methods untouched, this could be a solution for you.
using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Web.Http;
using Newtonsoft.Json.Serialization;

public class CamelCasedApiController : ApiController
{
    public HttpResponseMessage CreateResponse(object responseMessageContent)
    {
        try
        {
            var httpResponseMessage = Request.CreateResponse(HttpStatusCode.OK, responseMessageContent, JsonMediaTypeFormatter.DefaultMediaType);
            var objectContent = httpResponseMessage.Content as ObjectContent;

            if (objectContent != null)
            {
                var jsonMediaTypeFormatter = new JsonMediaTypeFormatter
                {
                    SerializerSettings =
                    {
                        ContractResolver = new CamelCasePropertyNamesContractResolver()
                    }
                };

                httpResponseMessage.Content = new ObjectContent(objectContent.ObjectType, objectContent.Value, jsonMediaTypeFormatter);
            }

            return httpResponseMessage;
        }
        catch (Exception exception)
        {
            return Request.CreateResponse(HttpStatusCode.InternalServerError, exception.Message);
        }
    }
}

The second solution uses an attribute to decorate the API controller method.

// http://stackoverflow.com/questions/14528779/use-camel-case-serialization-only-for-specific-actions
// This code allows the controller method to be decorated to use camel-casing. If you can modify the controller methods, use this approach.
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Web.Http.Filters;
using Newtonsoft.Json.Serialization;

public class CamelCasedApiMethodAttribute : ActionFilterAttribute
{
    private static JsonMediaTypeFormatter _camelCasingFormatter = new JsonMediaTypeFormatter();

    static CamelCasedApiMethodAttribute()
    {
        _camelCasingFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
    }

    public override void OnActionExecuted(HttpActionExecutedContext httpActionExecutedContext)
    {
        var objectContent = httpActionExecutedContext.Response.Content as ObjectContent;
        if (objectContent != null)
        {
            if (objectContent.Formatter is JsonMediaTypeFormatter)
            {
                httpActionExecutedContext.Response.Content = new ObjectContent(objectContent.ObjectType, objectContent.Value, _camelCasingFormatter);
            }
        }
    }
}

// Here is an example of how to use it.
[CamelCasedApiMethod]
public HttpResponseMessage Get()
{
    ...
}

The last solution uses an attribute to decorate the entire API controller.

// http://stackoverflow.com/questions/19956838/force-camalcase-on-asp-net-webapi-per-controller
// This code allows the entire controller to be decorated to use camel-casing. If you can modify the entire controller, use this approach.
using System;
using System.Linq;
using System.Net.Http.Formatting;
using System.Web.Http.Controllers;
using Newtonsoft.Json.Serialization;

public class CamelCasedApiControllerAttribute : Attribute, IControllerConfiguration
{
    public void Initialize(HttpControllerSettings httpControllerSettings, HttpControllerDescriptor httpControllerDescriptor)
    {
        var jsonMediaTypeFormatter = httpControllerSettings.Formatters.OfType<JsonMediaTypeFormatter>().Single();
        httpControllerSettings.Formatters.Remove(jsonMediaTypeFormatter);

        jsonMediaTypeFormatter = new JsonMediaTypeFormatter
        {
            SerializerSettings =
            {
                ContractResolver = new CamelCasePropertyNamesContractResolver()
            }
        };

        httpControllerSettings.Formatters.Add(jsonMediaTypeFormatter);
    }
}

// Here is an example of how to use it.
[CamelCasedApiController]
public class SomeController : ApiController
{
    ...
}
like image 136
Halcyon Avatar answered Oct 20 '22 18:10

Halcyon


If you want to set it globally you can just remove the current Json formatter from the HttpConfiguration and replace it with your own.

public static void Register(HttpConfiguration config)
{
    config.Formatters.Remove(config.Formatters.JsonFormatter);

    var serializer = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() };
    var formatter = new JsonMediaTypeFormatter { Indent = true, SerializerSettings =  serializer };
    config.Formatters.Add(formatter);
}
like image 28
Rikard Avatar answered Oct 20 '22 18:10

Rikard