# use double dispatch to customize the bahavior per serializable objects.
fun serialize(object: nullable Serializable) is abstract
+ # The object currently serialized by `serialized`
+ #
+ # Can be used by a custom serializer to add domain-specific serialization behavior.
+ protected fun current_object: nullable Object is abstract
+
# Serialize an object, with full serialization or a simple reference
protected fun serialize_reference(object: Serializable) is abstract
return true
end
+ # The method is called when a standard `value` is serialized
+ #
+ # The default behavior is to call `value.core_serialize_to(self)` but it
+ # can be redefined by a custom serializer to add domain-specific serialization behavior.
+ fun serialize_core(value: Serializable)
+ do
+ value.core_serialize_to(self)
+ end
+
# Warn of problems and potential errors (such as if an attribute
# is not serializable)
fun warn(msg: String) do print "Serialization warning: {msg}"
# Abstract deserialization service
#
-# After initialization of one of its sub-classes, call `deserialize`
+# The main service is `deserialize`.
abstract class Deserializer
- # Main method of this class, returns a Nit object
- fun deserialize: nullable Object is abstract
+ # Deserialize and return an object, storing errors in the attribute `errors`
+ #
+ # If a `static_type` is given, only subtypes of the `static_type` are accepted.
+ #
+ # This method behavior varies according to the implementation engines.
+ fun deserialize(static_type: nullable String): nullable Object is abstract
- # Internal method to be implemented by sub-classes
- fun deserialize_attribute(name: String): nullable Object is abstract
+ # Deserialize the attribute with `name` from the object open for deserialization
+ #
+ # The `static_type` can be used as last resort if the deserialized object
+ # desn't have any metadata declaring the dynamic type.
+ #
+ # Return the deserialized value or null on error, and set
+ # `deserialize_attribute_missing` to whether the attribute was missing.
+ #
+ # Internal method to be implemented by the engines.
+ fun deserialize_attribute(name: String, static_type: nullable String): nullable Object is abstract
+
+ # Was the attribute queried by the last call to `deserialize_attribute` missing?
+ var deserialize_attribute_missing = false
- # Internal method called by objects in creation,
- # to be implemented by sub-classes
+ # Register a newly allocated object (even if not completely built)
+ #
+ # Internal method called by objects in creation, to be implemented by the engines.
fun notify_of_creation(new_object: Object) is abstract
# Deserialize the next available object as an instance of `class_name`
#
- # Returns the deserialized object on success, aborts on error.
+ # Return the deserialized object on success and
+ # record in `errors` if `class_name` is unknown.
#
# This method should be redefined for each custom subclass of `Serializable`.
# All refinement should look for a precise `class_name` and call super
var errors = new Array[Error]
end
-# Deserialization got wrong attribute names
+# Error on invalid dynamic type for a deserialized attribute
class AttributeTypeError
super Error
+ autoinit receiver, attribute_name, attribute, expected_type
+
# Parent object of the problematic attribute
var receiver: Object
# Name of the type expected for `attribute`
var expected_type: String
- redef fun to_s
- do
+ redef var message is lazy do
var attribute = attribute
var found_type = if attribute != null then attribute.class_name else "null"
redef class Char super DirectSerializable end
redef class Int super DirectSerializable end
redef class Float super DirectSerializable end
-redef class NativeString super DirectSerializable end
+redef class CString super DirectSerializable end
redef class Text super DirectSerializable end
redef class SimpleCollection[E] super Serializable end
redef class Map[K, V] super Serializable end