因此,我可以使用JSON
轻松地将任意类型写入Newtonsoft.Json
:
type X = {
Number: decimal
Sequence: decimal
NumList: decimal list
}
let createItem (n, s, nL) =
{Number = n;
Sequence = s;
NumList = nL}
let items =
[
(1M, 1M, [1M; 2M; 3M])
(2M, 2M, [2M; 4M; 6M])
(3M, 3M, [3M; 6M; 9M])
]
|> List.map createItem
open Newtonsoft.Json
open System.IO
let writeToJson (path: string) (obj: 'a) : unit =
let serialized = JsonConvert.SerializeObject(obj)
File.WriteAllText(path, serialized)
writeToJson "xList.json" items
如何编写一个足够通用的函数,我可以读取JSON
文件?换句话说,我喜欢这样的东西:
let readFromJson (path: string) (t: 'T) =
let convertToQr = File.ReadAllText(path)
Newtonsoft.Json.JsonConvert.DeserializeObject<t list>(convertToQr)
其中第二个参数是Type
中对象的path
,但我不知道该怎么做。如果我尝试按原样使用此函数,则会出现编译器错误。
如何在上面的第二个参数中声明path
中的事物的类型?我可以吗?
答案 0 :(得分:5)
当明确定义时,通用参数在函数名之后立即写在尖括号中,在常规参数之前:
let readFromJson<'T>(path: string) =
let convertToQr = File.ReadAllText(path)
Newtonsoft.Json.JsonConvert.DeserializeObject<'T list>(convertToQr)
用法:
readFromJson<string> "/some/file.json"
或者,您可以指定函数的返回类型,并让编译器为您推断所有通用参数和参数:
let readFromJson(path: string) : 't list =
let convertToQr = File.ReadAllText(path)
Newtonsoft.Json.JsonConvert.DeserializeObject(convertToQr)
这里,编译器知道DeserializeObject
的泛型参数必须是't list
,因为它的结果是从readFromJson
返回的,结果类型readFromJson
是明确声明为't list
。类似地,只需通过注意函数定义中的泛型类型,编译器就会推断该函数有一个泛型参数。
以类似的方式,当调用函数时,您可以让编译器推断出所需的类型:
// call inferred to readFromJson<string>, because that's the required return type
let s: string list = readFromJson "/some/file.json"