如何将字符串解析为任何F#数据?

时间:2017-09-27 19:02:06

标签: f# f#-data

在F#中,按功能data设置的任何stringify都可以是sprintf,如下所示:

type someKindOfDataType = ...
let data : someKindOfDataType = ...
sprintf "%A" data

我们可以使用反转函数将字符串解析回someKindOfDataType,如下所示:?

let parse<'someKingOfDataType> (s:string) : someKindOfDataType = ....

就像javascript中的JSON.parse一样?

2 个答案:

答案 0 :(得分:2)

您正在描述通常被称为序列化的内容 - 从内存数据结构转换为可以通过网络传输的表示形式,可以是XML,JSON,二进制等。 - 和反序列化 - 相反。

sprintf "%A"旨在提供方便的数据可视化表示,通常仅用于开发目的而非生产中。它实际上并没有进行序列化,因为没有办法反序列化。

如果您想将F#数据序列化为字符串,我建议您通过Newtonsoft.Json等库使用JSON。

请注意,这不会产生类似于F#源代码的字符串,例如sprintf "%A",因为目的不同。一个例子:

Newtonsoft.Json.JsonConvert.SerializeObject [|Some 3; None|]
// """[{"Case":"Some","Fields":[3]},null]"""

Newtonsoft.Json.JsonConvert.DeserializeObject<int option []> """[{"Case":"Some","Fields":[3]},null]"""
// [|Some 3; None|]

您需要提供要反序列化的类型,如果字符串不代表该类型的有效实例,则此操作可能会抛出异常。

答案 1 :(得分:1)

标准的.NET方式通常是您在您尝试解析的类型的类中使用ParseTryParse方法。

但是在F#中,TryParse函数不是很友好,因为它使用输出参数,F#编译器仍允许你将它看作元组,这会使事情变得更好,但你仍然期待得到一个选项,这是一个例子:

let a = Int32.Parse "5"
let b = 
    match Int32.TryParse "5" with
    | true, value -> Some value
    | _           -> None

如果你想使用图书馆F#+有两个函数parsetryParse,它们会为你做以上所有事情:

#r @"FSharpPlus.dll"
open FSharpPlus
open System

let (a:int) = parse "5"
let (b:int option) = tryParse "5"
let (c: Net.IPAddress option) = tryParse "10.0.0.1"

// val a : int = 5
// val b : int option = Some 5
// val c : Net.IPAddress option = Some 10.0.0.1

只要类型定义了ParseTryParse,它就会起作用。