Serializing means that from object data a byte stream data is created.
Deserializing means that from a byte stream data an object data is created.
In case for a class these two conversions are well-defined and they are exactly the inverted process of themselves, that means that class is serializable.
A class is serializable when all of its fields are as well.
All wrapper classes, enums, array and List classes etc. are serializable by default, for the latter two the elements must be serializable as well.
Primitive types are boxed/unboxed automatically.
In case a class is serializable, all of its child (inheriting) classes will be as well unless a new field is added which is not serializable.
The process is executed by ObjectInputStream and ObjectOutputStream.
If an object is not eligible for the process, calling either methods results IOException, for deserializing ClassNotFoundException as well.
Serialization and deserialization take place in communication between server and client on the network. The transferred data is usually in JSON or XML format.
In web app, in case exception is raised during deserialization, the server response will be 4xx since the control endpoint does not receive proper data.
The process follows the structure of the class while the data will contain an instance of it.
Static fields will not be serialized, fields marked with transient access modifier neither. Having static and transient fields will not throw exception during process, these fields will be skipped.
In case the class is serializable by itself (following the information above), no special coding is necessary.
EXAMPLE FOR A SERIALIZABLE CLASS:
Not-serializable classes can be made to be one by expressing the two methods needed for serialization (contained by Serializable, used by ObjectInputStream and ObjectOutputStream).
Within these two methods the not-serializable fields will be converted to serializable form and back.
In a class a serialVersionUID field can be defined and a unique value per class can be associated in design-time.
This value is generated by some IDE platforms automatically (from class name, attributes and access modifiers) whilst other IDEs need manually defined value.
This long value is unique for a serializable class and makes the serialization-deserialization possible in platform-independent manner.
In case this ID is not defined and not generated by the IDE, the JVM will generate an ID for that class. This number will be compiler-dependent and may cause InvalidClassException.
The UID field and the two methods connected to serialization, should be marked with the @Serial annotation which helps the app to identify these data in-situ.
EXAMPLE FOR CUSTOM SERIALIZABLE CLASS (METHODS IN-PLACE):
EXAMPLE FOR CUSTOM SERIALIZABLE CLASS (METHODS IN OUTER CLASS):
EXAMPLE FOR CHECKING SERIALIZATION CAPABILITY (CLASS):
EXAMPLE FOR CHECKING SERIALIZATION CAPABILITY (OBJECT):
There are three ways to convert an object to JSON: by using built-in Jackson, external Jackson and external GSON libraries.
The built-in Jackson, based upon tests, can not deal with more complex objects (e.g. which contain LocalDate field).
The older Spring Boot framework used the built-in Jackson parser, however, in the newer versions they changed their parser to be more flexible.
EXAMPLE FOR CONVERTING OBJECT TO JSON STRING (BUILT-IN JACKSON, ESCAPED QUOTE MARKS):
EXAMPLE FOR CONVERTING OBJECT TO JSON STRING (BUILT-IN JACKSON, NOT-ESCAPED QUOTE MARKS):
EXAMPLE FOR CONVERTING OBJECT TO JSON STRING (BUILT-IN JACKSON, ESCAPED QUOTE MARKS, FORMATTED):
EXAMPLE FOR CONVERTING OBJECT TO JSON STRING (BUILT-IN JACKSON, THROUGH JSON OBJECT, ESCAPED QUOTE MARKS, FORMATTED):