Problem

data class Problem(val type: String = ABOUT_BLANK, val status: Int? = null, val title: String? = null, val detail: String? = null, val instance: String? = null, val extensions: Map<String, ProblemValue> = emptyMap())(source)

An RFC 9457 problem detail. This is the document carried by application/problem+json and application/problem+xml.

The five members §3.1 defines are named properties here. Anything else becomes a §3.2 extension member. It lives in Problem.extensions, and both codecs place it as a sibling of the standard members, not inside an extensions key.

Extension names are checked against RESERVED_MEMBERS alone, since reusing one of those five would produce a document with a duplicate key. §3.2 also suggests starting with a letter, using only [A-Za-z0-9_], and staying at least three characters long. That guidance is a SHOULD a valid document can ignore, so it stays documented here instead of enforced.

See also

Constructors

Link copied to clipboard
constructor(type: String = ABOUT_BLANK, status: Int? = null, title: String? = null, detail: String? = null, instance: String? = null, extensions: Map<String, ProblemValue> = emptyMap())

Types

Link copied to clipboard
object Companion

Holds what RFC 9457 fixes on the wire, the nesting limit both codecs share, and the about:blank factory.

Properties

Link copied to clipboard

a human-readable explanation of this occurrence. It exists to help the client correct the problem, not to carry debugging information, and §3.1 asks consumers to leave it unparsed. Machine-readable data belongs in an extension member.

Link copied to clipboard

the §3.2 extension members, keyed by member name.

Link copied to clipboard

URI reference identifying this specific occurrence. It need not be dereferenceable. Treat it as an opaque server-assigned identifier when it isn't.

Link copied to clipboard
val status: Int?

the HTTP status code the origin server generated. §3.1 treats this as advisory only. Generators must make it agree with the real response status, but §5 still allows the two to diverge once an intermediary rewrites a response without touching its body, so consumers should key off the real status. §3.1 fixes what this member means without saying which values are legal, so this stays unchecked too.

Link copied to clipboard

a short human-readable summary of the type. §3.1 asks it to stay constant across occurrences, localization aside.

Link copied to clipboard

URI reference identifying the problem type. §3.1 treats this as the primary identifier of what went wrong, ahead of Problem.title. An absent type means ABOUT_BLANK, which is why this has a default value instead of being nullable. Use an absolute URI where you can. A relative one resolves against the document's base URI, so its meaning shifts depending on where the document was fetched.

Functions

Link copied to clipboard
inline fun <T> Problem.extension(name: String, json: Json = ProblemJson): T?

Decodes a single extension member with the deserializer resolved from T, or returns null when the member is absent.

fun <T> Problem.extension(name: String, deserializer: DeserializationStrategy<T>, json: Json = ProblemJson): T?

Decodes a single extension member, or returns null when it is absent.

Link copied to clipboard
inline fun <T> Problem.extensionsAs(json: Json = ProblemJson): T

Decodes the whole extension map into T, with the deserializer resolved from T. Members T does not declare are ignored, as RFC 9457 §3.2 requires.

fun <T> Problem.extensionsAs(deserializer: DeserializationStrategy<T>, json: Json = ProblemJson): T

Decodes the whole extension map into T. This is the typed consuming edge.