首页 文章

将JSON多路树解码为F#多路树识别联盟

提问于
浏览
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
}

我广泛引用了Fold / Recursion over Multiway Tree in f# . 我不知道从哪里开始将这样的JSON结构解析为F#多路树 . 任何建议将不胜感激 . 谢谢

1 回答

  • 3

    考虑这个问题的一种方法是查看构建 CommentMultiTreeDatabaseModel 所需的数据 . 它需要 CommentDatabaseModelCommentMultiTreeDatabaseModel 列表 . 所以我们需要编写以下两个函数:

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

    但等等, parseTree 函数就是我们现在正在尝试编写的函数!因此,我们不是编写新函数,而是使用 rec 关键字标记当前函数,并在需要时调用它自己 .

    下面是一个如何完成的粗略示例 . 要看的关键是 parseTree ,它通过递归调用自身来构建数据 . 我用简单的DU表示了JSON输入数据 . 像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";},[])])
    *)
    

相关问题