[英]How to serialize F# records to JSON properly?
我在 F# 中有幾種類型,例如:
type ResourceRecordSet =
| Alias of Name : string *
Type : ResourceRecordType *
AliasTarget : AliasTarget
| Record of Name : string *
Type : ResourceRecordType *
ResourceRecords : List<string> * TTL : uint32
使用類型:
let r =
Record(
"domain.tld."
, SOA
, ["ns-583.awsdns-08.net.
awsdns-hostmaster.amazon.com.
1 7200 900 1209600 86400"]
, 900u
)
當我嘗試將其序列化為 JSON 時,我得到以下信息:
let rjson = JsonSerializer.Serialize(r)
sprintf "%A" rjson
Output:
"{"Case":"Record","Fields":["doman.tld.",{"Case":"SOA"},["ns-583.awsdns-08.net. awsdns-hostmaster.amazon.com. 1 7200 900 1209600 86400"],900]}"
有沒有辦法控制序列化並產生以下內容:
{
"Name": "doman.tld.",
"ResourceRecords": [ {"Value": "ns-583.awsdns-08.net. awsdns-hostmaster.amazon.com. 1 7200 900 1209600 86400" }],
"TTL": 900,
"Type": "SOA"
}
為了回答我自己的問題,在閱讀了不同人建議的不同庫之后,Fleece 似乎是這里最可靠的解決方案。
首先是一個簡單的例子:
open System.Text.Json
open Fleece.SystemTextJson
open Fleece.SystemTextJson.Operators
open FSharpPlus
type AliasTarget =
{
DNSName : string
EvaluateTargetHealth : bool
HostedZoneId : string
}
static member ToJson (a: AliasTarget) =
jobj [
"DNSName" .= a.DNSName
"EvaluateTargetHealth" .= a.EvaluateTargetHealth
"HostedZoneId" .= a.HostedZoneId
]
static member OfJson json =
match json with
| JObject o ->
monad {
let! dnsName = o .@ "DNSName"
let! evaluateTargetHealth = o .@ "EvaluateTargetHealth"
let! hostedZoneId = o .@ "HostedZoneId"
return {
DNSName = dnsName
EvaluateTargetHealth = evaluateTargetHealth
HostedZoneId = hostedZoneId
}
}
| x -> Decode.Fail.objExpected x
let outp = aliasTargetToJSON { DNSName = "dbrgct5gwrbsd.cloudfront.net."; EvaluateTargetHealth = false; HostedZoneId = "xxx"}
loggerBlog.LogInfo outp
let aliasJson = """{"DNSName":"dbrgct5gwrbsd.cloudfront.net.","EvaluateTargetHealth":false,"HostedZoneId":"xxx"}"""
let alias : AliasTarget ParseResult = parseJson aliasJson
loggerBlog.LogInfo (sprintf "%A" alias)
這打印:
2020-06-08T23:26:09 INFO [Website] {"DNSName":"dbrgct5gwrbsd.cloudfront.net.","EvaluateTargetHealth":false,"HostedZoneId":"xxx"}
2020-06-08T23:26:09 INFO [Website] Ok { DNSName = "dbrgct5gwrbsd.cloudfront.net."
EvaluateTargetHealth = false
HostedZoneId = "xxx" }
序列化和反序列化都有效。
也可以實施 ADT 或有區別的聯合:
type Shape =
| Rectangle of width : float * length : float
| Circle of radius : float
| Prism of width : float * float * height : float
with
static member JsonObjCodec =
Rectangle <!> jreq "rectangle" (function Rectangle (x, y) -> Some (x, y) | _ -> None)
<|> ( Circle <!> jreq "radius" (function Circle x -> Some x | _ -> None) )
<|> ( Prism <!> jreq "prism" (function Prism (x, y, z) -> Some (x, y, z) | _ -> None) )
更多在這里:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.