lib/json: parse errors are moved to deserializer errors
[nit.git] / lib / json / serialization.nit
index 4b7cb15..e92a532 100644 (file)
@@ -39,7 +39,7 @@
 # import json::serialization
 #
 # class Person
-#     auto_serializable
+#     serialize
 #
 #     var name: String
 #     var year_of_birth: Int
@@ -182,10 +182,14 @@ class JsonDeserializer
 
        redef fun deserialize_attribute(name)
        do
-               assert not path.is_empty
+               assert not path.is_empty # This is an internal error, abort
                var current = path.last
 
-               assert current.keys.has(name)
+               if not current.keys.has(name) then
+                       errors.add new Error("Deserialization Error: JSON object has not attribute '{name}'.")
+                       return null
+               end
+
                var value = current[name]
 
                return convert_object(value)
@@ -203,31 +207,63 @@ class JsonDeserializer
        # Convert from simple Json object to Nit object
        private fun convert_object(object: nullable Object): nullable Object
        do
+               if object isa JsonParseError then
+                       errors.add object
+                       return null
+               end
+
                if object isa JsonObject then
                        assert object.keys.has("__kind")
                        var kind = object["__kind"]
 
                        # ref?
                        if kind == "ref" then
-                               assert object.keys.has("__id")
+                               if not object.keys.has("__id") then
+                                       errors.add new Error("Serialization Error: JSON object reference does not declare a `__id`.")
+                                       return object
+                               end
+
                                var id = object["__id"]
-                               assert id isa Int
+                               if not id isa Int then
+                                       errors.add new Error("Serialization Error: JSON object reference declares a non-integer `__id`.")
+                                       return object
+                               end
+
+                               if not cache.has_id(id) then
+                                       errors.add new Error("Serialization Error: JSON object reference has an unknown `__id`.")
+                                       return object
+                               end
 
-                               assert cache.has_id(id)
                                return cache.object_for(id)
                        end
 
                        # obj?
                        if kind == "obj" then
-                               assert object.keys.has("__id")
-                               var id = object["__id"]
-                               assert id isa Int
+                               var id = null
+                               if object.keys.has("__id") then
+                                       id = object["__id"]
 
-                               assert object.keys.has("__class")
-                               var class_name = object["__class"]
-                               assert class_name isa String
+                                       if not id isa Int then
+                                               errors.add new Error("Serialization Error: JSON object declaration declares a non-integer `__id`.")
+                                               return object
+                                       end
+
+                                       if cache.has_id(id) then
+                                               errors.add new Error("Serialization Error: JSON object with `__id` {id} is deserialized twice.")
+                                               # Keep going
+                                       end
+                               end
 
-                               assert not cache.has_id(id) else print "Error: Object with id '{id}' of {class_name} is deserialized twice."
+                               if not object.keys.has("__class") then
+                                       errors.add new Error("Serialization Error: JSON object declaration does not declare a `__class`.")
+                                       return object
+                               end
+
+                               var class_name = object["__class"]
+                               if not class_name isa String then
+                                       errors.add new Error("Serialization Error: JSON object declaration declares a non-string `__class`.")
+                                       return object
+                               end
 
                                # advance on path
                                path.push object
@@ -244,17 +280,23 @@ class JsonDeserializer
 
                        # char?
                        if kind == "char" then
-                               assert object.keys.has("__val")
+                               if not object.keys.has("__val") then
+                                       errors.add new Error("Serialization Error: JSON `char` object does not declare a `__val`.")
+                                       return object
+                               end
+
                                var val = object["__val"]
-                               assert val isa String
 
-                               if val.length != 1 then print "Error: expected a single char when deserializing '{val}'."
+                               if not val isa String or val.is_empty then
+                                       errors.add new Error("Serialization Error: JSON `char` object does not declare a single char in `__val`.")
+                                       return object
+                               end
 
                                return val.chars.first
                        end
 
-                       print "Malformed Json string: unexpected Json Object kind '{kind or else "null"}'"
-                       abort
+                       errors.add new Error("Serialization Error: JSON object has an unknown `__kind`.")
+                       return object
                end
 
                if object isa Array[nullable Object] then