lib/json_serialization: clean up
[nit.git] / lib / json_serialization.nit
index 6a2d82a..e8c76b4 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Handles serialization and deserialization of objects to/from Json.
 module json_serialization
 
 import serialization
 import json::static
 
+# Serializer of Nit objects to Json string.
 class JsonSerializer
        super Serializer
 
        # Target writing stream
-       var stream: OStream
-
-       init(stream: OStream) do self.stream = stream
+       var stream: Writer
 
        redef fun serialize(object)
        do
@@ -52,9 +52,10 @@ class JsonSerializer
                end
        end
 
-       # Map of references to already serialized objects
+       # Map of references to already serialized objects.
        var refs_map = new HashMap[Serializable,Int]
 
+       # Get the internal serialized reference for this `object`.
        private fun ref_id_for(object: Serializable): Int
        do
                if refs_map.keys.has(object) then
@@ -67,20 +68,30 @@ class JsonSerializer
        end
 end
 
-# Deserializer from a Json string
+# Deserializer from a Json string.
 class JsonDeserializer
        super Deserializer
 
-       var root: nullable Object
-       var path = new Array[HashMap[String, nullable Object]]
+       # Json text to deserialize from.
+       private var text: Text
+
+       # Root json object parsed from input text.
+       var root: nullable Jsonable is noinit
+
+       # Depth-first path in the serialized object tree.
+       var path = new Array[JsonObject]
+
+       # Map of refenrences to already deserialized objects.
        var id_to_object = new HashMap[Int, Object]
 
+       # Last encountered object reference id.
+       #
+       # See `id_to_object`.
        var just_opened_id: nullable Int = null
 
-       init(text: Text)
-       do
-               var root = text.json_to_nit_object
-               if root isa HashMap[String, nullable Object] then path.add(root)
+       init do
+               var root = text.parse_json
+               if root isa JsonObject then path.add(root)
                self.root = root
        end
 
@@ -91,7 +102,7 @@ class JsonDeserializer
 
                assert current.keys.has(name)
                var value = current[name]
-               
+
                return convert_object(value)
        end
 
@@ -107,7 +118,7 @@ class JsonDeserializer
        # Convert from simple Json object to Nit object
        private fun convert_object(object: nullable Object): nullable Object
        do
-               if object isa HashMap[String, nullable Object] then
+               if object isa JsonObject then
                        assert object.keys.has("__kind")
                        var kind = object["__kind"]
 
@@ -153,7 +164,7 @@ class JsonDeserializer
                                assert val isa String
 
                                if val.length != 1 then print "Error: expected a single char when deserializing '{val}'."
-                               
+
                                return val.chars.first
                        end
 
@@ -197,18 +208,11 @@ redef class Bool
 end
 
 redef class Char
-       redef fun serialize_to_json(v) do v.stream.write "\{\"__kind\": \"char\", \"__val\": \"{to_s.to_json_s}\"\}"
+       redef fun serialize_to_json(v) do v.stream.write "\{\"__kind\": \"char\", \"__val\": {to_s.to_json}\}"
 end
 
 redef class String
-       redef fun serialize_to_json(v) do v.stream.write("\"{to_json_s}\"")
-
-       private fun to_json_s: String do return self.replace("\\", "\\\\").
-               replace("\"", "\\\"").replace("/", "\\/").
-               replace("\n", "\\n").replace("\r", "\\r").replace("\t", "\\t")
-               # FIXME add support for unicode char when supported by Nit strings
-               # FIXME add support for \f! # .replace("\f", "\\f")
-               # FIXME add support for \b .replace("\b", "\\b")
+       redef fun serialize_to_json(v) do v.stream.write(to_json)
 end
 
 redef class NativeString
@@ -253,13 +257,14 @@ redef class Array[E]
                end
        end
 
+       # Instanciate a new `Array` from its serialized representation.
        init from_deserializer(v: Deserializer)
        do
                if v isa JsonDeserializer then
                        v.notify_of_creation self
 
                        var length = v.deserialize_attribute("__length").as(Int)
-                       var arr = v.path.last["__items"].as(Array[nullable Object])
+                       var arr = v.path.last["__items"].as(SequenceRead[nullable Object])
                        for i in length.times do
                                var obj = v.convert_object(arr[i])
                                self.add obj