使用Microsoft.FSharpLu将JSON序列化为流

时间:2017-02-01 15:47:28

标签: json serialization f#

我一直在使用Newtonsoft.JsonNewtonsoft.Json.Fsharp库来创建新的JSON序列化程序并流式传输到文件。我喜欢流式传输到文件的能力,因为我正在处理大型文件,并且在流式传输之前,经常会遇到内存问题。

我使用简单的fx流式传输:

open Newtonsoft.Json
open Newtonsoft.Json.FSharp 
open System.IO

let writeToJson (path: string) (obj: 'a) : unit =
    let serialized = JsonConvert.SerializeObject(obj)
    let fileStream = new StreamWriter(path)
    let serializer = new JsonSerializer()

    serializer.Serialize(fileStream, obj)

    fileStream.Close()

这很有效。我的问题是,JSON字符串绝对是我不需要的东西。例如,

let m = 
    [
        (1.0M, None)
        (2.0M, Some 3.0M)
        (4.0M, None)
    ]

let makeType (tup: decimal * decimal option) = {FieldA = fst tup; FieldB = snd tup}

let y = List.map makeType m

Default.serialize y

val it : string =
  "[{"FieldA": 1.0},
    {"FieldA": 2.0,
     "FieldB": {
        "Case": "Some",
        "Fields": [3.0]
    }},
    {"FieldA": 4.0}]"

如果将其写入JSON并读入R,则会嵌套数据框,并且与Fields相关联的任何Case最终都是list 1}}:

library(jsonlite)
library(dplyr)

q <- fromJSON("default.json")

x <- 
    q %>%
    flatten()

x

> x
  FieldA FieldB.Case FieldB.Fields
1      1        <NA>          NULL
2      2        Some             3
3      4        <NA>          NULL
> sapply(x, class)
       FieldA   FieldB.Case FieldB.Fields 
    "numeric"   "character"        "list"

我不想在R中处理这些事情。我可以做到,但它很烦人,如果有很多很多列的文件,那就太傻了。

今天早上,我开始查看Microsoft.FSharpLu.Json documentation。该库具有Compact.serialize功能。快速测试表明,此库将消除对嵌套数据框和与listCase列相关联的Field的需求。例如:

Compact.serialize y

val it : string =
  "[{
    "FieldA": 1.0
    },
  {
    "FieldA": 2.0,
    "FieldB": 3.0
  },
  {
    "FieldA": 4.0
  }
  ]"

将此字符串读入R

q <- fromJSON("compact.json")

x <- q
x
> x
  FieldA FieldB
1      1     NA
2      2      3
3      4     NA
> sapply(x, class)
   FieldA    FieldB 
"numeric" "numeric

这在R.处理起来要简单得多,我想开始使用这个库。

但是,我不知道是否可以将Compact序列化程序序列化为流。我看到.serializeToFile.desrializeStream.tryDeserializeStream,但没有任何可以序列化为流的内容。有谁知道Compact是否可以处理写入流?我怎样才能做到这一点?

1 个答案:

答案 0 :(得分:2)

FSharpLu.Json中的Compact模块缺少序列化为流的帮助程序,但您应该可以通过遵循C#示例来实现 http://www.newtonsoft.com/json/help/html/SerializingJSON.htm。一些事情:

let writeToJson (path: string) (obj: 'a) : unit =
    let serializer = new JsonSerializer()
    serializer.Converters.Add(new Microsoft.FSharpLu.Json.CompactUnionJsonConverter())
    use sw = new StreamWriter(path)
    use writer = new JsonTextWriter(sw)
    serializer.Serialize(writer, obj)