OCaml library for JSONfeed parsing and creation

switch error types

+20 -28
+1 -1
README.md
··· 67 67 | Some title -> Printf.printf "- %s\n" title 68 68 | None -> () 69 69 ) (Jsonfeed.items feed) 70 - | Error (`Msg err) -> 70 + | Error err -> 71 71 Printf.eprintf "Parse error: %s\n" err 72 72 73 73 (* Parse from file *)
+2 -2
example/feed_parser.ml
··· 182 182 Format.printf "✓ Round-trip successful: feeds are equal\n" 183 183 else 184 184 Format.printf "✗ Round-trip failed: feeds differ\n" 185 - | Error (`Msg err) -> 185 + | Error err -> 186 186 Format.eprintf "✗ Round-trip failed: %s\n" err) 187 - | Error (`Msg err) -> 187 + | Error err -> 188 188 Format.eprintf "Error parsing feed: %s\n" err 189 189 with 190 190 | Sys_error msg ->
+3 -3
example/feed_validator.ml
··· 256 256 257 257 (match Jsonfeed.of_string invalid_json1 with 258 258 | Ok _ -> Format.printf "✗ Should have failed (missing version)\n" 259 - | Error (`Msg err) -> 259 + | Error err -> 260 260 Format.printf "✓ Correctly rejected invalid feed: %s\n" err); 261 261 262 262 (* Missing required title field *) ··· 267 267 268 268 (match Jsonfeed.of_string invalid_json2 with 269 269 | Ok _ -> Format.printf "✗ Should have failed (missing title)\n" 270 - | Error (`Msg err) -> 270 + | Error err -> 271 271 Format.printf "✓ Correctly rejected invalid feed: %s\n" err); 272 272 273 273 (* Item without id *) ··· 281 281 282 282 (match Jsonfeed.of_string invalid_json3 with 283 283 | Ok _ -> Format.printf "✗ Should have failed (item without id)\n" 284 - | Error (`Msg err) -> 284 + | Error err -> 285 285 Format.printf "✓ Correctly rejected invalid feed: %s\n" err); 286 286 287 287 Format.printf "\n"
+2 -3
lib/jsonfeed.ml
··· 72 72 73 73 (* JSON parsing and serialization *) 74 74 75 - type error = [ `Msg of string ] 75 + type error = string 76 76 77 - let error_msgf fmt = Format.kasprintf (fun s -> Error (`Msg s)) fmt 77 + let error_msgf fmt = Format.kasprintf (fun s -> Error s) fmt 78 78 79 79 (* JSON parsing helpers *) 80 80 ··· 350 350 (* JSON serialization *) 351 351 352 352 let to_jsonm enc feed = 353 - (* Simplified serialization using Jsonm *) 354 353 let enc_field name value_fn = 355 354 ignore (Jsonm.encode enc (`Lexeme (`Name name))); 356 355 value_fn ()
+8 -15
lib/jsonfeed.mli
··· 4 4 type-safe parsing and serialization of JSON Feed documents. JSON Feed is a 5 5 syndication format similar to RSS and Atom, but using JSON instead of XML. 6 6 7 - {b Key Features:} 8 - - Type-safe construction with compile-time validation 9 - - Support for all JSON Feed 1.1 fields 10 - - RFC 3339 date parsing with Ptime integration 11 - - Streaming parsing and serialization with Jsonm 12 - - Comprehensive documentation and examples 13 - 14 7 {b Quick Start:} 15 8 {[ 16 9 (* Create a simple feed *) ··· 33 26 (* Parse from string *) 34 27 match Jsonfeed.of_string json with 35 28 | Ok feed -> Printf.printf "Feed: %s\n" (Jsonfeed.title feed) 36 - | Error (`Msg err) -> Printf.eprintf "Error: %s\n" err 29 + | Error err -> Printf.eprintf "Error: %s\n" err 37 30 ]} 38 31 39 32 @see <https://www.jsonfeed.org/version/1.1/> JSON Feed Specification *) ··· 195 188 (** {1 Parsing and Serialization} *) 196 189 197 190 (** Error type for parsing operations. *) 198 - type error = [ `Msg of string ] 191 + type error = string 199 192 200 193 (** [of_jsonm decoder] parses a JSON Feed from a Jsonm decoder. 201 194 ··· 203 196 with streaming JSON processing pipelines. 204 197 205 198 @param decoder A Jsonm decoder positioned at the start of a JSON Feed document 206 - @return [Ok feed] on success, [Error (`Msg err)] on parse error 199 + @return [Ok feed] on success, [Error err] on parse error 207 200 208 201 {b Example:} 209 202 {[ 210 203 let decoder = Jsonm.decoder (`String json_string) in 211 204 match Jsonfeed.of_jsonm decoder with 212 205 | Ok feed -> (* process feed *) 213 - | Error (`Msg err) -> (* handle error *) 206 + | Error err -> (* handle error *) 214 207 ]} *) 215 - val of_jsonm : Jsonm.decoder -> (t, [> error]) result 208 + val of_jsonm : Jsonm.decoder -> (t, error) result 216 209 217 210 (** [to_jsonm encoder feed] serializes a JSON Feed to a Jsonm encoder. 218 211 ··· 234 227 (** [of_string s] parses a JSON Feed from a string. 235 228 236 229 @param s A JSON string containing a JSON Feed document 237 - @return [Ok feed] on success, [Error (`Msg err)] on parse error 230 + @return [Ok feed] on success, [Error err] on parse error 238 231 239 232 {b Example:} 240 233 {[ ··· 245 238 }|} in 246 239 match Jsonfeed.of_string json with 247 240 | Ok feed -> Printf.printf "Parsed: %s\n" (Jsonfeed.title feed) 248 - | Error (`Msg err) -> Printf.eprintf "Error: %s\n" err 241 + | Error err -> Printf.eprintf "Error: %s\n" err 249 242 ]} *) 250 - val of_string : string -> (t, [> error]) result 243 + val of_string : string -> (t, error) result 251 244 252 245 (** [to_string ?minify feed] serializes a JSON Feed to a string. 253 246
+4 -4
test/test_jsonfeed.ml
··· 235 235 | Ok feed -> 236 236 Alcotest.(check string) "title" "Test Feed" (Jsonfeed.title feed); 237 237 Alcotest.(check int) "items" 0 (List.length (Jsonfeed.items feed)) 238 - | Error (`Msg err) -> 238 + | Error err -> 239 239 Alcotest.fail (Printf.sprintf "Parse failed: %s" err) 240 240 241 241 let test_feed_parse_with_item () = ··· 258 258 Alcotest.(check string) "item id" "https://example.com/1" (Item.id item); 259 259 Alcotest.(check (option string)) "content_html" (Some "<p>Hello</p>") (Item.content_html item) 260 260 | _ -> Alcotest.fail "Expected 1 item") 261 - | Error (`Msg err) -> 261 + | Error err -> 262 262 Alcotest.fail (Printf.sprintf "Parse failed: %s" err) 263 263 264 264 let test_feed_roundtrip () = ··· 288 288 Alcotest.(check int) "items count" 289 289 (List.length (Jsonfeed.items feed1)) 290 290 (List.length (Jsonfeed.items feed2)) 291 - | Error (`Msg err) -> 291 + | Error err -> 292 292 Alcotest.fail (Printf.sprintf "Round-trip failed: %s" err) 293 293 294 294 let test_feed_parse_invalid_missing_content () = ··· 303 303 }|} in 304 304 match Jsonfeed.of_string json with 305 305 | Ok _ -> Alcotest.fail "Should reject item without content" 306 - | Error (`Msg err) -> 306 + | Error err -> 307 307 Alcotest.(check bool) "has error" true 308 308 (contains_substring err "content") 309 309