4

documentdb に次の JSON データがあり、これを F# マルチウェイ ツリー識別ユニオンに解析したいと考えています。

"commentTree": {
    "commentModel": {
        "commentId": "",
        "userId": "",
        "message": ""
      },
      "forest": []
    }

F# 多元判別共用体

type public CommentMultiTreeDatabaseModel = 
| CommentDatabaseModelNode of CommentDatabaseModel * list<CommentMultiTreeDatabaseModel>

ここで、CommentMultiTreeDatabaseModel は次のように定義されます

type public CommentDatabaseModel =
{ commentId : string
  userId : string
  message : string
}

f# のマルチウェイ ツリーでの Fold/Recursion を広範囲に参照しています。このような JSON 構造を解析して F# マルチウェイ ツリーにする場所がわかりません。どんな提案でも大歓迎です。ありがとう

4

1 に答える 1

3

これについて考える 1 つの方法は、CommentMultiTreeDatabaseModel. CommentDatabaseModelと のリストが必要ですCommentMultiTreeDatabaseModel。したがって、次の 2 つの関数を記述する必要があります。

let parseComment (input : JSON) : CommentDatabaseModel =
    ...

let parseTree (input : JSON) : CommentMultiTreeDatabaseModel =
    ...

しかし待ってください、parseTree関数は私たちが今書こうとしているものです! したがって、新しい関数を記述する代わりに、現在の関数をrecキーワードでマークし、必要な場所でそれ自体を呼び出すだけです。

以下は、それがどのように行われるかの大まかな例です。注目すべき重要なことはparseTree、再帰的に自分自身を呼び出すことによってデータを構築することです。JSON 入力データを単純な DU で表現しました。Chironのようなライブラリは、このようなものを作成できます。

このコードは、すべての JSON を一度に解析することに注意してください。また、末尾再帰ではないため、ツリー構造の深さに注意する必要があります。

[<RequireQualifiedAccess>]
type JSON =
    | String of string
    | Object of (string * JSON) list
    | Array of JSON list

type public CommentDatabaseModel = {
    commentId : string
    userId : string
    message : string
}

type public CommentMultiTreeDatabaseModel = 
    | CommentDatabaseModelNode of CommentDatabaseModel * list<CommentMultiTreeDatabaseModel>


let parseComment = function
    | JSON.Object [ "commentId", JSON.String commentId; "userId", JSON.String userId; "message", JSON.String message ] ->
        {
            commentId = commentId
            userId = userId
            message = message
        }
    | _ -> failwith "Bad data"

let rec parseTree (input : JSON) : CommentMultiTreeDatabaseModel =
    match input with
    | JSON.Object [ "commentModel", commentModel; "forest", JSON.Array forest ] ->
        CommentDatabaseModelNode (parseComment commentModel, List.map parseTree forest)
    | _ -> failwith "Bad data"

let parse (input : JSON) : CommentMultiTreeDatabaseModel =
    match input with
    | JSON.Object [ "commentTree", commentTree ] ->
        parseTree commentTree
    | _ -> failwith "Bad data"


let comment text =    
    JSON.Object [
        "commentId", JSON.String ""
        "userId", JSON.String ""
        "message", JSON.String text
    ]

let sampleData =
    JSON.Object [
        "commentTree", JSON.Object [
            "commentModel", comment "one"
            "forest", JSON.Array [
                JSON.Object [
                    "commentModel", comment "two"
                    "forest", JSON.Array []
                ]

                JSON.Object [
                    "commentModel", comment "three"
                    "forest", JSON.Array []
                ]
            ]
        ]
    ]

parse sampleData

(*
val it : CommentMultiTreeDatabaseModel =
  CommentDatabaseModelNode
    ({commentId = "";
      userId = "";
      message = "one";},
     [CommentDatabaseModelNode ({commentId = "";
                                 userId = "";
                                 message = "two";},[]);
      CommentDatabaseModelNode ({commentId = "";
                                 userId = "";
                                 message = "three";},[])])
*)
于 2017-01-09T04:24:11.917 に答える