2014-11-23 24 views
2

使用Newtonsoft.Json,最新的版本(6.0.6 =)我得到以下错误:Newtonsoft无法反序列化一个空的F#序列?

Cannot create and populate list type Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers+EmptyEnumerable`1[System.String]

然而,在post它宣布Newtonsoft.Json将全力支持Fsharp类型?

当我将违规类型更改为常规数组时,一切正常。

代码:

type Prescription() = 
    member val Id = "" with get, set 
    member val Status = new PrescriptionStatus() with get, set 
    member val Prescriber = new Prescriber() with get, set 
    member val Indications = [||] : string[] with get, set 

当我改变适应症为:

member val Indications = Seq.empty : string seq with get, set 

我碰上了错误。

此外,当我初始化什么是实际上是一个枚举作为一个数组,就不能构成:

member val Indications : string seq = [||] |> Array.toSeq with get, set 

回答

4

我猜的答案是,Newtonsoft.Json不完全支持F#的类型。

但是F#并没有让他们特别容易。例如,一个用Seq.empty定义的空seq不仅仅是一个IEnumerable<T>,它是一个特定的可执行实现EmptyEnumerable<T>,这似乎引发了序列化 - 很可能是因为没有合适的构造函数。从后链接到您:如果您初始化序列这样反而

To all future creators of immutable .NET collections: If your collection of T has a constructor that takes IEnumerable then Json.NET will automatically work when deserializing to your collection, otherwise you're all out of luck.

,也许行为会有所不同:

member val Indications = Seq.ofArray [||] : string seq with get, set 

但是,这是鸡蛋里挑骨头,这里实际的答案很简单 - 唐序列化序列。只需使用像数组这样的具体,行为良好的类型即可。类型越简单,在序列化或互操作时就越不容易让你头疼。

+0

谢谢,我已经尝试过,但是没有奏效。所以,我想这只是没有实现。必须切换回数组。 – halcwb 2014-11-23 19:36:58

0

我喜欢使用像数组这样的简单类型的概念,只是我想使用相同的DTO来映射到Linq查询中的IQueryable。所以,在这方面,阵列不是一种选择。幸运的是,有一些测试

,它很简单:

#load ".\Scripts\load-project.fsx" 

#time 

open System 
open System.Collections.Generic 

open Newtonsoft.Json 

[<CLIMutable>] 
type Test1 = 
    { 
     Strings : string seq 
    } 

type Test2() = 
    member val Strings = Seq.empty : IEnumerable<string> with get, set 

type Test3() = 
    member val Strings = Seq.empty : String seq with get, set 

type Test4() = 
    member val Strings : IEnumerable<string> = Seq.empty : IEnumerable<string> with get, set 

type Test5() = 
    member val Strings : IEnumerable<string> = [] |> List.toSeq : IEnumerable<string> with get, set 

type Test6() = 
    member val Strings = [] |> List.toSeq : string seq with get, set 

let test1 = { Strings = Seq.empty } 
let test2 = new Test2() 
let test3 = new Test3() 
let test4 = new Test4() 
let test5 = new Test5() 
let test6 = new Test6() 

let json1 = JsonConvert.SerializeObject(test1) 
let json2 = JsonConvert.SerializeObject(test2) 
let json3 = JsonConvert.SerializeObject(test3) 
let json4 = JsonConvert.SerializeObject(test4) 
let json5 = JsonConvert.SerializeObject(test5) 
let json6 = JsonConvert.SerializeObject(test6) 

let deserialized1 = JsonConvert.DeserializeObject<Test1>(json1) // Fails 
let deserialized2 = JsonConvert.DeserializeObject<Test2>(json2) // Fails 
let deserialized3 = JsonConvert.DeserializeObject<Test3>(json3) // Fails 
let deserialized4 = JsonConvert.DeserializeObject<Test4>(json4) // Fails 
let deserialized5 = JsonConvert.DeserializeObject<Test5>(json5) // Passes 
let deserialized6 = JsonConvert.DeserializeObject<Test5>(json6) // Passes 

所以,只要你使用具有可识别的构造函数,例如列表的类型构建你的序列,可将对象deserialised。奇怪的是,将序列初始化为一个数组,然后将其转换为一个序列,就像使用列表来排序示例(通过)一样,失败。

2

设置JsonSerializerSettings.ObjectCreationHandling = ObjectCreationHandling.Replace将解决此错误。

相关问题