HttpMessageConverter<T> class abstract

Strategy interface for converting between HTTP messages and Dart objects.

HttpMessageConverter implementations are responsible for the two-way conversion between HTTP request/response bodies and Dart objects. This abstraction enables content negotiation, serialization, and deserialization in a type-safe manner throughout the Jetleaf framework.

Generic Type Parameter

  • T: The Dart type that this converter can read and write

Primary Responsibilities

  • Deserialization: Convert HTTP request bodies to Dart objects (read)
  • Serialization: Convert Dart objects to HTTP response bodies (write)
  • Content Negotiation: Determine supported media types for specific types
  • Type Safety: Ensure proper type handling during conversion

Framework Integration

Converters are used by:

  • Request Body Processing: Converting JSON/XML request bodies to method parameters
  • Response Body Processing: Converting return values to JSON/XML responses
  • Content Negotiation: Selecting appropriate converters based on Accept headers
  • Error Handling: Providing meaningful conversion error messages

Built-in Implementations

Jetleaf typically provides these standard converters:

  • JsonHttpMessageConverter: Handles JSON ↔ Dart object conversion
  • StringHttpMessageConverter: Handles text/plain content
  • FormHttpMessageConverter: Handles application/x-www-form-urlencoded
  • ByteArrayHttpMessageConverter: Handles binary data (application/octet-stream)
  • XmlHttpMessageConverter: Handles XML content (application/xml)

Example: JSON Converter Implementation

@Generic(HttpMessageConverter)
class JsonHttpMessageConverter implements HttpMessageConverter<Object> {
  final JsonCodec _codec;
  
  JsonHttpMessageConverter(this._codec);

  @override
  bool canRead(Class<Object> type, [MediaType? mediaType]) {
    return mediaType?.includes(MediaType.APPLICATION_JSON) ?? true;
  }

  @override
  bool canWrite(Class<Object> type, [MediaType? mediaType]) {
    return mediaType?.includes(MediaType.APPLICATION_JSON) ?? true;
  }

  @override
  List<MediaType> getSupportedMediaTypes() {
    return [MediaType.APPLICATION_JSON];
  }

  @override
  Future<Object> read(Class<Object> type, HttpInputMessage inputMessage) async {
    try {
      final body = await inputMessage.getBody().readAsString();
      return _codec.decode(body);
    } catch (e) {
      throw HttpMessageNotReadableException('Failed to read JSON: $e', e);
    }
  }

  @override
  Future<void> write(Object object, MediaType? contentType, HttpOutputMessage outputMessage) async {
    try {
      final json = _codec.encode(object);
      outputMessage.getHeaders().setContentType(contentType ?? MediaType.APPLICATION_JSON);
      await outputMessage.getBody().writeString(json);
    } catch (e) {
      throw HttpMessageNotWritableException('Failed to write JSON: $e', e);
    }
  }
}

Content Negotiation Process

When processing requests/responses, the framework:

  1. Collects Media Types: From Accept header or Content-Type header
  2. Finds Compatible Converters: Using canRead/canWrite methods
  3. Selects Best Match: Based on media type specificity and quality factors
  4. Executes Conversion: Using the selected converter

Error Handling

Converters should throw framework-specific exceptions:

Best Practices

  • Make canRead and canWrite checks efficient and fast
  • Support common media type variations (e.g., application/json vs application/vnd.api+json)
  • Handle character encoding properly for text-based formats
  • Consider performance implications for large payloads
  • Provide clear error messages for debugging conversion issues
Implementers
Annotations
  • @Generic.new(HttpMessageConverter)

Constructors

HttpMessageConverter()
Strategy interface for converting between HTTP messages and Dart objects.
const

Properties

hashCode int
The hash code for this object.
no setterinherited
runtimeType Type
A representation of the runtime type of the object.
no setterinherited

Methods

canRead(Class type, [MediaType? mediaType]) bool
Determines whether this converter can deserialize the given type from the specified media type.
canWrite(Class type, [MediaType? mediaType]) bool
Determines whether this converter can serialize the given type to the specified media type.
equalizedProperties() List<Object?>
Mixin-style contract for value-based equality, hashCode, and toString.
inherited
getClassSupportedMediaTypes(Class<T> type) List<MediaType>
Returns the media types specifically supported for a given class type.
getSupportedMediaTypes() List<MediaType>
Returns the list of media types this converter supports by default.
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
read(Class<T> type, HttpInputMessage inputMessage) Future<T>
Deserializes an HTTP input message to a Dart object of type T.
toString() String
A string representation of this object.
inherited
write(T object, MediaType? contentType, HttpOutputMessage outputMessage) Future<void>
Serializes a Dart object to an HTTP output message.

Operators

operator ==(Object other) bool
The equality operator.
inherited