X-Git-Url: http://nitlanguage.org diff --git a/lib/json/static.nit b/lib/json/static.nit index 29e5c22..fdb9f65 100644 --- a/lib/json/static.nit +++ b/lib/json/static.nit @@ -34,12 +34,56 @@ interface Jsonable # SEE: `append_json` fun to_json: String is abstract + # Use `append_json` to implement `to_json`. + # + # Therefore, one that redefine `append_json` may use the following + # redefinition to link `to_json` and `append_json`: + # + # ~~~nitish + # redef fun to_json do return to_json_by_append + # ~~~ + # + # Note: This is not the default implementation of `to_json` in order to + # avoid cyclic references between `append_json` and `to_json` when none are + # implemented. + protected fun to_json_by_append: String do + var buffer = new RopeBuffer + append_json(buffer) + return buffer.write_to_string + end + # Append the JSON representation of `self` to the specified buffer. # # SEE: `to_json` - fun append_json(buffer: Buffer) do - buffer.append(to_json) + fun append_json(buffer: Buffer) do buffer.append(to_json) + + # Pretty print JSON string. + # + # ~~~ + # var obj = new JsonObject + # obj["foo"] = 1 + # obj["bar"] = true + # var arr = new JsonArray + # arr.add 2 + # arr.add false + # arr.add "baz" + # obj["baz"] = arr + # var res = obj.to_pretty_json + # var exp = """{ + # \t"foo": 1, + # \t"bar": true, + # \t"baz": [2, false, "baz"] + # }\n""" + # assert res == exp + # ~~~ + fun to_pretty_json: String do + var res = new FlatBuffer + pretty_json_visit(res, 0) + res.add '\n' + return res.write_to_string end + + private fun pretty_json_visit(buffer: FlatBuffer, indent: Int) is abstract end redef class Text @@ -80,13 +124,11 @@ redef class Text # Encode `self` in JSON. # - # assert "\t\"http://example.com\"\r\n\0\\".to_json == - # "\"\\t\\\"http:\\/\\/example.com\\\"\\r\\n\\u0000\\\\\"" - redef fun to_json do - var buffer = new FlatBuffer - append_json(buffer) - return buffer.write_to_string - end + # ~~~ + # assert "\t\"http://example.com\"\r\n\0\\".to_json == + # "\"\\t\\\"http:\\/\\/example.com\\\"\\r\\n\\u0000\\\\\"" + # ~~~ + redef fun to_json do return to_json_by_append # Parse `self` as JSON. # @@ -211,10 +253,29 @@ interface JsonMapRead[K: String, V: nullable Jsonable] # obj = new JsonObject # obj["baz"] = null # assert obj.to_json == "\{\"baz\":null\}" - redef fun to_json do - var buffer = new FlatBuffer - append_json(buffer) - return buffer.write_to_string + redef fun to_json do return to_json_by_append + + redef fun pretty_json_visit(buffer, indent) do + buffer.append "\{\n" + indent += 1 + var i = 0 + for k, v in self do + buffer.append "\t" * indent + buffer.append "\"{k}\": " + if v isa JsonObject or v isa JsonArray then + v.pretty_json_visit(buffer, indent) + else + buffer.append v.to_json + end + if i < length - 1 then + buffer.append "," + end + buffer.append "\n" + i += 1 + end + indent -= 1 + buffer.append "\t" * indent + buffer.append "\}" end private fun append_json_entry(iterator: MapIterator[String, nullable Jsonable], @@ -259,10 +320,21 @@ class JsonSequenceRead[E: nullable Jsonable] # assert arr.to_json =="[\"foo\"]" # arr.pop # assert arr.to_json =="[]" - redef fun to_json do - var buffer = new FlatBuffer - append_json(buffer) - return buffer.write_to_string + redef fun to_json do return to_json_by_append + + redef fun pretty_json_visit(buffer, indent) do + buffer.append "\[" + var i = 0 + for v in self do + if v isa JsonObject or v isa JsonArray then + v.pretty_json_visit(buffer, indent) + else + buffer.append v.to_json + end + if i < length - 1 then buffer.append ", " + i += 1 + end + buffer.append "\]" end private fun append_json_entry(iterator: Iterator[nullable Jsonable], @@ -283,13 +355,15 @@ redef class JsonParseError # Get the JSON representation of `self`. # - # var err = new JsonParseError("foo", new Position(1, 2, 3, 4, 5, 6)) - # assert err.to_json == "\{\"error\":\"JsonParseError\"," + - # "\"position\":\{" + - # "\"pos_start\":1,\"pos_end\":2," + - # "\"line_start\":3,\"line_end\":4," + - # "\"col_start\":5,\"col_end\":6" + - # "\},\"message\":\"foo\"\}" + # ~~~ + # var err = new JsonParseError("foo", new Position(1, 2, 3, 4, 5, 6)) + # assert err.to_json == "\{\"error\":\"JsonParseError\"," + + # "\"position\":\{" + + # "\"pos_start\":1,\"pos_end\":2," + + # "\"line_start\":3,\"line_end\":4," + + # "\"col_start\":5,\"col_end\":6" + + # "\},\"message\":\"foo\"\}" + # ~~~ redef fun to_json do return "\{\"error\":\"JsonParseError\"," + "\"position\":{position.to_json}," + @@ -302,12 +376,14 @@ redef class Position # Get the JSON representation of `self`. # - # var pos = new Position(1, 2, 3, 4, 5, 6) - # assert pos.to_json == "\{" + - # "\"pos_start\":1,\"pos_end\":2," + - # "\"line_start\":3,\"line_end\":4," + - # "\"col_start\":5,\"col_end\":6" + - # "\}" + # ~~~ + # var pos = new Position(1, 2, 3, 4, 5, 6) + # assert pos.to_json == "\{" + + # "\"pos_start\":1,\"pos_end\":2," + + # "\"line_start\":3,\"line_end\":4," + + # "\"col_start\":5,\"col_end\":6" + + # "\}" + # ~~~ redef fun to_json do return "\{\"pos_start\":{pos_start},\"pos_end\":{pos_end}," + "\"line_start\":{line_start},\"line_end\":{line_end}," + @@ -319,7 +395,8 @@ end # Redef parser redef class Nvalue - fun to_nit_object: nullable Jsonable is abstract + # The represented value. + private fun to_nit_object: nullable Jsonable is abstract end redef class Nvalue_number @@ -348,7 +425,8 @@ redef class Nvalue_null end redef class Nstring - fun to_nit_string: String do + # The represented string. + private fun to_nit_string: String do var res = new FlatBuffer var i = 1 while i < text.length - 1 do @@ -398,7 +476,8 @@ redef class Nvalue_object end redef class Nmembers - fun pairs: Array[Npair] is abstract + # All the key-value pairs. + private fun pairs: Array[Npair] is abstract end redef class Nmembers_tail @@ -415,8 +494,11 @@ redef class Nmembers_head end redef class Npair - fun name: String do return n_string.to_nit_string - fun value: nullable Jsonable do return n_value.to_nit_object + # The represented key. + private fun name: String do return n_string.to_nit_string + + # The represented value. + private fun value: nullable Jsonable do return n_value.to_nit_object end redef class Nvalue_array @@ -433,7 +515,8 @@ redef class Nvalue_array end redef class Nelements - fun items: Array[Nvalue] is abstract + # All the items. + private fun items: Array[Nvalue] is abstract end redef class Nelements_tail