F# — XmlSerializer, Record types and [CLIMutable]

I talked about the XML and JSON seri­al­iza­tion of F# types in a pre­vi­ous post, and since then F# 3.0 has been released and a new [CLIMutable] was qui­et­ly added amidst the hype sur­round­ing the awe­some type providers!

 

CLIMutable Attribute

When applied to a F# record type, the CLIMutable attribute tells the F# com­pil­er to gen­er­ate a default para­me­ter­less con­struc­tor as well as prop­er­ty get­ters and set­ters so that when work­ing with the record type from oth­er .Net lan­guages it’ll appear as a pret­ty stan­dard, muta­ble CLI type that you’d expect.

How­ev­er, when work­ing in F#, the nor­mal rules as far as record types are con­cerned still apply – immutabil­i­ty by default, pat­tern match­ing, cloning using the with key­word, etc.

For a sim­ple record type Per­son, let’s have a look at the com­pile code with and with­out the CLIMutable attribute:

image image

With­out the CLIMutable attribute, this is how the record type is nor­mal­ly com­piled:

image

With the CLIMutable attribute applied, things look a lot dif­fer­ent:

image

That’s all well and good, but why is this use­ful you might ask?

Because many seri­al­iz­ers, such as the BCL’s XmlSe­ri­al­iz­er (as well as oth­er seri­al­iz­ers avail­able in the open source space) only work with types that has a default con­struc­tor and con­tains prop­er­ty set­ters.

 

XmlSerializer and Record types

Unlike the Dat­a­Con­tract­Se­ri­al­iz­er which only requires a type to be dec­o­rat­ed with a Seri­al­iz­able or Dat­a­Con­tract attribute, the XmlSe­ri­al­iz­er on the oth­er hand, also requires the type to define a para­me­ter­less con­struc­tor.

Whilst both seri­al­iz­ers gen­er­ate XML out­puts, Dat­a­Con­tract­Se­ri­al­iz­er is intend­ed for mar­shalling data (that con­forms to a ‘con­tract’) for trans­porta­tion over the wire and there­fore less con­cerned with read­abil­i­ty of its out­put and offers lit­tle option for you to cus­tomize the gen­er­at­ed XML. It’s there­fore quite hap­py to spit out rather unread­able XML for our Per­son record type above:

 

<FSI_0004.Person xmlns=“http://schemas.datacontract.org/2004/07/”  xmlns:i=“http://www.w3.org/2001/XMLSchema-instance”><Age_x0040_>30</Age_x0040_><Name_x0040_>Yan Cui</Name_x0040_></FSI_0004.Person>

 

Mean­while, in the land of the XmlSe­ri­al­iz­er, its sole pur­pose of exis­tence is to gen­er­ate XML and offers a pla­toon of options to help ensure its out­put meets your func­tion­al and aes­thet­ic needs. By default it’ll gen­er­ate nice, indent­ed out­put for our CLIMutable ver­sion of Per­son record type:

 

<?xml version=“1.0”?>

<Per­son xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=“http://www.w3.org/2001/XMLSchema”>

  <Name>Yan Cui</Name>

  <Age>30</Age>

</Person>

 

In addi­tion, you can cus­tomize the XML out­put using the nor­mal XML-relat­ed attrib­ut­es:

image

<?xml version=“1.0”?>

<Per­son xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance” xmlns:xsd=“http://www.w3.org/2001/XMLSchema” PersonName=“Yan Cui”>

  <PersonAge>30</PersonAge>

</Person>

 

OSS Serializers

Of the OSS JSON seri­al­iz­ers I bench­mark reg­u­lar­ly, JSON.Net (v4.5.11 test­ed) works with both nor­mal and CLIMutable record types from F#. ServiceStack.Text (v3.9.37 test­ed) doesn’t work with ‘vanil­la’ record types on dese­ri­al­iza­tion (fields are left with default val­ues), but you can workaround by mak­ing the fields muta­ble or add the CLIMutable attribute to the type.

 

I hope this proves to be use­ful to you, and if like us you have a lot of C# code hang­ing around just to get pret­ty XML out of your F# record types, dare I say it’s about to throw away those C# code! Winking smile