POJO Categories

The following chart shows POJOs categorized into groups and whether they can be serialized or parsed:

##### General POJO serialization/parsing support

Group | Description | Examples | Can serialize? | Can parse?
--- | --- | --- | --- | ---
1 | Java primitives and primitive objects | {@code String} {@code Integer} {@code Float} {@code Boolean} | yes | yes
2 | Java Collections Framework objects and Java arrays |  |  |
2a | With standard keys/values Map keys are group [1, 4a, 6a] objects. Map, Collection, and array values are group [1, 2, 3ac, 4a, 6a] objects. | `HashSet<String,Integer>` `TreeMap<Integer,Bean>` `List<int[][]>` `Bean[]` | yes | yes
2b | With non-standard keys/values Map keys are group [2, 3, 4b, 5, 6b, 7] objects. Map, Collection, and array values are group [3b, 4b, 5, 6b, 7] objects. | `HashSet<Bean,Integer>` `TreeMap<Integer,Reader>` | yes | no
3 | Java Beans |  |  |
3a | With standard properties These are beans that have one or more properties defined by public getter or public fields. Properties can also be defined as final read-only fields and passed in as constructor args. Property values are group [1, 2, 3ac, 4a, 6a] objects. |  | yes | yes
3b | With non-standard properties or not true beans These include true beans that have one or more properties defined by getter and setter methods or properties, but property types include group [3b, 4b, 5, 6b, 7] objects. This also includes classes that look like beans but aren't true beans. For example, classes that have getters but not setters, or classes without no-arg constructors. |  | yes | no
3c | Virtual beans These are unimplemented bean interfaces with properties of type [1, 2, 3ac, 4a, 6a] objects. Parsers will automatically create interface proxies on top of BeanMap instances. |  | yes | yes
3d | Read-only beans without setters The same as 3a, but without property setters or constructor args. |  | yes | no
4 | Swapped objects These are objects that are not directly serializable, but have {@link oaj.transform.PojoSwap PojoSwaps} associated with them. The purpose of a POJO swap is to convert an object to another object that is easier to serialize and parse. For example, the {@link oaj.transforms.DateSwap.ISO8601DT} class can be used to serialize {@link java.util.Date} objects to ISO8601 strings, and parse them back into {@link java.util.Date} objects. |  |  |
4a | 2-way swapped to group [1, 2a, 3ac] objects For example, a swap that converts a {@code Date} to a {@code String}. | `java.util.Date` `java.util.GregorianCalendar` | yes | yes
4b | 1-way swapped to group [1, 2, 3] objects For example, a swap that converts an {@code Iterator} to a {@code List}. This would be one way, since you cannot reconstruct an {@code Iterator}. | `java.util.Iterator` | yes | no
5 | Readers and InputStreams Contents are serialized directly to the output stream or writer. Typically used for low-level language-specific replacement of POJOs using per-Media-Type POJO swaps. | {@code FileInputStream} {@code StringReader} | yes | no
6 | Non-serializable objects with standard methods for converting to a serializable form |  |  |
6a | Classes with a method that converts it to a serializable form: `public X swap(BeanSession);` where `X` is in groups [1, 2a, 3ac]. `public String toString();` where the string is any meaningful data. And a method that converts it back into the original object: `public static T fromString(String);` `public static T valueOf(String);` `public static T parse(String);` `public static T parseString(String);` `public static T forName(String);` `public static T forString(String);` `public T(X);` where `X` is in groups [1, 2a, 3ac]. `public static T unswap(BeanSession,X);` where `X` is in groups [1, 2a, 3ac]. | `java.lang.Class` `java.sql.Time` `java.sql.Timestamp` `java.text.MessageFormat` `java.text.NumberFormat` `java.util.Date` `java.util.UUID` `java.util.logging.Level` `javax.xml.bind.DatatypeConverter` | yes | yes
6b | Classes that only have a method to convert to a serializable form: `public X swap(BeanSession);` where `X` is in groups [1, 2, 3]. `public String toString();` where the string is any meaningful data. |  | yes | no
7 | All other objects Anything that doesn't fall into one of the groups above are simply converted to {@code Strings} using the {@code toString()} method. |  | yes | no

- Serializers are designed to work on tree-shaped POJO models. These are models where there are no referential loops (e.g. leaves with references to nodes, or nodes in one branch referencing nodes in another branch). There is a serializer setting {@code detectRecursions} to look for and handle these kinds of loops (by setting these references to null), but it is not enabled by default since it introduces a moderate performance penalty.

##### POJOs convertible to/from Strings

A separate category exists for POJOs that can be converted to and from Strings. These are used in places such as:

- Serializing of POJOs to Strings in the REST client API when no serializers are registered.
- Parsing of POJOs from Strings in the REST server API for "text/plain" requests where "text/plain" is not already mapped to an existing serializer.

As a general rule, all POJOs are converted to Strings using the `toString()` method.
However, there is one exception:

- {@link java.util.TimeZone} - Uses {@link java.util.TimeZone#getID()}

POJOs are convertible from Strings using any of the following (matched in the specified order):

- Any any of the following public static non-deprecated methods:
  - `create(String)`
  - `fromString(String)`
  - `fromValue(String)`
  - `valueOf(String)`
  - `parse(String)`
  - `parseString(String)`
  - `forName(String)`
  - `forString(String)`
- Has a public constructor that takes in a `String`.

Exceptions exist for the following classes:

- {@link java.util.TimeZone} - Uses {@link java.util.TimeZone#getTimeZone(String)}
- {@link java.util.Locale} - Uses {@link java.util.Locale#forLanguageTag(String)} after replacing '_' with '-'.
- {@link java.lang.Boolean} - Blank and "null" are interpreted as null values.
- Primitives (except for `void.class`) - Uses the primitive wrapper classes for instantiating from Strings.

##### POJOs convertible to/from other types

POJOs are also converted to various other types in places such as the Open-API serializers and parsers.
In this section, the type being converted to will be referred to as `X`.

POJOs are considered convertible from X if it has any of the following (matched in the specified order):

- Any any of the following public static non-deprecated methods:
  - `create(X)`
  - `from*(X)`
- Has a public constructor that takes in an `X`.
- The X class has a public non-static no-arg non-deprecated method called `to*()`.

POJOs are considered convertible from X if any of the reverse of above are true.