# Class Mappers

java.lang.Object
com.codename1.mapping.Mappers

public final class Mappers extends Object

Public entry point for the build-time JSON / XML mapping framework.

`@Mapped` classes get a generated mapper at build time. The generated mapper's static initializer self-registers with this registry. The registry stays empty until something triggers each generated class's `<clinit>`:

- iOS / Android -- the build server probes the project zip for `cn1app.MapperBootstrap`, and when present splices a `new cn1app.MapperBootstrap();` into the per-build application stub before `Display.init`. That constructor references every generated mapper, triggering their static initializers.
- JavaSE simulator + desktop -- `JavaSEPort#postInit` calls `Class.forName("cn1app.MapperBootstrap")` so the registry is populated on the same boundary. Classloading is the legitimate path here: JavaSE runs unobfuscated.
- Unit tests / manual init -- application code can call `Mappers.register(...)` directly to install a hand-written mapper for a class the build can't annotate.

Typical use after init:

    String json = Mappers.toJson(user);
    User u = Mappers.fromJson(json, User.class);

    String xml = Mappers.toXml(user);
    User u = Mappers.fromXml(xml, User.class);

The registry is keyed on `getClass().getName()` so it survives ParparVM rename and R8 obfuscation: both the registration site and the lookup site see the same renamed name within a single execution. The map keys are never persisted, so the renaming has no observable effect on behavior.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `static void`
  `appendJson(Object instance, StringBuilder out)`
  Appends `instance` as a JSON object using its registered mapper, taking the `Mapper.Direct` route when that mapper offers one.
  `static void`
  `appendJsonRaw(StringBuilder out, Object value)`
  Appends `value` exactly as `JSONWriter` would render it if it had been put into the map that `Mapper#toMap` builds.
  `static void`
  `appendJsonString(StringBuilder sb, String s)`
  Appends `s` as an escaped JSON string, or `null`.
  `static void`
  `appendJsonUsing(Mapper<?> mapper, Object instance, StringBuilder out)`
  Appends `instance` through the mapper the CALLER names, rather than the one registered for the instance's runtime class.
  `static void`
  `appendJsonValue(StringBuilder out, Object value)`
  Appends any value a generated codec can hold, producing exactly what the map path would.
  `static <T> T`
  `fromJson(Reader json, Class<T> type)`
  Parses JSON read from a `Reader` (file, network response, ...) without fully buffering it into a String first.
  `static <T> T`
  `fromJson(String json, Class<T> type)`
  Inverse of `#toJson`.
  `static <T> T`
  `fromXml(Reader xml, Class<T> type)`
  Parses XML read from a `Reader` without fully buffering it first.
  `static <T> T`
  `fromXml(String xml, Class<T> type)`
  Inverse of `#toXml`.
  `static <T> Mapper<T>`
  `get(Class<T> type)`
  Looks up the mapper for `type` (by `type.getName()`) or null when none is registered.
  `static <T> void`
  `register(Mapper<T> mapper)`
  Installs `mapper` under `mapper.type().getName()`.
  `static String`
  `toJson(Object instance)`
  Serializes `instance` to JSON.
  `static String`
  `toXml(Object instance)`
  Serializes `instance` to XML.

  ### Methods inherited from class Object

  `clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Method Details

  - ### register

    public static <T> void register(Mapper<T> mapper)
    Installs `mapper` under `mapper.type().getName()`. The generated per-class mapper's static initializer calls this; hand-written mappers for classes outside the build's annotation scan call it explicitly.

  - ### get

    public static <T> Mapper<T> get(Class<T> type)
    Looks up the mapper for `type` (by `type.getName()`) or null when none is registered.

  - ### toJson

    public static String toJson(Object instance)
    Serializes `instance` to JSON. Throws `IllegalStateException` when no mapper is registered for its concrete class; that always points at a missing `@Mapped` annotation or a build that ran without the process-annotations Mojo.

  - ### fromJson

    public static <T> T fromJson(String json, Class<T> type)
    Inverse of `#toJson`. Parses the JSON text and hands the resulting Map to the registered mapper.

  - ### fromJson

    public static <T> T fromJson(Reader json, Class<T> type)
    Parses JSON read from a `Reader` (file, network response, ...) without fully buffering it into a String first.

  - ### toXml

    public static String toXml(Object instance)
    Serializes `instance` to XML.

  - ### fromXml

    public static <T> T fromXml(String xml, Class<T> type)
    Inverse of `#toXml`. Parses the XML text and hands the resulting Element to the registered mapper.

  - ### fromXml

    public static <T> T fromXml(Reader xml, Class<T> type)
    Parses XML read from a `Reader` without fully buffering it first.

  - ### appendJsonValue

    public static void appendJsonValue(StringBuilder out, Object value)

    Appends any value a generated codec can hold, producing exactly what the map path would.

    Public because generated `toJson` methods call it for the property kinds they cannot render inline -- a nested mapped object, a `Property`'s value, a list element. A nested object goes through ITS mapper, taking that mapper's `Mapper.Direct` route when it offers one, so nesting stays free of intermediate maps all the way down.

    Conversions match `Mapper#toMap` exactly, and must keep matching: a date becomes its millisecond value and an enum its `name()`, because that is what the map path puts in the map before the writer ever sees it.

  - ### appendJson

    public static void appendJson(Object instance, StringBuilder out)

    Appends `instance` as a JSON object using its registered mapper, taking the `Mapper.Direct` route when that mapper offers one.

    Unlike `#toJson(Object)` this appends rather than returning a String, so nesting does not build one String per level. An unmapped value falls back to its `toString`, which is what `Mapper#toMap` does for the same case rather than failing the whole document.

  - ### appendJsonRaw

    public static void appendJsonRaw(StringBuilder out, Object value)

    Appends `value` exactly as `JSONWriter` would render it if it had been put into the map that `Mapper#toMap` builds.

    This is deliberately NOT `#appendJsonValue`: that one is smarter, turning a `Date` into epoch milliseconds and a mapped object into nested JSON. Where a generated mapper is reproducing what the map path stored RAW -- a `Property` value is the case that matters -- being smarter is being different, and `Mapper.Direct` promises identical output rather than better output.

  - ### appendJsonUsing

    public static void appendJsonUsing(Mapper<?> mapper, Object instance, StringBuilder out)

    Appends `instance` through the mapper the CALLER names, rather than the one registered for the instance's runtime class.

    The distinction is polymorphism. A field declared `Base` holding an instance of an unmapped subclass finds no mapper by runtime class, and `#appendJson(Object, StringBuilder)` then falls back to the quoted `toString`. `Mapper#toMap` looks the mapper up by the DECLARED type and serialises the subclass as an object, so a generated mapper reproducing the map path has to ask the same question. Mirrors what the map path does with a null mapper too: the raw value, which renders as its quoted `toString`.

  - ### appendJsonString

    public static void appendJsonString(StringBuilder sb, String s)

    Appends `s` as an escaped JSON string, or `null`.

    Public because GENERATED mappers call it: a direct writer has to escape exactly the way the map path does, and the only way to guarantee that is for both to use this method rather than each having its own copy.