I haven't tried it out, but do try

[link:msdn.microsoft.com]

as I think perhaps the .Net 'DataContract' programming model does work with F# records, and there is a JSON serializer/deserializer for this programming model.

By on 6/24/2009 11:29 PM ()

Wow I feel sheepish -- the WCF stuff does work :\. DataContract can use fields directly, and doesn't need a specific constructor. (But a lot of APIs do need a properties and often a parameterless constructor... right?)

You'll need to add some attributes to make it work properly, as the fields have an @ prefix, and the properties aren't settable:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 

open System
open System.Runtime.Serialization

[<DataContract>]
type rectest = {
    [<field: DataMember(Name = "id")>]
    id   : int
    [<field: DataMember(Name = "name")>]
    name : string }

let dcs = Json.DataContractJsonSerializer(typeof<rectest>)
let ms = new IO.MemoryStream()
dcs.WriteObject(ms, { id = 2; name = "foo" })
printfn "%s" (ms.ToArray() |> Text.Encoding.UTF8.GetString)
ms.Seek(0L, IO.SeekOrigin.Begin) |> ignore
let r = dcs.ReadObject(ms) :?> rectest
printfn "%A" r

Awesome. We can probably stick this into a few other places and make certain frameworks (say, ASP.NET MVC) work properly too!

Thanks Brian!

By on 6/25/2009 12:11 AM ()

As a note to the F# team, it'd be nice if the F# compiler didn't create mangled names. Since F# record generated fields are assembly-access only, it shouldn't matter if they have a name matching the property name, should it? Or is there 3rd party code out there that messes up if it encounters such a type?

By on 6/25/2009 1:39 AM ()

Guys, thanks for the helpful replies!

I haven't had time to work through them yet, but will do so.

One more piece of info I should add, though:

The problem I reported occurred with September 2008 CTP. This morning I upgraded to May 2009 CTP and am getting good results with JSON.net for serialization/deserialization of nested records, where records contain simple scalar types and / or nested arrays or ResizeArrays (= System.Collections.Generic.List). JSON.net will serialize F# lists no problem, but cannot deserialise.

Now, I just have to see if I can figure out how to marshal some kind of dictionary / map in and out. Guessing will have to go with the regular dot net Dictionary<k,v> for this.

Once again, thx for the responses!

By on 6/25/2009 2:43 AM ()

Yea, fine control over what IL F# emits can be annoying when dealing with certain libraries that make certain assumptions :). Most libraries just expect all code to be like C# would generate it (this gets really nasty with expression trees).

When doing object interop with serialization frameworks, you might need to just use the F# OO types. With these, you can generate constructors or read/write properties as you see fit. I agree though, it sucks since record types are a lot nicer to deal with.

If you really wanted to use records, you could use F# reflection and hack something up to generate a type that looks like whatever the framework expects. Pass that type in, then pop it out to a record automatically. Won't work for all APIs, but might work for this one.

BTW, if you go the F# OO route (which is still easier than using C# and doing interop), here's how it'd look:

1
2
3
4
5
6
7
8
9
 

type FooReadWrite() =
    let mutable field1 = ""
    member x.Field1 with get() = field1 and set(v) = field1 <- v
    
type FooReadOnly(field1: string) = 
    member x.Field1 = field1
By on 6/24/2009 10:45 PM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper