2017-01-05 112 views
4

我已经在documentdb以下JSON数据,我想它解析为一个F#的多路系统中,这一区分联合解码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#multiway树。任何建议将不胜感激。谢谢

+0

我想你真正想问的问题是如何解析递归json结构到相应的F#递归数据类型? – scrwtp

回答

3

想想这个的一种方法是通过查看你需要什么数据来构造CommentMultiTreeDatabaseModel。它需要一个CommentDatabaseModel和一个CommentMultiTreeDatabaseModel的列表。因此,我们需要编写以下两个功能:

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";},[])]) 
*) 
+0

谢谢你的回应。我暂时推迟了在我的应用中实现这个功能,但我会回到它。再次感谢 –

+1

感谢您的回复。我刚刚使用Chiron来实现它 –