diff --git a/Cargo.toml b/Cargo.toml
index 763cfef4844189bac64b8d9d32cbb57879f6d9f1..00d916515e7b73dc731aaee5c6e3b29d49e53657 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -5,9 +5,14 @@ edition = "2021"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
+[features]
+serde = ["dep:serde"]
+
 [dependencies]
 jsonschema = {version = "0.17.1", default-features = false, features = ["draft202012"]}
 serde_json = "1.0.113"
+serde = { version = "*", features = ["derive"], optional = true}
+
 
 [dev-dependencies]
 utoipa = "4.2.0"
diff --git a/README.md b/README.md
index 253ee60cb7d3cb72fdca2e105abc3ab6cde49dad..691f743db69e1f52b7676faf0ec04cf1e5207d60 100644
--- a/README.md
+++ b/README.md
@@ -27,9 +27,12 @@ fn main() {
         panic!("This should be an error!");
     };
 
+    let context = result.context();
+    assert_eq!(context[0].description, r#"["one"] has less than 2 items"#);
+    assert_eq!(context[1].description, "10 is less than the minimum of 15");
     assert_eq!(
         result.to_string(),
-        r#"JSON doesn't match expected schema: ["one"] has less than 2 items, 10 is less than the minimum of 15"#
+        r#"JSON doesn't match expected schema: found 2 errors"#
     );
 }
 
diff --git a/src/error.rs b/src/error.rs
new file mode 100644
index 0000000000000000000000000000000000000000..65859b0d223c4ede4d9df4402b21811899a756b6
--- /dev/null
+++ b/src/error.rs
@@ -0,0 +1,74 @@
+use std::fmt::Display;
+
+/// The error that is returned by the [`SchemaInspector`] when the provided JSON to the `inspect` function
+/// fails to conform to the schema the inspector was compiled with.
+///
+/// The error type internally holds a context containing detailed information about what part of the JSON differs from the schema
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct SchemaError {
+    pub(crate) context: Vec<ErrContext>,
+}
+
+/// The interal type containing metadata where the error has occurred along with why
+#[derive(Debug, Clone, PartialEq, Eq)]
+#[cfg_attr(feature = "serde", derive(serde::Serialize))]
+pub struct ErrContext {
+    /// the field where the validation failed
+    pub field: String,
+    /// detailed description of why the validation failed
+    pub description: String,
+}
+
+impl SchemaError {
+    /// Get the context of the error
+    pub fn context(&self) -> &[ErrContext] {
+        &self.context
+    }
+}
+
+impl std::error::Error for SchemaError {}
+
+impl Display for SchemaError {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        let num_errors = self.context.len();
+        let noun = if num_errors < 2 { "error" } else { "errors" };
+        write!(
+            f,
+            "JSON doesn't match expected schema: found {num_errors} {noun}",
+        )
+    }
+}
+
+/// All the possible errors that can occur while initializing [`SchemaInspector`]
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum InitError {
+    SchemaNotFound(String),
+    ResolutionFailure(String), // contains the reference that was not resolved
+    InvalidSchema(Option<String>), // contains the missing field in the schema
+    CompileFailure,
+    InferenceFailure,
+}
+
+impl std::error::Error for InitError {}
+
+impl Display for InitError {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        let base = "failed to initialize Inspector:";
+        match self {
+            Self::SchemaNotFound(schema) => {
+                write!(f, "{base} {schema} was not found in the provided schemas")
+            }
+            Self::ResolutionFailure(schema) => write!(
+                f,
+                "{base} failed to resolve references: referenced schema {schema} was not found"
+            ),
+            Self::InferenceFailure => write!(f, "{base} name of the type couldn't be inferred"),
+            Self::CompileFailure => write!(f, "{base} failed to compile schema"),
+            Self::InvalidSchema(schema) => write!(
+                f,
+                "{base} invalid schema provided: {} is missing or is not an object",
+                schema.as_deref().unwrap_or("field")
+            ),
+        }
+    }
+}
diff --git a/src/lib.rs b/src/lib.rs
index ed249908bfba1de226ffd6a3519e3ae27155bbc7..dddb9eb545a4573cc40a8ed0cfc9cd028a779ae7 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,7 +1,10 @@
 #[doc = include_str!("../README.md")]
 use jsonschema::{Draft, JSONSchema};
 use serde_json::{Map, Value};
