Enum Class ClassFormat

java.lang.Object
java.lang.Enum<ClassFormat>
org.apache.juneau.marshall.ClassFormat
All Implemented Interfaces:
Serializable, Comparable<ClassFormat>, Constable

public enum ClassFormat extends Enum<ClassFormat>
Supported wire formats for Class values.

Used by MarshallingContext.Builder.classFormat(ClassFormat), Marshalled.classFormat(), MarshalledProp.classFormat(), and MarshalledConfig.classFormat() to control how Class values are written to text-based wire formats.

The default is FQCN which mirrors the historical ClassSwap behavior (canonical dotted name with sensible fallback to the JVM binary name).

FQCN vs BINARY_NAME for nested classes

For nested-type encoding the two forms diverge:

For arrays the difference is more dramatic:

  • FQCN produces "int[]" / "java.lang.String[]".
  • BINARY_NAME produces "[I" / "[Ljava.lang.String;" (JVM descriptor form).
SIMPLE_NAME is serialize-only

SIMPLE_NAME discards package and outer-class context and is not round-trip safe. The parser path for this constant throws UnsupportedOperationException; use FQCN or BINARY_NAME for round-trippable wires.

Precedence (highest to lowest)
  1. @MarshalledProp(classFormat=…) on the bean property.
  2. @Marshalled(classFormat=…) on the bean class.
  3. @MarshalledConfig(classFormat=…) on @Rest-annotated classes / methods.
  4. Programmatic MarshallingContext.Builder.classFormat(ClassFormat).
  5. Environment variable MarshallingContext.classFormat.
  6. The default constant (FQCN).
Parser leniency

Parsers SHALL try Class.forName(String, boolean, ClassLoader) first regardless of the parser-side ClassFormat setting — this handles BINARY_NAME and most FQCN inputs unambiguously. For nested-type FQCN input ("java.util.Map.Entry"), the parser walks back through dotted segments from right to left, replacing each uppercase-prefixed dot with $ and retrying — this resolves multi-level nesting like "com.example.Outer.Inner.Deepest" to com.example.Outer$Inner$Deepest. For FQCN array input the parser strips trailing [] pairs, resolves the leaf component type (including primitives like "int"), and rebuilds the array via Class.arrayType() — so "int[]" resolves to int[].class and "java.lang.String[][]" resolves to String[][].class.

Binary serializers

Binary serializers (BSON / CBOR / MsgPack / Prototext / Parquet) emit a UTF-8 string regardless of this setting — there is no native Class wire type in any supported binary format.

  • Enum Constant Details

    • NOT_SET

      public static final ClassFormat NOT_SET
      Sentinel meaning "no value configured" — falls through to the next-higher precedence level.
    • FQCN

      public static final ClassFormat FQCN
      Canonical fully-qualified name with dotted nested-type separators (the default).

      Uses Class.getCanonicalName() when available; falls back to Class.getName() for local / anonymous classes where getCanonicalName() returns null.

      Example:

      java.lang.String java.util.Map.Entry int[]

    • BINARY_NAME

      public static final ClassFormat BINARY_NAME
      JVM binary name per Class.getName().
      Example:

      java.lang.String java.util.Map$Entry [Ljava.lang.String; [I

      Identical to FQCN for top-level non-array reference types; diverges for nested types ($ vs .) and arrays (JVM descriptor vs Type[] form).

    • SIMPLE_NAME

      public static final ClassFormat SIMPLE_NAME
      Unqualified simple name per Class.getSimpleName().
      Example:

      java.lang.String Entry int

      Serialize-only. The parser path for this constant throws UnsupportedOperationException — there is no defensible way to resolve "Map" back to a unique Class without a registry hint, and adding such a hint is out of scope.

  • Method Details

    • values

      public static ClassFormat[] values()
      Returns an array containing the constants of this enum class, in the order they are declared.
      Returns:
      an array containing the constants of this enum class, in the order they are declared
    • valueOf

      public static ClassFormat valueOf(String name)
      Returns the enum constant of this class with the specified name. The string must match exactly an identifier used to declare an enum constant in this class. (Extraneous whitespace characters are not permitted.)
      Parameters:
      name - the name of the enum constant to be returned.
      Returns:
      the enum constant with the specified name
      Throws:
      IllegalArgumentException - if this enum class has no constant with the specified name
      NullPointerException - if the argument is null
    • setClassNameGuard

      public static void setClassNameGuard(Predicate<String> value)
      Installs a global guard that vets class names before the parser path resolves them to a Class.

      The guard is consulted for every candidate name (including the nested-type $-rewritten forms) before it is passed to Class.forName(String, boolean, ClassLoader). Names the guard rejects are treated as unresolvable. This lets a deployment restrict which types may be materialized from parsed input to an explicit allow-list.

      Parameters:
      value - The guard predicate returning true for permitted class names, or null to allow all names (the default).
    • format

      public static String format(Class<?> value, ClassFormat format)
      Formats the specified Class using this format.

      NOT_SET / null format are treated as FQCN.

      Parameters:
      value - The value to format. Can be null (returns null).
      format - The configured format. Can be null (treated as FQCN).
      Returns:
      The formatted wire representation, or null if value is null.
    • parse

      public static Class<?> parse(String value, ClassFormat format, ClassLoader classLoader)
      Parses the specified wire value into a Class.

      Lenient parsing — handles every shape produced by format(Class, ClassFormat) for the round-trippable formats (FQCN and BINARY_NAME), and accepts cross-form input as well (an FQCN parser still resolves BINARY_NAME input and vice versa).

      Resolution steps:

      1. Strip trailing [] pairs (FQCN array form), tracking dimension count. Empty brackets at the leading edge (JVM descriptor form like "[I" / "[Ljava.lang.String;") are left to Class.forName(String, boolean, ClassLoader) because that method already handles them.
      2. Resolve the leaf component:
        • If the leaf names a primitive type ("int", "boolean", etc. — emitted by FQCN for primitive arrays), return the corresponding TYPE class.
        • Otherwise try Class.forName(String, boolean, ClassLoader) directly.
        • On failure, walk dots from right to left, replacing each uppercase-prefixed dot with $ (cumulatively — already-replaced dots stay replaced) and retrying. This resolves multi-level nesting like "com.example.Outer.Inner.Deepest" to com.example.Outer$Inner$Deepest. Dots whose trailing segment starts with a lowercase letter are treated as package boundaries and skipped.
      3. Apply Class.arrayType() once per stripped dimension to rebuild the array class.

      SIMPLE_NAME is not supported on the parser side — throws UnsupportedOperationException.

      Parameters:
      value - The wire value. Can be null or blank (returns null).
      format - The configured format hint. Can be null (treated as FQCN).
      classLoader - The class loader. Can be null (uses context class loader).
      Returns:
      The parsed Class, or null if value is null or blank.
      Throws:
      IllegalArgumentException - If the value cannot be resolved.
      UnsupportedOperationException - If format is SIMPLE_NAME.
    • isNumeric

      public boolean isNumeric()
      Returns true if this format emits a numeric wire value.

      Always false — every constant emits a textual representation.

      Returns:
      false.