module json_serialization
import serialization
-import simple_json_reader
+import json::static
class JsonSerializer
super Serializer
class JsonDeserializer
super Deserializer
- var root: nullable Object
- var path = new Array[HashMap[String, nullable Object]]
+ var root: nullable Jsonable
+ var path = new Array[JsonObject]
var id_to_object = new HashMap[Int, Object]
var just_opened_id: nullable Int = null
- init(text: String)
+ init(text: Text)
do
- var root = text.json_to_nit_object
- if root isa HashMap[String, nullable Object] then path.add(root)
+ var root = text.parse_json
+ if root isa JsonObject then path.add(root)
self.root = root
end
# 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"]
if val.length != 1 then print "Error: expected a single char when deserializing '{val}'."
- return val.first
+ return val.chars.first
end
- print "Malformed Json string: unexpected Json Object kind '{kind}'"
+ print "Malformed Json string: unexpected Json Object kind '{kind or else "null"}'"
abort
end
+ if object isa Array[nullable Object] then
+ # special case, isa Array[nullable Serializable]
+ var array = new Array[nullable Serializable]
+ for e in object do array.add e.as(nullable Serializable)
+ return array
+ end
+
return object
end
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
end
redef class Array[E]
- redef fun serialize_to_json(v) do
- v.stream.write "["
- var is_first = true
- for e in self do
- if is_first then
- is_first = false
- else v.stream.write(", ")
-
- if not v.try_to_serialize(e) then
- v.warn("element of type {e.class_name} is not serializable.")
+ redef fun serialize_to_json(v)
+ 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(", ")
+
+ 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(", ")
+
+ 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
+ end
+
+ 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(SequenceRead[nullable Object])
+ for i in length.times do
+ var obj = v.convert_object(arr[i])
+ self.add obj
end
end
- v.stream.write "]"
end
end