如何为 F# 中的类型生成 CSV reader/writer?

How do I generate a CSV reader/writer for a type in F#?

我正在使用 FSharp.Data 库中的类型提供程序来为我从 Web 服务调用返回的预期 JSON 响应生成类型。当我从示例 JSON 文件生成它们时,这非常有效,例如:

type User = JsonProvider<"data/user.sample.json">

我想做的是生成一些可以读写我在 F# 中定义的类型的 CSV 表示形式的东西。 CsvProvider 似乎不符合要求,就像 JsonProvider 一样,它似乎适用于我 starting 使用 CSV 文件的情况并想要生成一个类型,而我想要一些相反方向的东西。

自己使用 the CsvFile module 滚动这个似乎并不难,但是有更好的方法吗?

是否要自己定义预期的结构JSON?这可以通过 FSharp.Data 轻松实现。下面是获取最近几天黄金价格的示例。

首先定义预期的结构。这里 dateprice。然后你就用它来解析你的数据。

type Gold = JsonProvider<"""{ "date":"2015-03-20", "price":1171.75}""">
let goldPrcs = Gold.Parse goldPrcJson

这些是我的示例数据:

let goldPrcJson = """[["2015-03-20",1171.75],["2015-03-19",1164.0],["2015-03-18",1149.0],...]"""

第一个结果:

[
 [
   "2015-03-20",
   1171.75
 ],
 [
   "2015-03-19",
   1164.0
 ],
 [
   "2015-03-18",
   1149.0
 ],
 ...
]

类似的方法也可以应用于 CSV。

tldr 答案是:不,没有更好的办法 /tldr

总的来说,你有这组数据,你想序列化这组数据,但是又想控制如何序列化数据,而不去控制?

唔?

所以:

只需序列化您拥有的数据。而且,如果您对如何序列化它有任何偏好(json、xml、csv 等),您需要亲自动手并实际决定一些事情,甚至可能需要编写代码来处理一下。

好的,json,xml 是 "easy" 并且或多或少是开箱即用的,直到你遇到一些 "special" 情况并且必须确保它仍然通过添加属性和其他属性来工作。

序列化为 csv 是 OTOH,只不过是将所有数据记录聚合到一个带有分隔符的字符串中,然后将每一行写入文件。

Edit/addendum:

在进一步思考这个问题和主要问题 "what do you actually want to do?" 之后,我认为 "confusion" 可能是类型提供程序是某种超级序列化程序。而不是。

我确实尝试通过添加一些数据来创建 "new" csv 并且工作得很好,但正如你所说你需要先验文件格式,并且该文件格式是 "locked".

你也许可以做类似的事情(我认为无论如何都不应该使用):

#r @"..\packages\FSharp.Data.2.2.0\lib\net40\FSharp.Data.dll"

open FSharp.Data

[<Literal>]
let csvstring = @"Column1;Column2;Column3
Stringinfo;123;20150331"

type SomeCSV = CsvProvider< csvstring, Separators=";", HasHeaders=true >

let csv = SomeCSV.GetSample().Truncate(0)
let rows = 
 seq
   {
    yield SomeCSV.Row("colum1", 111, 20150330 )
   }

let csvmodded = csv.Append rows

csvmodded.Save(@"c:\temp\csttestmodded.csv")

在再次阅读您所有的评论和原始帖子后,我很确定您想要的是 "serializing"(或 "deserializing")。不是类型提供者。

TypeProviders 用于使用您无法完全控制 format/serialization 的内容(也不是真的,但现在让我们继续使用),尤其是 CSV、XML(没有 XSD) ), JSON, 你不是 "owning" 原来的 "data format" (我猜你称之为 POCO)。

如果您确实拥有 POCO 并想将此数据提供给其他人,则通常不是由类型提供者来处理序列化(但可能是为了在消费端进行反序列化)。

我不确定这次编辑是否阐明了很多(即使对我来说也是如此!;-)