Files
Flash5/flash-extensions/flash-ext-jackson
Zakaria El OrcheandClaude Opus 5 ef4740f26d feat(core): a service a handler asks for, and a body typed in its signature
Two things every handler was writing by hand.

@Inject on a field is filled inside bind, before onInit, once per handler at
boot: the request path still reads a field. The service is looked up by the
field's exact declared type; a static or final field is refused, and a type
nothing provides fails the boot naming the field. onInit stays for what has to
be computed, or for a service that may not be there.

BodyHandler<B> puts the body type in the signature — handle(req, res, body) —
and leaves reading it to the format. bodyTypeOf resolves that type argument
through a whole chain of bases, so tooling can read off a class what a route
takes. @Consumes says in which media type, inherited from the base class that
implements the reading, and is descriptive: the router does not enforce it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-23 13:31:13 +00:00
..
2026-05-11 13:54:19 +00:00
2026-04-17 18:56:06 +02:00

flash-ext-jackson

Jackson JSON integration for Flash with an opinionated auto-marshal middleware.

What it provides

Component Description
JacksonExtension Registers JSON services into FlashContext
Json JSON read/write helper (body, bodyFrom, write, writeView)
ObjectMapper Raw mapper escape hatch for advanced usage
JacksonMiddleware autoJson() middleware for automatic outbound JSON marshalling

Default mapper behavior (new JacksonExtension()):

  • auto-discovers Jackson modules on classpath (findAndAddModules())
  • includes Java Time support (jackson-datatype-jsr310)
  • writes date/time values as ISO-8601 strings (not numeric timestamps)

Install the extension, then apply autoJson() once at app or scope level.

JacksonExtension jackson = new JacksonExtension();

FlashApp app = FlashApp.create(8080)
    .install(jackson)
    .use(jackson.autoJson());

app.startAndBlock();

Behavior of autoJson():

  • pass-through: null, Response, byte[], String, CharSequence
  • any other return value: serialize to JSON byte[]
  • sets Content-Type: application/json for marshalled responses
  • serialization failures throw IllegalStateException

This keeps handlers concise while preserving Flash's direct byte write path.

Installation

<dependency>
    <groupId>dev.relism</groupId>
    <artifactId>flash-ext-jackson</artifactId>
    <version>1.1-indev2</version>
</dependency>

Json helper API

Use Json when you want explicit, local control in a handler.

@POST("/users")
public final class CreateUser extends RequestHandler {
    private Json json;

    @Override
    protected void onInit() {
        json = require(Json.class);
    }

    @Override
    public Object handle(Request req, Response res) throws Exception {
        CreateUserBody body = json.body(req, CreateUserBody.class);
        UserDto created = service.create(body);
        res.status(201);
        return json.write(res, created);
    }
}

Methods:

  • body(req, Type.class) -> parse from req.body().bytes()
  • bodyFrom(req, Type.class) -> parse from req.body().stream()
  • write(res, obj) -> writes JSON string and sets JSON content type
  • writeView(res, obj, View.class) -> JSON with Jackson @JsonView
  • mapper() -> raw ObjectMapper

Custom mapper

ObjectMapper mapper = JsonMapper.builder()
    .addModule(new JavaTimeModule())
    .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
    .build();

FlashApp.create(8080)
    .install(new JacksonExtension(mapper));

Scope usage

autoJson() works the same at scope level:

JacksonExtension jackson = new JacksonExtension();

app.mount("/api", api -> {
    api.use(jackson.autoJson());
    api.get("/health", (req, res) -> Map.of("ok", true));
});

If you need to pull it from context, JacksonMiddleware is also provided as a service after the app boots (same lifecycle model as other extension-provided services).

Notes

  • Install order is irrelevant (Flash two-phase extension lifecycle).
  • autoJson() and OpenAPI are intentionally decoupled.