Reviving polymorphic JSON
The built-in metadata covers the bulk of use cases. However, to deal with types whose JSON might take more than one form, you will need a custom reviving strategy.
We are going to walk through two examples: first, we will revive objects based on an enumerated field that will indicate how the object should be revived; second, we will revive objects based on their shape only, without any additional fields.
To deal with fields where several subclasses of the declared type would need to be revived, see the "runtime type" recipe.
Example 1: revive based on an enumerated field
We are going to create a NumberCollection
class which models either an M.StringMap
or an M.List
to parse JSON like this:
Note: the convention is to name the type field as simply type
, but we will continue with collectionType
to show that it is up to you.
First, we can use M.Enum
to create CollectionType
:
Now, we can create our NumberCollection
class:
Note that the value for each field in innerTypes
can be either metadata or a metadata-returning function that will be passed the plain object being revived.
We can now use it as follows:
In this case, the serialisation side of things will work out of the box, since M.List
, M.StringMap
and our CollectionType
implemented with an M.Enum
, implement .toJSON()
methods on their instances:
Example 2: revive based on the shape of the value
First, it is worth mentioning this is not always possible, as the shape of the JSON representation might be ambiguous (see example in Gson's RuntimeTypeAdapterFactory).
In this example, we are going to revive the same polymorphic JSON as the one above, but without an enumerated field to hint the type of the collection.
The end result is simpler, but less generic. It might require non-trivial updates to the logic that figures out which metadata to use. For example, if we start supporting map(number())
, whose JSON representation is an array of pairs, Array.isArray
will not be enough.
Last updated