Merge: metrics: `--nullables` distinguishes safe and unsafe calls on `null`
[nit.git] / lib / json / serialization.nit
index 98a8e87..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.
+# 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
 private import ::serialization::engine_tools
-import static
+private import static
 
 # Serializer of Nit objects to Json string.
 class JsonSerializer
@@ -50,6 +90,7 @@ class JsonSerializer
        # * 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
@@ -138,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]
@@ -262,6 +303,20 @@ redef class Serializable
                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