mbraceproject / FsPickler

A fast multi-format message serializer for .NET
http://mbraceproject.github.io/FsPickler/
MIT License
324 stars 52 forks source link

ISO8601 string unpickle gives unable to cast object of type 'DateTime' to type 'String'. #68

Closed philderbeast closed 8 years ago

philderbeast commented 8 years ago
#r "../packages/FsPickler/lib/net45/FsPickler.dll"
#r "../packages/FsPickler.Json/lib/net45/FsPickler.Json.dll"

fsi.PrintLength <- 1000
fsi.PrintWidth <- 1000

open System
open Nessos.FsPickler.Json

let json = FsPickler.CreateJsonSerializer(indent = true)

type GenericRecord<'T> = { GValue : 'T }
type GenericRecordAsString = GenericRecord<string>

let a0 = json.PickleToString<string>("a")
let a0' = json.UnPickleOfString<string>(a0)

let a1 = json.PickleToString<GenericRecordAsString>({ GValue = "a" })
let a1' = json.UnPickleOfString<GenericRecordAsString>(a1)

let b0 = json.PickleToString<string>("2013-10-30T16:00:00")
let b0' = json.UnPickleOfString<string>(b0)

let b1 = json.PickleToString<GenericRecordAsString>({ GValue = "2013-10-30T16:00:00" })
let b1' = json.UnPickleOfString<GenericRecordAsString>(b1)

In the above, the string -> a -> a' pickle (string -> a) and unpickle (a -> a') conversions work as does the ISO 8601 string -> b pickle but the b -> b' unpickle fails with the exception ...

Nessos.FsPickler.FsPicklerException: Error deserializing object of type 'System.String'. ---> System.InvalidCastException: Unable to cast object of type 'System.DateTime' to type 'System.String'

The ISO 8601 string -> b0 pickle looks good as does the ISO 8601 string -> b1 ..

val b0 : string = "{
  "FsPickler": "1.4.0",
  "type": "System.String",
  "value": "2013-10-30T16:00:00"
}"

val b1 : string = "{
  "FsPickler": "1.4.0",
  "type": "FSI_0004+GenericRecord`1[System.String]",
  "value": {
    "GValue": "2013-10-30T16:00:00"
  }
}"
eiriktsarpalis commented 8 years ago

I think this happens because JsonReader from Json.NET proactively parses the entry as DateTime based on the string content. This is further indication that we should move away from Json.NET altogether.

philderbeast commented 8 years ago

When using the JsonReader from Json.NET, after calling .Read() the .Value is of type DateTime. Is there the option of calling .ReadString() instead when reading a primitive as a string?

eiriktsarpalis commented 8 years ago

There is ReadAsString(), but for reasons that I cannot entirely remember, I chose to go for the .Value approach. I'll have a go at re-evaluating that choice.

philderbeast commented 8 years ago

Snappy turnaround time on this and good to be able to opt out of date parse handling.