modules.md
August 14, 2026 ยท View on GitHub
ForyJsonModule packages a coherent set of Fory JSON registrations into one reusable extension.
A module can be provided by a language integration, a third-party library, a framework, or an
application. Use a module when consumers should install the whole extension with one builder call;
use direct builder registration for an application-specific codec that does not need separate
distribution.
Creating and Installing a Module
After implementing a codec such as MoneyCodec from the
Custom Codecs guide, a library can distribute its registration as a module:
import org.apache.fory.json.ForyJson;
import org.apache.fory.json.ForyJsonModule;
import org.apache.fory.json.ModuleContext;
public final class MoneyJsonModule implements ForyJsonModule {
public static final MoneyJsonModule INSTANCE = new MoneyJsonModule();
private MoneyJsonModule() {}
@Override
public void install(ModuleContext context) {
context.registerCodec(Money.class, new MoneyCodec());
}
}
ForyJson json =
ForyJson.builder()
.withModule(MoneyJsonModule.INSTANCE)
.build();
Installation runs while build() creates the immutable runtime configuration. Treat a module
configuration as immutable after adding it to a builder. Registered codec instances are shared by
concurrent operations and must be thread-safe.
Module Registrations
ModuleContext exposes the registrations needed by reusable integrations:
| Registration | Use |
|---|---|
registerCodec(Class, JsonValueCodec) | One shared complete codec for an exact class |
registerCodec(Class, JsonCodecFactory) | A resolver-owned complete codec for an exact class |
registerMixin(Class) | An annotated Mixin for its declared target |
registerCodecFactory(JsonCodecFactory) | A codec family selected from a parameterized target type |
Codec implementations and JsonCodecFactory behavior are documented in
Custom Codecs. Modules only package those registrations for installation.
Application registrations made directly on ForyJsonBuilder take precedence over module exact
registrations. Conflicting module registrations fail during build() instead of depending on
installation order.
Module Identity
moduleKey() identifies the module configuration for generated-code reuse and conflict checking.
The default key is the module class name and is sufficient for a configuration-free module.
A configurable module must return a deterministic key that includes every option affecting codec selection or generated code. Do not include secrets, mutable process state, or values unrelated to the installed JSON behavior.
public final class ConfiguredJsonModule implements ForyJsonModule {
private final boolean compactNames;
public ConfiguredJsonModule(boolean compactNames) {
this.compactNames = compactNames;
}
@Override
public String moduleKey() {
return getClass().getName() + ":compactNames=" + compactNames;
}
@Override
public void install(ModuleContext context) {
// Register the codecs, factories, or Mixins selected by this configuration.
}
}
For a Scala example that packages derived third-party enum codecs in a module, see Packaging Derived Codecs in a Module.