example: add 24 game task of Rosetta code
[nit.git] / lib / json_serialization.nit
index 8b4ee97..b9667db 100644 (file)
@@ -219,49 +219,46 @@ redef class NativeString
        redef fun serialize_to_json(v) do to_s.serialize_to_json(v)
 end
 
-redef class Array[E]
-       redef fun serialize_to_json(v)
+redef class Collection[E]
+       # Utility to serialize a normal Json array
+       private fun serialize_to_pure_json(v: JsonSerializer)
        do
-               if class_name == "Array[nullable Serializable]" then
-                       # Using class_name to the the exact type
-                       # We do not want Array[Int] or anything else here
                        v.stream.write "["
                        var is_first = true
                        for e in self do
                                if is_first then
                                        is_first = false
-                               else v.stream.write(", ")
+                               else v.stream.write ", "
 
                                if not v.try_to_serialize(e) then
                                        v.warn("element of type {e.class_name} is not serializable.")
                                end
                        end
                        v.stream.write "]"
-               else
-                       # Register as pseudo object
-                       var id = v.ref_id_for(self)
-                       v.stream.write "\{\"__kind\": \"obj\", \"__id\": {id}, \"__class\": \"{class_name}\""
-                       v.stream.write """, "__length": {{{length}}}, "__items": ["""
-                       var is_first = true
-                       for e in self do
-                               if is_first then
-                                       is_first = false
-                               else v.stream.write(", ")
+       end
+end
 
-                               if not v.try_to_serialize(e) then
-                                       v.warn("element of type {e.class_name} is not serializable.")
-                               end
-                       end
-                       v.stream.write "]"
-                       v.stream.write "\}"
-               end
+redef class SimpleCollection[E]
+       redef fun serialize_to_json(v)
+       do
+               # Register as pseudo object
+               var id = v.ref_id_for(self)
+               v.stream.write """{"__kind": "obj", "__id": """
+               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": """
+               serialize_to_pure_json v
+               v.stream.write "\}"
        end
 
-       # Instanciate a new `Array` from its serialized representation.
        redef init from_deserializer(v: Deserializer)
        do
                if v isa JsonDeserializer then
                        v.notify_of_creation self
+                       init
 
                        var length = v.deserialize_attribute("__length").as(Int)
                        var arr = v.path.last["__items"].as(SequenceRead[nullable Object])
@@ -273,6 +270,59 @@ redef class Array[E]
        end
 end
 
+redef class Array[E]
+       redef fun serialize_to_json(v)
+       do
+               if 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
+               # Register as pseudo object
+               var id = v.ref_id_for(self)
+
+               v.stream.write """{"__kind": "obj", "__id": """
+               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 """, "__keys": """
+
+               keys.serialize_to_pure_json v
+
+               v.stream.write """, "__values": """
+               values.serialize_to_pure_json v
+               v.stream.write "\}"
+       end
+
+       # Instantiate a new `Array` from its serialized representation.
+       redef init from_deserializer(v: Deserializer)
+       do
+               init
+
+               if v isa JsonDeserializer then
+                       v.notify_of_creation self
+
+                       var length = v.deserialize_attribute("__length").as(Int)
+                       var keys = v.path.last["__keys"].as(SequenceRead[nullable Object])
+                       var values = v.path.last["__values"].as(SequenceRead[nullable Object])
+                       for i in length.times do
+                               var key = v.convert_object(keys[i])
+                               var value = v.convert_object(values[i])
+                               self[key] = value
+                       end
+               end
+       end
+end
+
 # Maps instances to a value, uses `is_same_instance`
 #
 # Warning: This class does not implement all the services from `Map`.