我一直在使用Newtonsoft.Json
和Newtonsoft.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
功能。快速测试表明,此库将消除对嵌套数据框和与list
和Case
列相关联的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
是否可以处理写入流?我怎样才能做到这一点?
答案 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)