Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F#, Json.NET 6.0 and WebApi - serialization of record types

Json.NET 6.0.1 adds F# support for records and discriminated unions. When serializing a F# record type using Json.NET I now get nicely formatted JSON.

The serialization is done as follow:

let converters = [| (new StringEnumConverter() :> JsonConverter) |]
JsonConvert.SerializeObject(questionSet, Formatting.Indented, converters)

However, when I try to expose my F# types through a ASP.NET WebApi 5.0 service, written in C#, the serialized JSON includes an @-sign infront of all properties. The @-sign comes from the internal backing field for the record type (this used to be a known problem with Json.Net and F#).

But - since I'm using the updated version of Json.NET, shouldn't the result be the same as when calling JsonConvert? Or is JsonConvert behaving differently than JsonTextWriterand JsonTextReader?

As far as I can tell from reading the JsonMediaTypeFormatter in the WebApi source JsonTextWriterand JsonTextReader is used by WebApi.

like image 643
Jonas Follesø Avatar asked Apr 01 '14 14:04

Jonas Follesø


2 Answers

You can adorn your records with the [<CLIMutable>] attribute:

[<CLIMutable>]
type MyDtr = {
    Message : string
    Time : string }

That's what I do.


For nice XML formatting, you can use:

GlobalConfiguration.Configuration.Formatters.XmlFormatter.UseXmlSerializer <- true

For nice JSON formatting, you can use:

config.Formatters.JsonFormatter.SerializerSettings.ContractResolver <-
    Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver()
like image 160
Mark Seemann Avatar answered Nov 07 '22 10:11

Mark Seemann


I believe it's because the backing fields that are emitted by F# records don't follow the same naming convention as C# property backing fields.

The easiest way I've found to get around this is to change the ContractResolver at the startup of your web application from the System.Net.Http.Formatting.JsonContractResolver to use the Newtonsoft.Json.Serialization.DefaultContractResolver instead: -

Formatters.JsonFormatter.SerializerSettings.ContractResolver <- DefaultContractResolver()

You'll then get all JSON formatting done via Newtonsoft's JSON formatter rather than the NET one.

like image 40
Isaac Abraham Avatar answered Nov 07 '22 09:11

Isaac Abraham