cdumay_json/lib.rs
1//! [](./LICENSE)
2//! [](https://crates.io/crates/cdumay_json)
3//! [](https://docs.rs/cdumay_json)
4//! [](https://github.com/cdumay/cdumay_json)
5//!
6//! A small crate to manipulate Json data.
7//!
8//! ## Features
9//!
10//! - Categorizes `serde_json::Error` into specific error types (`Syntax`, `IO`, `Data`, `EOF`)
11//! - Each error type is associated with a custom code, HTTP status, and descriptive message
12//! - Structured output for APIs, logging systems, and observability platforms
13//! - Includes context metadata via `BTreeMap`
14//! - Provides a convenient `convert_json_result!` macro for error conversion
15//!
16//! ## Usage
17//!
18//! Using the `JsonErrorConverter` directly:
19//! ```rust
20//! use cdumay_core::{Error, ErrorConverter};
21//! use serde_json::Value;
22//! use std::collections::BTreeMap;
23//! use cdumay_json::JsonErrorConverter;
24//!
25//! fn parse_json(input: &str) -> cdumay_core::Result<Value> {
26//! serde_json::from_str::<Value>(input).map_err(|e| {
27//! let mut ctx = BTreeMap::new();
28//! ctx.insert("input".to_string(), serde_value::Value::String(input.to_string()));
29//! JsonErrorConverter::convert(&e, "Failed to parse JSON".to_string(), ctx)
30//! })
31//! }
32//! ```
33//!
34//! Using the `convert_json_result!` macro:
35//! ```rust
36//! use cdumay_json::convert_json_result;
37//! use serde_json::Value;
38//! use std::collections::BTreeMap;
39//! use cdumay_core::{Error, ErrorConverter};
40//!
41//! fn parse_json(input: &str) -> cdumay_core::Result<Value> {
42//! // Basic usage with just the result
43//! convert_json_result!(serde_json::from_str::<Value>(input));
44//!
45//! // With custom context
46//! let mut ctx = BTreeMap::new();
47//! ctx.insert("input".to_string(), serde_value::Value::String(input.to_string()));
48//! convert_json_result!(serde_json::from_str::<Value>(input), ctx.clone());
49//!
50//! // With custom context and message
51//! convert_json_result!(serde_json::from_str::<Value>(input), ctx, "Failed to parse JSON")
52//! }
53//! ```
54#[macro_use]
55mod macros;
56
57use cdumay_core::{Error, ErrorConverter, define_errors, define_kinds};
58use serde_json::error::Category;
59use std::collections::BTreeMap;
60
61define_kinds! {
62 JsonSyntax = (400, "Syntax Error"),
63 JsonData = (400, "Invalid JSON data"),
64 JsonEof = (500, "Reached the end of the input data"),
65 JsonIo = (500, "IO Error"),
66}
67
68define_errors! {
69 IoError = JsonIo,
70 SyntaxError = JsonSyntax,
71 DataError = JsonData,
72 EofError = JsonEof
73}
74
75/// A utility struct for handling JSON errors and converting them into standardized error types.
76pub struct JsonErrorConverter;
77
78impl ErrorConverter for JsonErrorConverter {
79 type Error = serde_json::Error;
80 /// Converts a `serde_json::Error` into a standardized `Error` type based on its category.
81 ///
82 /// # Arguments
83 ///
84 /// * `err` - The `serde_json::Error` to be converted.
85 /// * `text` - A descriptive message for the error.
86 /// * `context` - A mutable reference to a `BTreeMap` containing additional error details.
87 ///
88 /// # Returns
89 ///
90 /// A standardized `Error` instance corresponding to the category of the provided `serde_json::Error`.
91 fn convert(err: &serde_json::Error, text: String, context: BTreeMap<String, serde_value::Value>) -> Error {
92 match err.classify() {
93 Category::Io => IoError::new().with_message(text).with_details(context).into(),
94 Category::Syntax => SyntaxError::new().with_message(text).with_details(context).into(),
95 Category::Data => DataError::new().with_message(text).with_details(context).into(),
96 Category::Eof => EofError::new().with_message(text).with_details(context).into(),
97 }
98 }
99}