cdumay_error_json/
lib.rs

1//! [![License: BSD-3-Clause](https://img.shields.io/badge/license-BSD--3--Clause-blue)](./LICENSE)
2//! [![cdumay_error_json on crates.io](https://img.shields.io/crates/v/cdumay_error_json)](https://crates.io/crates/cdumay_error_json)
3//! [![cdumay_error_json on docs.rs](https://docs.rs/cdumay_error_json/badge.svg)](https://docs.rs/cdumay_error_json)
4//! [![Source Code Repository](https://img.shields.io/badge/Code-On%20GitHub-blue?logo=GitHub)](https://github.com/cdumay/cdumay_error_json)
5//!
6//! A utility crate that converts `serde_json::Error` into structured, typed errors using the [`cdumay_error`](https://docs.rs/cdumay-error/) framework. This ensures consistent error handling, easier debugging, and informative error reporting across your Rust applications.
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//!
15//! ## Usage
16//!
17//! ```rust
18//! use cdumay_error::ErrorConverter;
19//! use serde_json::Value;
20//! use std::collections::BTreeMap;
21//! use cdumay_error_json::JsonErrorConverter;
22//!
23//! fn parse_json(input: &str) -> Result<Value, cdumay_error::Error> {
24//!     serde_json::from_str::<Value>(input).map_err(|e| {
25//!        let mut ctx = BTreeMap::new();
26//!        ctx.insert("input".to_string(), serde_value::Value::String(input.to_string()));
27//!        JsonErrorConverter::convert(&e, "Failed to parse JSON".to_string(), ctx)
28//!    })
29//! }
30//!```
31use cdumay_error::{AsError, Error, ErrorConverter, define_errors, define_kinds};
32use serde_json::error::Category;
33use std::collections::BTreeMap;
34
35/// Define custom error kinds with unique codes, HTTP status codes, and descriptions.
36define_kinds! {
37    JsonSyntax = ("JSON-00001", 400, "Syntax Error"),
38    JsonData = ("JSON-00002", 400, "Invalid JSON data"),
39    JsonEof = ("JSON-00003", 500, "Reached the end of the input data"),
40    JsonIo = ("JSON-00004", 500, "Syntax Error"),
41}
42
43/// Define error types corresponding to the previously defined error kinds.
44define_errors! {
45    IoError = JsonIo,
46    SyntaxError = JsonSyntax,
47    DataError = JsonData,
48    EofError = JsonEof
49}
50
51/// A utility struct for handling JSON errors and converting them into standardized error types.
52pub struct JsonErrorConverter;
53
54impl ErrorConverter for JsonErrorConverter {
55    type Error = serde_json::Error;
56    /// Converts a `serde_json::Error` into a standardized `Error` type based on its category.
57    ///
58    /// # Arguments
59    ///
60    /// * `err` - The `serde_json::Error` to be converted.
61    /// * `text` - A descriptive message for the error.
62    /// * `context` - A mutable reference to a `BTreeMap` containing additional error details.
63    ///
64    /// # Returns
65    ///
66    /// A standardized `Error` instance corresponding to the category of the provided `serde_json::Error`.
67    fn convert(err: &serde_json::Error, text: String, context: BTreeMap<String, serde_value::Value>) -> Error {
68        match err.classify() {
69            Category::Io => IoError::new().set_message(text).set_details(context).into(),
70            Category::Syntax => SyntaxError::new().set_message(text).set_details(context).into(),
71            Category::Data => DataError::new().set_message(text).set_details(context).into(),
72            Category::Eof => EofError::new().set_message(text).set_details(context).into(),
73        }
74    }
75}