Search code examples
c#.netjsonf#datacontract

DataContract / JsonSerializer '@' appended to variable names


For some reason when I serialize a type (f#):

type JsonKeyValuePair<'T, 'S> =  {
    [<DataMember>] 
    mutable key : 'T
    [<DataMember>] 
    mutable value : 'S
}

let printJson() = 

    use stream = new MemoryStream() 
    use reader = new System.IO.StreamReader(stream)

    let o = {key = "a"; value = 1 }
    let jsonSerializer = Json.DataContractJsonSerializer(typeof<TestGrounds.JsonKeyValuePair<string, int>>)

    jsonSerializer.WriteObject (stream , o)
    stream.Seek(int64 0, SeekOrigin.Begin) |> ignore 

    printfn <| Printf.TextWriterFormat<unit>(reader.ReadToEnd())
    ()

It generates a string:

{"key@":"a","value@":1}

and if I attempt to deserialze it without the @ sign:

let deserialize() = 
    let json = "{\"key\":\"b\",\"value\":2}"
    let o  = deserializeString<TestGrounds.JsonKeyValuePair<string, int>> json
    ()

{"The data contract type 'TestGrounds.JsonKeyValuePair`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]' cannot be deserialized because the required data members 'key@, value@' were not found."}

However put the @ back in:

let run2 () = 
    let json = "{\"key@\":\"b\",\"value@\":2}"
    let o  = deserializeString<TestGrounds.JsonKeyValuePair<string, int>> json
    ()

and we are all good. As far ask i know there is no reference to @ in the Json Spec (http://www.json.org/)...


Solution

  • F# generates fields called key@ and value@ to back the properties called key and value. Try putting a DataContract attribute on your record type - without it the serializer will ignore the DataMember attributes and appears to just write out every field.