Merge: Missing a unboxing when compiling a call to `new NativeArray`
authorJean Privat <jean@pryen.org>
Sat, 23 May 2015 01:01:18 +0000 (21:01 -0400)
committerJean Privat <jean@pryen.org>
Sat, 23 May 2015 01:01:18 +0000 (21:01 -0400)
In the following code,

~~~nit
var i
i = 4
var na = new NativeArray[Object](i)
~~~

the declaration type of `i` is `nullable Object`, so the C-type of `i` is `val*` (and not `int`).
Therefore, in the `new NativeArray`, it should be unboxed because the C signature expect a `int`.

Pull-Request: #1365
Reviewed-by: Alexis Laferrière <alexis.laf@xymus.net>
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>

21 files changed:
contrib/benitlux/src/benitlux_controller.nit
lib/android/bundle/bundle.nit
lib/android/intent/intent_api10.nit
lib/android/shared_preferences/shared_preferences_api10.nit
lib/json/serialization.nit [moved from lib/json_serialization.nit with 53% similarity]
lib/linux/data_store.nit
lib/mpi.nit
lib/serialization/engine_tools.nit [new file with mode: 0644]
lib/standard/file.nit
tests/sav/nitg-e/test_deserialization_serial.res [deleted file]
tests/sav/nitg-e/test_json_deserialization_alt1.res [moved from tests/sav/nitg-e/test_deserialization.res with 100% similarity]
tests/sav/nitserial_args1.res
tests/sav/test_deserialization.res [deleted file]
tests/sav/test_json_deserialization.res [moved from tests/sav/test_deserialization_alt1.res with 100% similarity]
tests/sav/test_json_deserialization_alt1.res [moved from tests/sav/test_deserialization_serial.res with 100% similarity]
tests/sav/test_json_deserialization_alt2.res [new file with mode: 0644]
tests/sav/test_serialization_alt1.res [new file with mode: 0644]
tests/test_deserialization.nit
tests/test_deserialization_serial.nit
tests/test_json_deserialization.nit [new file with mode: 0644]
tests/test_serialization.nit

index 2297bbd..f124315 100644 (file)
@@ -18,7 +18,7 @@
 module benitlux_controller
 
 import nitcorn
-import json_serialization
+private import json::serialization
 
 import benitlux_model
 import benitlux_db
index 3678cbc..19b2f8e 100644 (file)
@@ -19,7 +19,7 @@
 module bundle
 
 import serialization
-import json_serialization
+import json::serialization
 
 import platform
 import activities
index 5f37179..5312c15 100644 (file)
@@ -21,7 +21,7 @@ module intent_api10
 import dalvik
 import android::bundle
 import serialization
