X-Git-Url: http://nitlanguage.org diff --git a/lib/json/serialization_write.nit b/lib/json/serialization_write.nit index 43987e8..009e131 100644 --- a/lib/json/serialization_write.nit +++ b/lib/json/serialization_write.nit @@ -33,7 +33,7 @@ class JsonSerializer # 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. + # * Preserve the Nit `Char` and `Byte` types as special objects. # * 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 metadata, it can be complex to read. @@ -69,6 +69,8 @@ class JsonSerializer # Used only when `plain_json == true`. private var first_attribute = false + redef var current_object = null + redef fun serialize(object) do if object == null then @@ -88,8 +90,11 @@ class JsonSerializer end first_attribute = true + var last_object = current_object + current_object = object object.accept_json_serializer self first_attribute = false + current_object = last_object if plain_json then open_objects.pop end @@ -99,8 +104,8 @@ class JsonSerializer do if not plain_json or not first_attribute then stream.write "," - first_attribute = false end + first_attribute = false new_line_and_indent stream.write "\"" @@ -144,26 +149,49 @@ redef class Text redef fun accept_json_serializer(v) do v.stream.write "\"" + + var start_i = 0 + var escaped = null for i in [0 .. self.length[ do var char = self[i] if char == '\\' then - v.stream.write "\\\\" + escaped = "\\\\" else if char == '\"' then - v.stream.write "\\\"" + escaped = "\\\"" else if char < ' ' then if char == '\n' then - v.stream.write "\\n" + escaped = "\\n" else if char == '\r' then - v.stream.write "\\r" + escaped = "\\r" else if char == '\t' then - v.stream.write "\\t" + escaped = "\\t" else - v.stream.write char.escape_to_utf16 + escaped = char.escape_to_utf16 + end + end + + if escaped != null then + # Write open non-escaped string + if start_i <= i then + v.stream.write substring(start_i, i-start_i) end + + # Write escaped character + v.stream.write escaped + escaped = null + start_i = i+1 + end + end + + # Write remaining non-escaped string + if start_i < length then + if start_i == 0 then + v.stream.write self else - v.stream.write char.to_s + v.stream.write substring(start_i, length-start_i) end end + v.stream.write "\"" end end @@ -214,10 +242,10 @@ redef class Serializable # which is used by all the serialization engines, not just JSON. protected fun accept_json_serializer(v: JsonSerializer) do - var id = v.cache.new_id_for(self) v.stream.write "\{" v.indent_level += 1 if not v.plain_json then + var id = v.cache.new_id_for(self) v.new_line_and_indent v.stream.write "\"__kind\": \"obj\", \"__id\": " v.stream.write id.to_s @@ -225,7 +253,7 @@ redef class Serializable v.stream.write class_name v.stream.write "\"" end - core_serialize_to(v) + v.serialize_core(self) v.indent_level -= 1 v.new_line_and_indent @@ -258,6 +286,19 @@ redef class Char end end +redef class Byte + redef fun accept_json_serializer(v) + do + if v.plain_json then + to_i.accept_json_serializer v + else + v.stream.write "\{\"__kind\": \"byte\", \"__val\": " + to_i.accept_json_serializer v + v.stream.write "\}" + end + end +end + redef class CString redef fun accept_json_serializer(v) do to_s.accept_json_serializer(v) end @@ -289,8 +330,10 @@ end redef class SimpleCollection[E] redef fun accept_json_serializer(v) do - # Register as pseudo object - if not v.plain_json then + if v.plain_json then + serialize_to_pure_json v + else + # Register as pseudo object var id = v.cache.new_id_for(self) v.stream.write """{""" v.indent_level += 1 @@ -301,14 +344,12 @@ redef class SimpleCollection[E] v.stream.write class_name v.stream.write """",""" v.new_line_and_indent + v.stream.write """"__items": """ + serialize_to_pure_json v core_serialize_to v - end - - serialize_to_pure_json v - if not v.plain_json then v.indent_level -= 1 v.new_line_and_indent v.stream.write "\}"