X-Git-Url: http://nitlanguage.org diff --git a/lib/serialization/serialization.nit b/lib/serialization/serialization.nit index 8977baa..7c689b6 100644 --- a/lib/serialization/serialization.nit +++ b/lib/serialization/serialization.nit @@ -16,7 +16,7 @@ # Abstract services to serialize Nit objects to different formats # -# This module declares the `auto_serializable` annotation to mark Nit classes as serializable. +# This module declares the `serialize` annotation to mark Nit classes as serializable. # For an introduction to this service, refer to the documentation of the `serialization` group. # This documentation provides more technical information on interesting entitie of this module. # @@ -44,6 +44,8 @@ # `notify_of_creation` must be redefined. module serialization is new_annotation auto_serializable + new_annotation serialize + new_annotation noserialize end # Abstract serialization service to be sub-classed by specialized services. @@ -86,7 +88,7 @@ end # Abstract deserialization service # # After initialization of one of its sub-classes, call `deserialize` -interface Deserializer +abstract class Deserializer # Main method of this class, returns a Nit object fun deserialize: nullable Object is abstract @@ -104,9 +106,60 @@ interface Deserializer # This method should be redefined for each custom subclass of `Serializable`. # All refinement should look for a precise `class_name` and call super # on unsupported classes. - fun deserialize_class(class_name: String): Object do - print "Error: doesn't know how to deserialize class \"{class_name}\"" - abort + protected fun deserialize_class(class_name: String): nullable Object do + return deserialize_class_intern(class_name) + end + + # Generated service to deserialize the next available object as an instance of `class_name` + # + # Refinements to this method will be generated by the serialization phase. + # To avoid conflicts, there should not be any other refinements to this method. + # You can instead use `deserialize_class`. + protected fun deserialize_class_intern(class_name: String): nullable Object do + errors.add new Error("Deserialization Error: Doesn't know how to deserialize class \"{class_name}\"") + return null + end + + # Should `self` keep trying to deserialize an object after an error? + # + # This behavior takes effect after each attribute deserialization with + # errors such as a missing attribute or the value is of the wrong type. + # If `keep_going`, the attribute will be skipped but the engine will + # deserialize the next attribute. + # If `not keep_going`, the engine stops deserializing right away. + # + # When at `true`, this may cause the accumulation of a lot of entries in `errors`. + # + # Default at `true`. + var keep_going: nullable Bool = null is writable + + # Errors encountered in the last call to `deserialize` + var errors = new Array[Error] +end + +# Deserialization got wrong attribute names +class AttributeTypeError + super Error + + # Parent object of the problematic attribute + var receiver: Object + + # Name of the problematic attribute in `receiver` + var attribute_name: String + + # Deserialized object that isn't of the `expected_type` + var attribute: nullable Object + + # Name of the type expected for `attribute` + var expected_type: String + + redef fun to_s + do + var attribute = attribute + var found_type = if attribute != null then attribute.class_name else "null" + + return "Deserialization Error: { + }Wrong type on `{receiver.class_name}::{attribute_name}` expected `{expected_type}`, got `{found_type}`" end end @@ -138,7 +191,7 @@ interface Serializable # Create an instance of this class from the `deserializer` # # This constructor is refined by subclasses to correctly build their instances. - init from_deserializer(deserializer: Deserializer) do end + init from_deserializer(deserializer: Deserializer) is nosuper do end end redef interface Object @@ -189,7 +242,7 @@ redef class Couple[F, S] end end -redef class Container[E] +redef class Ref[E] super Serializable redef init from_deserializer(v)