-use std::fmt::Display;
+
+pub mod error;
+
+pub use error::*;
 
 /// The JSON schema inspector (validator)
 ///
@@ -123,65 +126,14 @@ impl SchemaInspector {
     /// that is inconsistent with the compiled schema.
     pub fn inspect(&self, json: &Value) -> Result<(), SchemaError> {
         self.schema.validate(json).map_err(|err| {
-            let mut cause = err.fold(String::new(), |mut acc, err| {
-                acc.push_str(&err.to_string());
-                acc.push_str(", ");
-                acc
-            });
-            cause.pop();
-            cause.pop();
-            SchemaError { cause }
-        })
-    }
-}
-
-/// The error that is returned by the [`SchemaInspector`] when the provided JSON to the `inspect` function
-/// fails to conform to the schema the inspector was compiled with.
-///
-/// The error type internally holds a string containing detailed information about what part of the JSON differs from the schema
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub struct SchemaError {
-    cause: String,
-}
-
-impl std::error::Error for SchemaError {}
+            let context = err
+                .map(|err| ErrContext {
+                    field: err.instance_path.to_string(),
+                    description: err.to_string(),
+                })
+                .collect();
 
-impl Display for SchemaError {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        write!(f, "JSON doesn't match expected schema: {}", self.cause)
-    }
-}
-
-/// All the possible errors that can occur while initializing [`SchemaInspector`]
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub enum InitError {
-    SchemaNotFound(String),
-    ResolutionFailure(String), // contains the reference that was not resolved
-    InvalidSchema(Option<String>), // contains the missing field in the schema
-    CompileFailure,
-    InferenceFailure,
-}
-
-impl std::error::Error for InitError {}
-
-impl Display for InitError {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        let base = "failed to initialize Inspector:";
-        match self {
-            Self::SchemaNotFound(schema) => {
-                write!(f, "{base} {schema} was not found in the provided schemas")
-            }
-            Self::ResolutionFailure(schema) => write!(
-                f,
-                "{base} failed to resolve references: referenced schema {schema} was not found"
-            ),
-            Self::InferenceFailure => write!(f, "{base} name of the type couldn't be inferred"),
-            Self::CompileFailure => write!(f, "{base} failed to compile schema"),
-            Self::InvalidSchema(schema) => write!(
-                f,
-                "{base} invalid schema provided: {} is missing or is not an object",
-                schema.as_deref().unwrap_or("field")
-            ),
-        }
+            SchemaError { context }
+        })
     }
 }
diff --git a/tests/basic.rs b/tests/basic.rs
index 81789f12bf512651f35aa466fb6c35433bb25aed..9dd1a8200e350c8492fd193ca6eef4edbd11ca5b 100644
--- a/tests/basic.rs
+++ b/tests/basic.rs
@@ -138,7 +138,18 @@ fn validate_regular_schema_err() {
         "field3": true,
         "field4": [""]
     }));
+
     assert!(result.is_err());
+    let err = result.err().unwrap();
+    assert_eq!(
+        err.to_string(),
+        "JSON doesn't match expected schema: found 1 error"
+    );
+    assert_eq!(err.context()[0].field, "/field2");
+    assert_eq!(
+        err.context()[0].description,
+        "0 is less than the minimum of 5"
+    );
 }
 
 #[test]
@@ -176,7 +187,11 @@ fn validate_nested_schema_err() {
             }
         }
     }));
-    assert!(result.is_err())
+    let err = result.err().unwrap();
+    assert_eq!(
+        err.to_string(),
+        "JSON doesn't match expected schema: found 2 errors"
+    );
 }
 
 #[test]