views:

68

answers:

2

Hello!

I'm trying to serialize "vector" (Microsoft.FSharp.Math) type. And I get that error:

Exception Details: System.Runtime.Serialization.SerializationException: Type 'Microsoft.FSharp.Math.Instances+FloatNumerics@115' with data contract name 'Instances.FloatNumerics_x0040_115:http://schemas.datacontract.org/2004/07/Microsoft.FSharp.Math' is not expected. Add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.

I have tried to put KnownType attribute and some other stuff, but nothing helps!

Could someone know the answer? This is the code I use:

// [< KnownType( typeof<vector> ) >]
type MyType = vector             

let public writeTest =
    let aaa = vector [1.1;2.2]
    let serializer = new DataContractJsonSerializer( typeof<MyType> )
    let writer = new StreamWriter( @"c:\test.txt" )
    serializer.WriteObject(writer.BaseStream, aaa)
    writer.Close()   
+5  A: 

I think that F# vector type doesn't provide all the necessary support for JSON serialization (and is quite a complex type internally). Perhaps the best thing to do in your case would be to convert it to an array and serialize the array (which will also definitely generate shorter and more efficient JSON).

The conversion is quite straightforward:

let aaa = vector [1.1;2.2] 
let arr = Array.ofSeq aaa // Convert vector to array

// BTW: The 'use' keyword behaves like 'using' in C#
use writer = new StreamWriter( @"c:\test.txt" ) 
let serializer = new DataContractJsonSerializer() 
serializer.WriteObject(writer.BaseStream, aaa) 

To convert the array back to vector, you can use Vector.ofSeq (which is a counterpart to Array.ofSeq used in the example above).

Tomas Petricek
Good point and pure, but what if the vector is part of larger structure and I want to serialize whole structure and not field by field?
The_Ghost
+4  A: 

You can also use:

let v = vector [1.;3.];
let vArr = v.InternalValues

to get the internal array of the vector. In this way, you don't need to create a temporary array.

Types, RowVector, Matrix also has this method to get the internal arrays.

Yin Zhu
Good point! But it is more like a hack.
The_Ghost