-private import json_serialization
+private import json::serialization
 
 in "Java" `{
        import android.content.Intent;
index 72a634c..84d213d 100644 (file)
@@ -19,11 +19,11 @@ module shared_preferences_api10
 
 import dalvik
 import serialization
-private import json_serialization
+private import json::serialization
 
 in "Java" `{
        import android.content.SharedPreferences;
-       import android.content.Context; 
+       import android.content.Context;
        import android.app.Activity;
        import java.util.Map;
        import java.util.Iterator;
similarity index 53%
rename from lib/json_serialization.nit
rename to lib/json/serialization.nit
index b9667db..61c6f61 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
+# Handles serialization and deserialization of objects to/from JSON
+#
+# ## Nity JSON
+#
+# `JsonSerializer` write Nit objects that subclass `Serializable` to JSON,
+# and `JsonDeserializer` can read them. They both use meta-data added to the
+# generated JSON to recreate the Nit instances with the exact original type.
+#
+# For more information on Nit serialization, see: ../serialization/README.md
+#
+# ## Plain JSON
+#
+# The attribute `JsonSerializer::plain_json` triggers generating plain and
+# clean JSON. This format is easier to read for an human and a non-Nit program,
+# but it cannot be fully deserialized. It can still be read by services from
+# `json::static` and `json::dynamic`.
+#
+# A shortcut to this service is provided by `Serializable::to_plain_json`.
+#
+# ### Usage Example
+#
+# ~~~nitish
+# import json::serialization
+#
+# class Person
+#     auto_serializable
+#
+#     var name: String
+#     var year_of_birth: Int
+#     var next_of_kin: nullable Person
+# end
+#
+# var bob = new Person("Bob", 1986)
+# var alice = new Person("Alice", 1978, bob)
+#
+# assert bob.to_plain_json == """
+# {"name": "Bob", "year_of_birth": 1986, "next_of_kin": null}"""
+#
+# assert alice.to_plain_json == """
+# {"name": "Alice", "year_of_birth": 1978, "next_of_kin": {"name": "Bob", "year_of_birth": 1986, "next_of_kin": null}}"""
+# ~~~
+module serialization
 
-import serialization
-import json::static
+import ::serialization
+private import ::serialization::engine_tools
+private import static
 
 # Serializer of Nit objects to Json string.
 class JsonSerializer
@@ -27,25 +68,87 @@ class JsonSerializer
        # Target writing stream
        var stream: Writer
 
+       # Write plain JSON? easier to read but does not support Nit deserialization
+       #
+       # If `false`, the default, serialize to support deserialization:
+       #
+       # * Write meta-data, including the types of the serialized objects so they can
+       #   be deserialized to their original form using `JsonDeserializer`.
+       # * Use references when an object has already been serialized so to not duplicate it.
+       # * Support cycles in references.
+       # * Preserve the Nit `Char` type as an object because it does not exist in JSON.
+       # * The generated JSON is standard and can be read by non-Nit programs.
+       #   However, some Nit types are not represented by the simplest possible JSON representation.
+       #   With the added meta-data, it can be complex to read.
+       #
+       # If `true`, serialize for other programs:
+       #
+       # * Nit objects are serialized to pure and standard JSON so they can
+       #   be easily read by non-Nit programs and humans.
+       # * Nit objects are serialized for every references, so they can be duplicated.
+       #   It is easier to read but it creates a larger output.
+       # * Does not support cycles, will replace the problematic references by `null`.
+       # * Does not serialize the meta-data needed to deserialize the objects
+       #   back to regular Nit objects.
+       # * Keys of Nit `HashMap` are converted to their string reprensentation using `to_s`.
+       var plain_json = false is writable
+
+       # List of the current open objects, the first is the main target of the serialization
+       #
+       # Used only when `plain_json == true` to detect cycles in serialization.
+       private var open_objects = new Array[Object]
+
+       # Has the first attribute of the current object already been serialized?
+       #
+       # Used only when `plain_json == true`.
+       private var first_attribute = false
+
        redef fun serialize(object)
        do
                if object == null then
                        stream.write "null"
-               else object.serialize_to_json(self)
+               else
+                       if plain_json then
+                               for o in open_objects do
+                                       if object.is_same_serialized(o) then
+                                               # Cycle detected
+                                               stream.write "null"
+                                               return
+                                       end
+                               end
+
+                               open_objects.add object
+                       end
+
+                       first_attribute = true
+                       object.serialize_to_json self
+                       first_attribute = false
+
+                       if plain_json then open_objects.pop
+               end
        end
 
        redef fun serialize_attribute(name, value)
        do
-               stream.write ", \"{name}\": "
+               if not plain_json or not first_attribute then
+                       stream.write ", "
+                       first_attribute = false
+               end
+
+               stream.write "\""
+               stream.write name
+               stream.write "\": "
                super
        end
 
        redef fun serialize_reference(object)
        do
-               if refs_map.has_key(object) then
+               if not plain_json and refs_map.has_key(object) then
                        # if already serialized, add local reference
                        var id = ref_id_for(object)
-                       stream.write "\{\"__kind\": \"ref\", \"__id\": {id}\}"
+                       stream.write "\{\"__kind\": \"ref\", \"__id\": "
+                       stream.write id.to_s
+                       stream.write "\}"
                else
                        # serialize here
                        serialize object
@@ -76,10 +179,10 @@ class JsonDeserializer
        private var text: Text
 
        # Root json object parsed from input text.
-       var root: nullable Jsonable is noinit
+       private var root: nullable Jsonable is noinit
 
        # Depth-first path in the serialized object tree.
-       var path = new Array[JsonObject]
+       private var path = new Array[JsonObject]
 
        # Map of references to already deserialized objects.
        private var id_to_object = new StrictHashMap[Int, Object]
@@ -189,10 +292,31 @@ redef class Serializable
        private fun serialize_to_json(v: JsonSerializer)
        do
                var id = v.ref_id_for(self)
-               v.stream.write "\{\"__kind\": \"obj\", \"__id\": {id}, \"__class\": \"{class_name}\""
+               v.stream.write "\{"
+               if not v.plain_json then
+                       v.stream.write "\"__kind\": \"obj\", \"__id\": "
+                       v.stream.write id.to_s
+                       v.stream.write ", \"__class\": \""
+                       v.stream.write class_name
+                       v.stream.write "\""
+               end
                core_serialize_to(v)
                v.stream.write "\}"
        end
+
+       # Serialize this object to plain JSON
+       #
+       # This is a shortcut using `JsonSerializer::plain_json`,
+       # see its documentation for more information.
+       fun to_plain_json: String
+       do
+               var stream = new StringWriter
+               var serializer = new JsonSerializer(stream)
+               serializer.plain_json = true
+               serializer.serialize self
+               stream.close
+               return stream.to_s
+       end
 end
 
 redef class Int
@@ -208,7 +332,16 @@ redef class Bool
 end
 
 redef class Char
-       redef fun serialize_to_json(v) do v.stream.write "\{\"__kind\": \"char\", \"__val\": {to_s.to_json}\}"
+       redef fun serialize_to_json(v)
+       do
+               if v.plain_json then
+                       v.stream.write to_s.to_json
+               else
+                       v.stream.write "\{\"__kind\": \"char\", \"__val\": "
+                       v.stream.write to_s.to_json
+                       v.stream.write "\}"
+               end
+       end
 end
 
 redef class String
@@ -242,16 +375,22 @@ 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": """
+               if not v.plain_json then
+                       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": """
+               end
+
                serialize_to_pure_json v
-               v.stream.write "\}"
+
+               if not v.plain_json then
+                       v.stream.write "\}"
+               end
        end
 
        redef init from_deserializer(v: Deserializer)
@@ -273,7 +412,7 @@ end
 redef class Array[E]
        redef fun serialize_to_json(v)
        do
-               if class_name == "Array[nullable Serializable]" then
+               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.
 
@@ -288,19 +427,40 @@ redef class Map[K, V]
                # 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": """
+               if v.plain_json then
+                       v.stream.write "\{"
+                       var first = true
+                       for key, val in self do
+                               if not first then
+                                       v.stream.write ", "
+                               else first = false
+
+                               if key == null then key = "null"
+
+                               v.stream.write key.to_s.to_json
+                               v.stream.write ": "
+                               if not v.try_to_serialize(val) then
+                                       v.warn("element of type {val.class_name} is not serializable.")
+                                       v.stream.write "null"
+                               end
+                       end
+                       v.stream.write "\}"
+               else
+                       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
 
-               keys.serialize_to_pure_json v
+                       v.stream.write """, "__keys": """
+                       keys.serialize_to_pure_json v
 
-               v.stream.write """, "__values": """
-               values.serialize_to_pure_json v
-               v.stream.write "\}"
+                       v.stream.write """, "__values": """
+                       values.serialize_to_pure_json v
+
+                       v.stream.write "\}"
+               end
        end
 
        # Instantiate a new `Array` from its serialized representation.
@@ -322,59 +482,3 @@ redef class Map[K, V]
                end
        end
 end
-
-# Maps instances to a value, uses `is_same_instance`
-#
-# Warning: This class does not implement all the services from `Map`.
-private class StrictHashMap[K, V]
-       super Map[K, V]
-
-       # private
-       var map = new HashMap[K, Array[Couple[K, V]]]
-
-       redef var length = 0
-
-       redef fun is_empty do return length == 0
-
-       # private
-       fun node_at(key: K): nullable Couple[K, V]
-       do
-               if not map.keys.has(key) then return null
-
-               var arr = map[key]
-               for couple in arr do
-                       if couple.first.is_same_serialized(key) then
-                               return couple
-                       end
-               end
-
-               return null
-       end
-
-       redef fun [](key)
-       do
-               var node = node_at(key)
-               assert node != null
-               return node.second
-       end
-
-       redef fun []=(key, value)
-       do
-               var node = node_at(key)
-               if node != null then
-                       node.second = value
-                       return
-               end
-
-               var arr
-               if not map.keys.has(key) then
-                       arr = new Array[Couple[K, V]]
-                       map[key] = arr
-               else arr = map[key]
-
-               arr.add new Couple[K, V](key, value)
-               self.length += 1
-       end
-
-       redef fun has_key(key) do return node_at(key) != null
-end
index 5743d82..8291616 100644 (file)
@@ -20,7 +20,7 @@ module data_store
 import app::data_store
 private import xdg_basedir
 private import sqlite3
-private import json_serialization
+private import json::serialization
 
 redef class App
        redef var data_store = new LinuxStore
index 5696d32..69d0d9f 100644 (file)
@@ -33,7 +33,7 @@ end
 import c
 intrude import standard::string
 import serialization
-private import json_serialization
+private import json::serialization
 
 in "C Header" `{
        #include <mpi.h>
diff --git a/lib/serialization/engine_tools.nit b/lib/serialization/engine_tools.nit
new file mode 100644 (file)
index 0000000..1e0ee0b
--- /dev/null
@@ -0,0 +1,74 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Advanced services for serialization engines
+module engine_tools
+
+import serialization
+
+# Maps instances to a value, uses `is_same_instance`
+#
+# Warning: This class does not implement all the services from `Map`.
+class StrictHashMap[K, V]
+       super Map[K, V]
+
+       # private
+       var map = new HashMap[K, Array[Couple[K, V]]]
+
+       redef var length = 0
+
+       redef fun is_empty do return length == 0
+
+       # private
+       fun node_at(key: K): nullable Couple[K, V]
+       do
+               if not map.keys.has(key) then return null
+
+               var arr = map[key]
+               for couple in arr do
+                       if couple.first.is_same_serialized(key) then
+                               return couple
+                       end
+               end
+
+               return null
+       end
+
+       redef fun [](key)
+       do
+               var node = node_at(key)
+               assert node != null
+               return node.second
+       end
+
+       redef fun []=(key, value)
+       do
+               var node = node_at(key)
+               if node != null then
+                       node.second = value
+                       return
+               end
+
+               var arr
+               if not map.keys.has(key) then
+                       arr = new Array[Couple[K, V]]
+                       map[key] = arr
+               else arr = map[key]
+
+               arr.add new Couple[K, V](key, value)
+               self.length += 1
+       end
+
+       redef fun has_key(key) do return node_at(key) != null
+end
index 5324f01..1490ee7 100644 (file)
@@ -1024,39 +1024,23 @@ redef class String
        #     assert files.is_empty
        #
        # TODO find a better way to handle errors and to give them back to the user.
-       fun files: Array[String] is extern import Array[String], Array[String].add, NativeString.to_s, String.to_cstring `{
-               char *dir_path;
-               DIR *dir;
-
-               dir_path = String_to_cstring( recv );
-               if ((dir = opendir(dir_path)) == NULL)
-               {
-                       //perror( dir_path );
-                       //exit( 1 );
-                       Array_of_String results;
-                       results = new_Array_of_String();
-                       return results;
-               }
-               else
-               {
-                       Array_of_String results;
-                       String file_name;
-                       struct dirent *de;
-
-                       results = new_Array_of_String();
-
-                       while ( ( de = readdir( dir ) ) != NULL )
-                               if ( strcmp( de->d_name, ".." ) != 0 &&
-                                       strcmp( de->d_name, "." ) != 0 )
-                               {
-                                       file_name = NativeString_to_s( strdup( de->d_name ) );
-                                       Array_of_String_add( results, file_name );
-                               }
+       fun files: Array[String]
+       do
+               var res = new Array[String]
+               var d = new NativeDir.opendir(to_cstring)
+               if d.address_is_null then return res
+
+               loop
+                       var de = d.readdir
+                       if de.address_is_null then break
+                       var name = de.to_s_with_copy
+                       if name == "." or name == ".." then continue
+                       res.add name
+               end
+               d.closedir
 
-                       closedir( dir );
-                       return results;
-               }
-       `}
+               return res
+       end
 end
 
 redef class NativeString
@@ -1129,6 +1113,24 @@ private extern class NativeFile `{ FILE* `}
        new native_stderr is extern "file_NativeFileCapable_NativeFileCapable_native_stderr_0"
 end
 
+# Standard `DIR*` pointer
+private extern class NativeDir `{ DIR* `}
+
+       # Open a directory
+       new opendir(path: NativeString) `{ return opendir(path); `}
+
+       # Close a directory
+       fun closedir `{ closedir(recv); `}
+
+       # Read the next directory entry
+       fun readdir: NativeString `{
+               struct dirent *de;
+               de = readdir(recv);
+               if (!de) return NULL;
+               return de->d_name;
+       `}
+end
+
 redef class Sys
 
        # Standard input
diff --git a/tests/sav/nitg-e/test_deserialization_serial.res b/tests/sav/nitg-e/test_deserialization_serial.res
deleted file mode 100644 (file)
index 90e0d60..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-Runtime error: Aborted (../lib/serialization/serialization.nit:109)
-# Nit:
-<A: true a 0.123 1234 asdf false>
-
-# Json:
-{"__kind": "obj", "__id": 0, "__class": "A", "b": true, "c": {"__kind": "char", "__val": "a"}, "f": 0.123, "i": 1234, "s": "asdf", "n": null}
-
-# Back in Nit:
-<A: true a 0.123 1234 asdf false>
-
-# Nit:
-<B: <A: false b 123.123 2345 hjkl false> 1111 qwer>
-
-# Json:
-{"__kind": "obj", "__id": 0, "__class": "B", "b": false, "c": {"__kind": "char", "__val": "b"}, "f": 123.123, "i": 2345, "s": "hjkl", "n": null, "ii": 1111, "ss": "qwer"}
-
-# Back in Nit:
-<B: <A: false b 123.123 2345 hjkl false> 1111 qwer>
-
-# Nit:
-<C: <A: true a 0.123 1234 asdf false> <B: <A: false b 123.123 2345 hjkl false> 1111 qwer>>
-
-# Json:
-{"__kind": "obj", "__id": 0, "__class": "C", "a": {"__kind": "obj", "__id": 1, "__class": "A", "b": true, "c": {"__kind": "char", "__val": "a"}, "f": 0.123, "i": 1234, "s": "asdf", "n": null}, "b": {"__kind": "obj", "__id": 2, "__class": "B", "b": false, "c": {"__kind": "char", "__val": "b"}, "f": 123.123, "i": 2345, "s": "hjkl", "n": null, "ii": 1111, "ss": "qwer"}, "aa": {"__kind": "ref", "__id": 1}}
-
-# Back in Nit:
-<C: <A: true a 0.123 1234 asdf false> <B: <A: false b 123.123 2345 hjkl false> 1111 qwer>>
-
-# Nit:
-<D: <B: <A: false b 123.123 2345 new line ->
-<- false> 1111         f"\r\/> true>
-
-# Json:
-{"__kind": "obj", "__id": 0, "__class": "D", "b": false, "c": {"__kind": "char", "__val": "b"}, "f": 123.123, "i": 2345, "s": "new line ->\n<-", "n": null, "ii": 1111, "ss": "\tf\"\r\\\/", "d": {"__kind": "ref", "__id": 0}}
-
-# Back in Nit:
-<D: <B: <A: false b 123.123 2345 new line ->
-<- false> 1111         f"\r\/> true>
-
-Error: doesn't know how to deserialize class "Array"
index 22ebc32..fc2e797 100644 (file)
@@ -13,7 +13,6 @@ redef class Deserializer
                if name == "Array[nullable Object]" then return new Array[nullable Object].from_deserializer(self)
                if name == "Array[Serializable]" then return new Array[Serializable].from_deserializer(self)
                if name == "Array[String]" then return new Array[String].from_deserializer(self)
-               if name == "StrictHashMap[Serializable, Int]" then return new StrictHashMap[Serializable, Int].from_deserializer(self)
                if name == "HashMap[Serializable, Array[Couple[Serializable, Int]]]" then return new HashMap[Serializable, Array[Couple[Serializable, Int]]].from_deserializer(self)
                if name == "Array[Couple[Serializable, Int]]" then return new Array[Couple[Serializable, Int]].from_deserializer(self)
                return super
diff --git a/tests/sav/test_deserialization.res b/tests/sav/test_deserialization.res
deleted file mode 100644 (file)
index 13f9a72..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-Runtime error: Aborted (../lib/serialization/serialization.nit:109)
-# Nit:
-<A: true a 0.123 1234 asdf false>
-
-# Json:
-{"__kind": "obj", "__id": 0, "__class": "A", "b": true, "c": {"__kind": "char", "__val": "a"}, "f": 0.123, "i": 1234, "s": "asdf", "n": null}
-
-# Back in Nit:
-<A: true a 0.123 1234 asdf false>
-
-# Nit:
-<B: <A: false b 123.123 2345 hjkl false> 1111 qwer>
-
-# Json:
-{"__kind": "obj", "__id": 0, "__class": "B", "b": false, "c": {"__kind": "char", "__val": "b"}, "f": 123.123, "i": 2345, "s": "hjkl", "n": null, "ii": 1111, "ss": "qwer"}
-
-# Back in Nit:
-<B: <A: false b 123.123 2345 hjkl false> 1111 qwer>
-
-# Nit:
-<C: <A: true a 0.123 1234 asdf false> <B: <A: false b 123.123 2345 hjkl false> 1111 qwer>>
-
-# Json:
-{"__kind": "obj", "__id": 0, "__class": "C", "a": {"__kind": "obj", "__id": 1, "__class": "A", "b": true, "c": {"__kind": "char", "__val": "a"}, "f": 0.123, "i": 1234, "s": "asdf", "n": null}, "b": {"__kind": "obj", "__id": 2, "__class": "B", "b": false, "c": {"__kind": "char", "__val": "b"}, "f": 123.123, "i": 2345, "s": "hjkl", "n": null, "ii": 1111, "ss": "qwer"}, "aa": {"__kind": "ref", "__id": 1}}
-
-# Back in Nit:
-<C: <A: true a 0.123 1234 asdf false> <B: <A: false b 123.123 2345 hjkl false> 1111 qwer>>
-
-# Nit:
-<D: <B: <A: false b 123.123 2345 new line ->
-<- false> 1111         f"\r\/> true>
-
-# Json:
-{"__kind": "obj", "__id": 0, "__class": "D", "b": false, "c": {"__kind": "char", "__val": "b"}, "f": 123.123, "i": 2345, "s": "new line ->\n<-", "n": null, "ii": 1111, "ss": "\tf\"\r\\\/", "d": {"__kind": "ref", "__id": 0}}
-
-# Back in Nit:
-<D: <B: <A: false b 123.123 2345 new line ->
-<- false> 1111         f"\r\/> true>
-
-Error: doesn't know how to deserialize class "Array[Object]"
diff --git a/tests/sav/test_json_deserialization_alt2.res b/tests/sav/test_json_deserialization_alt2.res
new file mode 100644 (file)
index 0000000..99e49d6
--- /dev/null
@@ -0,0 +1,49 @@
+# Nit:
+<A: true a 0.123 1234 asdf false>
+
+# Json:
+{"b": true, "c": "a", "f": 0.123, "i": 1234, "s": "asdf", "n": null}
+
+# Nit:
+<B: <A: false b 123.123 2345 hjkl false> 1111 qwer>
+
+# Json:
+{"b": false, "c": "b", "f": 123.123, "i": 2345, "s": "hjkl", "n": null, "ii": 1111, "ss": "qwer"}
+
+# Nit:
+<C: <A: true a 0.123 1234 asdf false> <B: <A: false b 123.123 2345 hjkl false> 1111 qwer>>
+
+# Json:
+{"a": {"b": true, "c": "a", "f": 0.123, "i": 1234, "s": "asdf", "n": null}, "b": {"b": false, "c": "b", "f": 123.123, "i": 2345, "s": "hjkl", "n": null, "ii": 1111, "ss": "qwer"}, "aa": {"b": true, "c": "a", "f": 0.123, "i": 1234, "s": "asdf", "n": null}}
+
+# Nit:
+<D: <B: <A: false b 123.123 2345 new line ->
+<- false> 1111         f"\r\/> true>
+
+# Json:
+{"b": false, "c": "b", "f": 123.123, "i": 2345, "s": "new line ->\n<-", "n": null, "ii": 1111, "ss": "\tf\"\r\\\/", "d": null}
+
+# Nit:
+<E: a: hello, 1234, 123.4; b: hella, 2345, 234.5>
+
+# Json:
+{"a": ["hello", 1234, 123.4], "b": ["hella", 2345, 234.5]}
+
+# Nit:
+<E: 2222>
+
+# Json:
+{"n": 2222}
+
+# Nit:
+<E: 33.33>
+
+# Json:
+{"n": 33.33}
+
+# Nit:
+<G: hs: -1, 0; s: one, two; hm: one. 1, two. 2; am: three. 3, four. 4>
+
+# Json:
+{"hs": [-1, 0], "s": ["one", "two"], "hm": {"one": 1, "two": 2}, "am": {"three": "3", "four": "4"}}
+
diff --git a/tests/sav/test_serialization_alt1.res b/tests/sav/test_serialization_alt1.res
new file mode 100644 (file)
index 0000000..9b381b9
--- /dev/null
@@ -0,0 +1,25 @@
+# Nit:
+<A: true a 0.123 1234 asdf false>
+
+# Json:
+{"b": true, "c": "a", "f": 0.123, "i": 1234, "s": "asdf", "n": null, "array": [88, "hello", null]}
+
+# Nit:
+<B: <A: false b 123.123 2345 hjkl false> 1111 qwer>
+
+# Json:
+{"b": false, "c": "b", "f": 123.123, "i": 2345, "s": "hjkl", "n": null, "array": [88, "hello", null], "ii": 1111, "ss": "qwer"}
+
+# Nit:
+<C: <A: true a 0.123 1234 asdf false> <B: <A: false b 123.123 2345 hjkl false> 1111 qwer>>
+
+# Json:
+{"a": {"b": true, "c": "a", "f": 0.123, "i": 1234, "s": "asdf", "n": null, "array": [88, "hello", null]}, "b": {"b": false, "c": "b", "f": 123.123, "i": 2345, "s": "hjkl", "n": null, "array": [88, "hello", null], "ii": 1111, "ss": "qwer"}, "aa": {"b": true, "c": "a", "f": 0.123, "i": 1234, "s": "asdf", "n": null, "array": [88, "hello", null]}}
+
+# Nit:
+<D: <B: <A: false b 123.123 2345 new line ->
+<- false> 1111         f"\r\/> true>
+
+# Json:
+{"b": false, "c": "b", "f": 123.123, "i": 2345, "s": "new line ->\n<-", "n": null, "array": [88, "hello", null], "ii": 1111, "ss": "\tf\"\r\\\/", "d": null}
+
index f26bcbf..1360bf2 100644 (file)
@@ -15,7 +15,6 @@
 # limitations under the License.
 
 import serialization
-import json_serialization
 
 # Simple class
 class A
@@ -93,7 +92,6 @@ class E
 
        var a = new Array[Object].with_items("hello", 1234, 123.4)
        var b = new Array[nullable Serializable].with_items("hella", 2345, 234.5)
-       init do end
 
        redef fun to_s do return "<E: a: {a.join(", ")}; b: {b.join(", ")}>"
 end
@@ -103,7 +101,6 @@ class F[N: Numeric]
        auto_serializable
 
        var n: N
-       init(n: N) do self.n = n
 
        redef fun to_s do return "<E: {n}>"
 end
@@ -133,31 +130,23 @@ class G
                "hm: {hm.join(", ", ". ")}; am: {am.join(", ", ". ")}>"
 end
 
-var a = new A(true, 'a', 0.1234, 1234, "asdf", null)
-var b = new B(false, 'b', 123.123, 2345, "hjkl", 12, 1111, "qwer")
-var c = new C(a, b)
-var d = new D(false, 'b', 123.123, 2345, "new line ->\n<-", null, 1111, "\t\f\"\r\\/")
-d.d = d
-var e = new E
-var fi = new F[Int](2222)
-var ff = new F[Float](33.33)
-var g = new G
-
-# Default works only with Nit serial
-var tests = [a, b, c, d, e, fi, ff, g: Serializable]
-
-# Alt1 should work without nitserial
-#alt1# tests = new Array[Serializable].with_items(a, b, c, d)
-
-for o in tests do
-       var stream = new StringWriter
-       var serializer = new JsonSerializer(stream)
-       serializer.serialize(o)
-
-       var deserializer = new JsonDeserializer(stream.to_s)
-       var deserialized = deserializer.deserialize
-
-       print "# Nit:\n{o}\n"
-       print "# Json:\n{stream}\n"
-       print "# Back in Nit:\n{deserialized or else "null"}\n"
+class TestEntities
+       var a = new A(true, 'a', 0.1234, 1234, "asdf", null)
+       var b = new B(false, 'b', 123.123, 2345, "hjkl", 12, 1111, "qwer")
+       var c = new C(a, b)
+       var d = new D(false, 'b', 123.123, 2345, "new line ->\n<-", null, 1111, "\t\f\"\r\\/")
+       init do d.d = d
+       var e = new E
+       var fi = new F[Int](2222)
+       var ff = new F[Float](33.33)
+       var g = new G
+
+       # should work without nitserial
+       var without_generics: Array[Serializable] = [a, b, c, d: Serializable]
+
+       # Default works only with Nit serial
+       var with_generics: Array[Serializable] = [a, b, c, d, e, fi, ff, g: Serializable]
 end
+
+# We instanciate it here so that `nitserial` detects generic types as being alive
+var entities = new TestEntities
index 7d1d443..b0be7fa 100644 (file)
@@ -33,13 +33,7 @@ redef class Deserializer
                if name == "ArrayMap[String, String]" then return new ArrayMap[String, String].from_deserializer(self)
                if name == "Array[Serializable]" then return new Array[Serializable].from_deserializer(self)
                if name == "Array[String]" then return new Array[String].from_deserializer(self)
-               if name == "HashMap[Serializable, Int]" then return new HashMap[Serializable, Int].from_deserializer(self)
-               if name == "Array[JsonObject]" then return new Array[JsonObject].from_deserializer(self)
-               if name == "HashMap[Int, Object]" then return new HashMap[Int, Object].from_deserializer(self)
-               if name == "Array[Node]" then return new Array[Node].from_deserializer(self)
-               if name == "Array[LRState]" then return new Array[LRState].from_deserializer(self)
                if name == "Array[Couple[String, String]]" then return new Array[Couple[String, String]].from_deserializer(self)
-               if name == "Array[nullable Jsonable]" then return new Array[nullable Jsonable].from_deserializer(self)
                return super
        end
 end
diff --git a/tests/test_json_deserialization.nit b/tests/test_json_deserialization.nit
new file mode 100644 (file)
index 0000000..8baadb1
--- /dev/null
@@ -0,0 +1,37 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import test_deserialization
+import json::serialization
+#alt1# import test_deserialization_serial
+
+var entities = new TestEntities
+
+var tests = entities.without_generics#alt1##alt2#
+#alt1#var tests = entities.with_generics
+#alt2#var tests = entities.with_generics
+
+for o in tests do
+       var stream = new StringWriter
+       var serializer = new JsonSerializer(stream)
+       #alt2#serializer.plain_json = true
+       serializer.serialize(o)
+
+       var deserializer = new JsonDeserializer(stream.to_s)#alt2#
+       var deserialized = deserializer.deserialize#alt2#
+
+       print "# Nit:\n{o}\n"
+       print "# Json:\n{stream}\n"
+       print "# Back in Nit:\n{deserialized or else "null"}\n"#alt2#
+end
index 1d3de0a..5517cff 100644 (file)
@@ -15,7 +15,7 @@
 # limitations under the License.
 
 import serialization
-import json_serialization
+import json::serialization
 
 # Simple class
 class A
@@ -97,6 +97,7 @@ d.d = d
 for o in new Array[Serializable].with_items(a, b, c, d) do
        var stream = new StringWriter
        var serializer = new JsonSerializer(stream)
+       #alt1#serializer.plain_json = true
        serializer.serialize(o)
 
        print "# Nit:\n{o}\n"