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