f# - 如何将选项和DU序列化为值或null(最好使用json.net)

时间:2017-03-14 01:20:54

标签: serialization f# json.net

我如何从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?"
}

谢谢: - )

2 个答案:

答案 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等的类型。