pub struct ProblemJson {
pub type: String,
pub title: String,
pub status: u16,
pub detail: String,
pub instance: Option<String>,
pub extensions: BTreeMap<String, Value>,
}Expand description
RFC 7807 / 9457 Problem Details response body with optional extension members.
Unlike ApiError (which carries in-process state such as source and
Arc), ProblemJson is a pure serialization type — every field maps
directly to the wire format.
The extensions map serializes flat into the JSON object, so arbitrary
key-value members (e.g. trace_id, request_id) appear at the top level
alongside the standard fields:
{
"type": "urn:api-bones:error:resource-not-found",
"title": "Resource Not Found",
"status": 404,
"detail": "Booking 42 not found",
"instance": "urn:uuid:01234567-89ab-cdef-0123-456789abcdef",
"trace_id": "abc123"
}Content-Type is application/problem+json.
§no_std support
Available when either std or alloc is enabled together with serde
(required for serde_json::Value and BTreeMap).
Uses BTreeMap internally so heap
allocation is the only requirement — std is not needed.
§Examples
use api_bones::error::{ApiError, ErrorCode, ProblemJson};
let err = ApiError::not_found("booking 42 not found");
let problem = ProblemJson::from(err);
assert_eq!(problem.status, 404);
assert_eq!(problem.title, "Resource Not Found");Adding extension members:
use api_bones::error::{ApiError, ProblemJson};
let mut problem = ProblemJson::from(ApiError::internal("db timeout"));
problem.extensions.insert("trace_id".into(), "abc123".into());
assert_eq!(problem.extensions["trace_id"], "abc123");Fields§
§type: StringMachine-readable error type URI (RFC 9457 §3.1.1 type).
title: StringHuman-friendly summary (RFC 9457 §3.1.2 title).
status: u16HTTP status code (RFC 9457 §3.1.3 status).
detail: StringHuman-readable specifics (RFC 9457 §3.1.4 detail).
instance: Option<String>URI identifying this occurrence (RFC 9457 §3.1.5 instance).
extensions: BTreeMap<String, Value>Flat extension members (e.g. trace_id, request_id).
Serialized inline at the top level of the JSON object via
#[serde(flatten)]. Keys must not collide with the standard fields.
Uses BTreeMap for no_std compatibility.
Implementations§
Source§impl ProblemJson
impl ProblemJson
Sourcepub fn new(
type: impl Into<String>,
title: impl Into<String>,
status: u16,
detail: impl Into<String>,
) -> Self
pub fn new( type: impl Into<String>, title: impl Into<String>, status: u16, detail: impl Into<String>, ) -> Self
Build a ProblemJson directly from its components.
§Examples
use api_bones::error::ProblemJson;
let p = ProblemJson::new(
"urn:api-bones:error:bad-request",
"Bad Request",
400,
"missing field `email`",
);
assert_eq!(p.status, 400);
assert!(p.extensions.is_empty());Sourcepub fn with_instance(self, instance: impl Into<String>) -> Self
pub fn with_instance(self, instance: impl Into<String>) -> Self
Set the instance field (RFC 9457 §3.1.5).
§Examples
use api_bones::error::ProblemJson;
let p = ProblemJson::new("urn:api-bones:error:bad-request", "Bad Request", 400, "oops")
.with_instance("urn:uuid:00000000-0000-0000-0000-000000000000");
assert!(p.instance.is_some());Sourcepub fn extend(&mut self, key: impl Into<String>, value: impl Into<Value>)
pub fn extend(&mut self, key: impl Into<String>, value: impl Into<Value>)
Insert an extension member.
§Examples
use api_bones::error::ProblemJson;
let mut p = ProblemJson::new("urn:api-bones:error:bad-request", "Bad Request", 400, "oops");
p.extend("trace_id", "abc123");
assert_eq!(p.extensions["trace_id"], "abc123");Trait Implementations§
Source§impl Clone for ProblemJson
impl Clone for ProblemJson
Source§fn clone(&self) -> ProblemJson
fn clone(&self) -> ProblemJson
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for ProblemJson
impl Debug for ProblemJson
Source§impl<'de> Deserialize<'de> for ProblemJson
impl<'de> Deserialize<'de> for ProblemJson
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl From<ApiError> for ProblemJson
Available on crate features std and serde only.
impl From<ApiError> for ProblemJson
std and serde only.Source§fn from(err: ApiError) -> Self
fn from(err: ApiError) -> Self
Convert an ApiError into a ProblemJson.
code→typeviaErrorCode::urnrequest_id(UUID) →instanceas"urn:uuid:<id>"errors(validation) →"errors"extension membersourceis dropped (not part of the wire format)
§Examples
use api_bones::error::{ApiError, ErrorCode, ProblemJson};
let err = ApiError::new(ErrorCode::Forbidden, "not allowed");
let p = ProblemJson::from(err);
assert_eq!(p.status, 403);
assert_eq!(p.title, "Forbidden");