# import json::serialization
#
# class Person
-# auto_serializable
+# serialize
#
# var name: String
# var year_of_birth: Int
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)
# 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"]
+ var kind = null
+ if object.keys.has("__kind") then
+ kind = object["__kind"]
+ end
# 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
+ if kind == "obj" or kind == null then
+ var id = null
+ if object.keys.has("__id") then
+ id = object["__id"]
+
+ if not id isa Int then
+ errors.add new Error("Serialization Error: JSON object declaration declares a non-integer `__id`.")
+ return object
+ end
- assert object.keys.has("__class")
- var class_name = object["__class"]
- assert class_name isa String
+ if cache.has_id(id) then
+ errors.add new Error("Serialization Error: JSON object with `__id` {id} is deserialized twice.")
+ # Keep going
+ end
+ end
+
+ if not object.keys.has("__class") then
+ errors.add new Error("Serialization Error: JSON object declaration does not declare a `__class`.")
+ return object
+ end
- assert not cache.has_id(id) else print "Error: Object with id '{id}' of {class_name} is deserialized twice."
+ 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
# 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
return object
end
- redef fun deserialize do return convert_object(root)
+ redef fun deserialize
+ do
+ errors.clear
+ return convert_object(root)
+ end
end
redef class Serializable
v.stream.write id.to_s
v.stream.write """, "__class": """"
v.stream.write class_name
- v.stream.write """", "__length": """
- v.stream.write length.to_s
- v.stream.write """, "__items": """
+ v.stream.write """", "__items": """
end
serialize_to_pure_json v
v.notify_of_creation self
init
- var length = v.deserialize_attribute("__length").as(Int)
var arr = v.path.last["__items"].as(SequenceRead[nullable Object])
- for i in length.times do
- var obj = v.convert_object(arr[i])
+ for o in arr do
+ var obj = v.convert_object(o)
self.add obj
end
end
end
end
-redef class Array[E]
- redef fun serialize_to_json(v)
- do
- if v.plain_json or class_name == "Array[nullable Serializable]" then
- # Using class_name to get the exact type,
- # we do not want Array[Int] or anything else here.
-
- serialize_to_pure_json v
- else super
- end
-end
-
redef class Map[K, V]
redef fun serialize_to_json(v)
do