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 ()