2017-01-05 59 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來實現它 –