我如何从web api获取json以仅格式化值,或者为Option类型和Discriminated Unions设置null,最好使用Newtonsoft。
我目前正在使用Newtonsoft,只需将其添加到web api即可使用:
config.Formatters.JsonFormatter.SerializerSettings <- new JsonSerializerSettings()
当我使用我身边的数据时,我可以使用以下方法轻松将其转换回F#项目:JsonConvert.DeserializeObject<'a>(json)
api也将由非.NET客户端使用,所以我想要一个更标准的格式化json结果。
我想解决我的问题,不必为我的所有记录/ DU添加代码或装饰器以使其工作。我有很多有很多属性的记录,有些是Option。
ex(这就是DU序列化的方式):
// When value
"animal": {
"case": "Dog"
}
// When no value
"animal": null
这就是我需要的:
// When value
"animal": "Dog"
// When no value
"animal": null
这是Option类型序列化的方式:
"DocumentInfo": {
"case": "Some",
"fields": [
{
"docId": "77fb9dd0-bfbe-42e0-9d29-d5b1f5f0a9f7",
"docType": "Monkey Business",
"docName": "mb.doc",
"docContent": "why cant it just give me the values?"
}
]
}
这就是我需要的:
"DocumentInfo": {
"docId": "77fb9dd0-bfbe-42e0-9d29-d5b1f5f0a9f7",
"docType": "Monkey Business",
"docName": "mb.doc",
"docContent": "why cant it just give me the values?"
}
谢谢: - )
答案 0 :(得分:3)
您可以尝试使用Chiron。我自己没有使用它,所以我无法给你一个广泛的例子,但https://neoeinstein.github.io/blog/2015/12-13-chiron-json-ducks-monads/index.html有一些示例代码。 (另请参阅https://neoeinstein.github.io/blog/2016/04-02-chiron-computation-expressions/index.html以获得更好的语法)。基本上,Chiron知道如何序列化和反序列化基本的F#类型(字符串,数字,选项等),你可以通过提供两种静态方法ToJson
和类型来教导它来序列化任何其他类型。 FromJson
:
static member ToJson (x:DocumentInfo) = json {
do! Json.write "docId" x.docId
do! Json.write "docType" x.docType
do! Json.write "docName" x.docName
do! Json.write "docContent" x.docContent
}
static member FromJson (_:DocumentInfo) = json {
let! i = Json.read "docId"
let! t = Json.read "docType"
let! n = Json.read "docName"
let! c = Json.read "docContent"
return { docId = i; docType = t; docName = n; docContent = c }
}
通过在DocumentInfo
类型上提供这两种静态方法,Chiron将自动知道如何序列化DocumentInfo option
。至少,这是我的理解 - 但Chiron的文档很遗憾(我的意思是字面意思缺少:它还没有被写过),所以我没有&#39我自己真的用过了。所以这可能是也可能不是您需要的答案,但希望即使您最终没有使用它也会对您有所帮助。
答案 1 :(得分:0)
我找到了允许我使用Newtonsoft(JSON.NET)的解决方案,在需要时为我的类型应用自定义转换器,不需要对我的DU或记录进行任何更改。
简短的回答是,为Json.Net创建一个自定义转换器并使用读/写Json覆盖:
type CustomDuConverter() =
inherit JsonConverter() (...)
不幸的是,我在网上找到的那些已经创建的内容不能满足我上面列出的需求,但会稍加修改。一个很好的例子是:https://gist.github.com/isaacabraham/ba679f285bfd15d2f53e
要在每次通话的Web Api中应用自定义序列化程序,请使用:
config.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new CustomDuConverter())
要反序列化使用(将反序列化为DU的示例):
JsonConvert.DeserializeObject<Animal>("Dog", customConverter)
例如:
type Animal = Dog | Cat
JSON:
"animal": "Dog"
这将允许您为消费者创建一个干净的Api,并允许您将第三方Json数据用于使用Option等的类型。