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