CamelCase JSON Formatting for NancyFX Application
As I have chosen NancyFX framework for my pet project, I’ve spend yet another week playing with it. My original expectations were - I’ll be super-duper-fast with it, since it’s so comprehensive and powerful. One more time I have to admit - every technology has it’s learning curve, it could be smooth, but it is still curve. Time need to be invested to learn it.
The good thing, it’s very interesting to fight new challenges, and it’s so cool that Nancy just “does not contain everything”, but actually allows to customize things, as you wish to.
Nancy’s default JSON formatter
Nancy is using Marek Habersack’s version JsonSerializer, which is a smart wrapper on JavaScriptSerializer. It works, fine.. but the problem, it does not provide any facilities to change default formatting settings. That would mean, if you have a module with method like that,
public class SitesModule : NancyModule
{
public SitesModule() : base("/api/sites")
{
Get["/"] = parameters => Response.AsJson(new[] {new { Name = "Site 1", DeployStatus = "Deployed" }});
}
}
You will get valid JSON, but it would serialize all C# properties, as they are:
"[{"Name":"Site 1","DeployStatus":"Deployed "}]"
Don’t know about you, but it makes me sick too work with uppercase object fields in JavaScript. Fortunately, such advanced JavaScript serialization libraries as JSON.NET has formatting features. So, our goal is to create custom serialize (based on JSON.NET) and integrate it to Nancy’s pipeline.
JSON.NET based serialization
In order to do that, we need to implement special interface (guess it’s name?) - ISerializer
. Without further explanation, I just copy and paste code here:
public class JsonNetSerializer : ISerializer
{
private readonly JsonSerializer _serializer;
public JsonNetSerializer()
{
var settings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
_serializer = JsonSerializer.Create(settings);
}
public bool CanSerialize(string contentType)
{
return contentType == "application/json";
}
public void Serialize<TModel>(string contentType, TModel model, Stream outputStream)
{
using (var writer = new JsonTextWriter(new StreamWriter(outputStream)))
{
_serializer.Serialize(writer, model);
writer.Flush();
}
}
}
Changing the configuration
NancyFX bootstrapper has a special method, which have to be overridden in order to change internal configuration. There is a very convenient helper, that is useful for changing some particular bits of config.
protected override NancyInternalConfiguration InternalConfiguration
{
get
{
return NancyInternalConfiguration.WithOverrides(c => c.Serializers.Insert(0, typeof(JsonNetSerializer)));
}
}
Please note, I’m inserting that to position 0, just to make sure it’s *before* default JsonSerializer
type, since AsJson() response formatter is using FirstOrDefault
strategy to find corresponding serialize class. Just build and re-start your app, and from now your JSON’s would be looking really good:
"[{"name":"Site 1","deployStatus":"Deployed "}]"
Much more better now!
As I have chosen NancyFX framework for my pet project, I’ve spend yet another week playing with it. My original expectations were - I’ll be super-duper-fast with it, since it’s so comprehensive and powerful. One more time I have to admit - every technology has it’s learning curve, it could be smooth, but it is still curve. Time need to be invested to learn it.
The good thing, it’s very interesting to fight new challenges, and it’s so cool that Nancy just “does not contain everything”, but actually allows to customize things, as you wish to.
Nancy’s default JSON formatter
Nancy is using Marek Habersack’s version JsonSerializer, which is a smart wrapper on JavaScriptSerializer. It works, fine.. but the problem, it does not provide any facilities to change default formatting settings. That would mean, if you have a module with method like that,
public class SitesModule : NancyModule { public SitesModule() : base("/api/sites") { Get["/"] = parameters => Response.AsJson(new[] {new { Name = "Site 1", DeployStatus = "Deployed" }}); } }
You will get valid JSON, but it would serialize all C# properties, as they are:
"[{"Name":"Site 1","DeployStatus":"Deployed "}]"
Don’t know about you, but it makes me sick too work with uppercase object fields in JavaScript. Fortunately, such advanced JavaScript serialization libraries as JSON.NET has formatting features. So, our goal is to create custom serialize (based on JSON.NET) and integrate it to Nancy’s pipeline.
JSON.NET based serialization
In order to do that, we need to implement special interface (guess it’s name?) - ISerializer
. Without further explanation, I just copy and paste code here:
public class JsonNetSerializer : ISerializer { private readonly JsonSerializer _serializer; public JsonNetSerializer() { var settings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }; _serializer = JsonSerializer.Create(settings); } public bool CanSerialize(string contentType) { return contentType == "application/json"; } public void Serialize<TModel>(string contentType, TModel model, Stream outputStream) { using (var writer = new JsonTextWriter(new StreamWriter(outputStream))) { _serializer.Serialize(writer, model); writer.Flush(); } } }
Changing the configuration
NancyFX bootstrapper has a special method, which have to be overridden in order to change internal configuration. There is a very convenient helper, that is useful for changing some particular bits of config.
protected override NancyInternalConfiguration InternalConfiguration { get { return NancyInternalConfiguration.WithOverrides(c => c.Serializers.Insert(0, typeof(JsonNetSerializer))); } }
Please note, I’m inserting that to position 0, just to make sure it’s *before* default JsonSerializer
type, since AsJson() response formatter is using FirstOrDefault
strategy to find corresponding serialize class. Just build and re-start your app, and from now your JSON’s would be looking really good:
"[{"name":"Site 1","deployStatus":"Deployed "}]"
Much more better now!