OCaml library for JSONfeed parsing and creation
1(** Example: Creating and serializing a JSON Feed 2 3 This demonstrates: 4 - Creating authors 5 - Creating items with different content types 6 - Creating a complete feed 7 - Serializing to JSON string and file *) 8 9open Jsonfeed 10 11(* Helper to write feed to output channel *) 12let to_file filename feed = 13 match Jsonfeed.to_string feed with 14 | Ok s -> 15 Out_channel.with_open_gen 16 [Open_wronly; Open_creat; Open_trunc; Open_text] 17 0o644 18 filename 19 (fun oc -> Out_channel.output_string oc s) 20 | Error e -> 21 Printf.eprintf "Error encoding feed: %s\n" (Jsont.Error.to_string e); 22 exit 1 23 24let create_blog_feed () = 25 (* Create some authors *) 26 let jane = Author.create 27 ~name:"Jane Doe" 28 ~url:"https://example.com/authors/jane" 29 ~avatar:"https://example.com/avatars/jane.png" 30 () in 31 32 let john = Author.create 33 ~name:"John Smith" 34 ~url:"https://example.com/authors/john" 35 () in 36 37 (* Create items with different content types *) 38 let item1 = Item.create 39 ~id:"https://example.com/posts/1" 40 ~url:"https://example.com/posts/1" 41 ~title:"Introduction to OCaml" 42 ~content:(`Both ( 43 "<p>OCaml is a powerful functional programming language.</p>", 44 "OCaml is a powerful functional programming language." 45 )) 46 ~date_published:(Jsonfeed.Rfc3339.parse "2024-11-01T10:00:00Z" |> Option.get) 47 ~date_modified:(Jsonfeed.Rfc3339.parse "2024-11-01T15:30:00Z" |> Option.get) 48 ~authors:[jane] 49 ~tags:["ocaml"; "programming"; "functional"] 50 ~summary:"A beginner's guide to OCaml programming" 51 () in 52 53 let item2 = Item.create 54 ~id:"https://example.com/posts/2" 55 ~url:"https://example.com/posts/2" 56 ~title:"JSON Feed for Syndication" 57 ~content:(`Html "<p>JSON Feed is a modern alternative to RSS and Atom.</p>") 58 ~date_published:(Jsonfeed.Rfc3339.parse "2024-11-02T09:00:00Z" |> Option.get) 59 ~authors:[jane; john] 60 ~tags:["json"; "syndication"; "web"] 61 ~image:"https://example.com/images/jsonfeed.png" 62 () in 63 64 (* Microblog-style item (text only, no title) *) 65 let item3 = Item.create 66 ~id:"https://example.com/micro/42" 67 ~content:(`Text "Just shipped a new feature! 🚀") 68 ~date_published:(Jsonfeed.Rfc3339.parse "2024-11-03T08:15:00Z" |> Option.get) 69 ~tags:["microblog"] 70 () in 71 72 (* Create the complete feed *) 73 let feed = Jsonfeed.create 74 ~title:"Example Blog" 75 ~home_page_url:"https://example.com" 76 ~feed_url:"https://example.com/feed.json" 77 ~description:"A blog about programming, web development, and technology" 78 ~icon:"https://example.com/icon-512.png" 79 ~favicon:"https://example.com/favicon-64.png" 80 ~authors:[jane; john] 81 ~language:"en-US" 82 ~items:[item1; item2; item3] 83 () in 84 85 feed 86 87let create_podcast_feed () = 88 (* Create podcast author *) 89 let host = Author.create 90 ~name:"Podcast Host" 91 ~url:"https://podcast.example.com/host" 92 ~avatar:"https://podcast.example.com/host-avatar.jpg" 93 () in 94 95 (* Create episode with audio attachment *) 96 let attachment = Attachment.create 97 ~url:"https://podcast.example.com/episodes/ep1.mp3" 98 ~mime_type:"audio/mpeg" 99 ~title:"Episode 1: Introduction" 100 ~size_in_bytes:15_728_640L 101 ~duration_in_seconds:1800 102 () in 103 104 let episode = Item.create 105 ~id:"https://podcast.example.com/episodes/1" 106 ~url:"https://podcast.example.com/episodes/1" 107 ~title:"Episode 1: Introduction" 108 ~content:(`Html "<p>Welcome to our first episode!</p>") 109 ~date_published:(Jsonfeed.Rfc3339.parse "2024-11-01T12:00:00Z" |> Option.get) 110 ~attachments:[attachment] 111 ~authors:[host] 112 ~image:"https://podcast.example.com/episodes/ep1-cover.jpg" 113 () in 114 115 (* Create podcast feed with hub for real-time updates *) 116 let hub = Hub.create 117 ~type_:"WebSub" 118 ~url:"https://pubsubhubbub.appspot.com/" 119 () in 120 121 let feed = Jsonfeed.create 122 ~title:"Example Podcast" 123 ~home_page_url:"https://podcast.example.com" 124 ~feed_url:"https://podcast.example.com/feed.json" 125 ~description:"A podcast about interesting topics" 126 ~icon:"https://podcast.example.com/icon.png" 127 ~authors:[host] 128 ~language:"en-US" 129 ~hubs:[hub] 130 ~items:[episode] 131 () in 132 133 feed 134 135let main () = 136 (* Create blog feed *) 137 let blog_feed = create_blog_feed () in 138 Format.printf "Created blog feed: %a\n\n" Jsonfeed.pp blog_feed; 139 140 (* Serialize to string *) 141 (match Jsonfeed.to_string blog_feed with 142 | Ok json_string -> 143 Format.printf "JSON (first 200 chars): %s...\n\n" 144 (String.sub json_string 0 (min 200 (String.length json_string))) 145 | Error e -> 146 Printf.eprintf "Error serializing to string: %s\n" (Jsont.Error.to_string e); 147 exit 1); 148 149 (* Serialize to file *) 150 to_file "blog-feed.json" blog_feed; 151 Format.printf "Wrote blog feed to blog-feed.json\n\n"; 152 153 (* Create podcast feed *) 154 let podcast_feed = create_podcast_feed () in 155 Format.printf "Created podcast feed: %a\n\n" Jsonfeed.pp_summary podcast_feed; 156 157 (* Validate feeds *) 158 (match Jsonfeed.validate blog_feed with 159 | Ok () -> Format.printf "✓ Blog feed is valid\n" 160 | Error errors -> 161 Format.printf "✗ Blog feed validation errors:\n"; 162 List.iter (Format.printf " - %s\n") errors); 163 164 (match Jsonfeed.validate podcast_feed with 165 | Ok () -> Format.printf "✓ Podcast feed is valid\n" 166 | Error errors -> 167 Format.printf "✗ Podcast feed validation errors:\n"; 168 List.iter (Format.printf " - %s\n") errors) 169 170let () = main ()