diff --git a/library/extras/visitor/print_json_visitor.e b/library/extras/visitor/print_json_visitor.e
index 6fa64558..6072769b 100644
--- a/library/extras/visitor/print_json_visitor.e
+++ b/library/extras/visitor/print_json_visitor.e
@@ -1,102 +1,102 @@
-note
- description: "PRINT_JSON_VISITOR Generates the JSON-String for a JSON_VALUE"
- author: "jvelilla"
- date: "2008/08/24"
- revision: "0.1"
-
-class
- PRINT_JSON_VISITOR
-
-inherit
- JSON_VISITOR
-
-create make
-
-feature -- Initialization
-
- make
- -- Create a new instance
- do
- create to_json.make_empty
- end
-
-feature -- Access
-
- to_json: STRING
- -- JSON representation
-
-feature -- Visitor Pattern
-
- visit_json_array (a_json_array: JSON_ARRAY)
- -- Visit `a_json_array'.
- local
- value: JSON_VALUE
- l_json_array: ARRAYED_LIST [JSON_VALUE]
- do
- l_json_array:=a_json_array.array_representation
- to_json.append ("[")
- from
- l_json_array.start
- until
- l_json_array.off
- loop
- value := l_json_array.item
- value.accept (Current)
- l_json_array.forth
- if not l_json_array.after then
- to_json.append(",")
- end
- end
- to_json.append ("]")
- end
-
- visit_json_boolean (a_json_boolean: JSON_BOOLEAN)
- -- Visit `a_json_boolean'.
- do
- to_json.append (a_json_boolean.item.out)
- end
-
- visit_json_null (a_json_null: JSON_NULL)
- -- Visit `a_json_null'.
- do
- to_json.append ("null")
- end
-
- visit_json_number (a_json_number: JSON_NUMBER)
- -- Visit `a_json_number'.
- do
- to_json.append (a_json_number.item)
- end
-
- visit_json_object (a_json_object: JSON_OBJECT)
- -- Visit `a_json_object'.
- local
- l_pairs: HASH_TABLE[JSON_VALUE,JSON_STRING]
- do
- l_pairs := a_json_object.map_representation
- to_json.append ("{")
- from
- l_pairs.start
- until
- l_pairs.off
- loop
- l_pairs.key_for_iteration.accept (Current)
- to_json.append (":")
- l_pairs.item_for_iteration.accept (Current)
- l_pairs.forth
- if not l_pairs.after then
- to_json.append (",")
- end
- end
- to_json.append ("}")
- end
-
- visit_json_string (a_json_string: JSON_STRING)
- -- Visit `a_json_string'.
- do
- to_json.append ("%"")
- to_json.append (a_json_string.item)
- to_json.append ("%"")
- end
-
-end
+note
+ description: "PRINT_JSON_VISITOR Generates the JSON-String for a JSON_VALUE"
+ author: "jvelilla"
+ date: "2008/08/24"
+ revision: "0.1"
+
+class
+ PRINT_JSON_VISITOR
+
+inherit
+ JSON_VISITOR
+
+create make
+
+feature -- Initialization
+
+ make
+ -- Create a new instance
+ do
+ create to_json.make_empty
+ end
+
+feature -- Access
+
+ to_json: STRING
+ -- JSON representation
+
+feature -- Visitor Pattern
+
+ visit_json_array (a_json_array: JSON_ARRAY)
+ -- Visit `a_json_array'.
+ local
+ value: JSON_VALUE
+ l_json_array: ARRAYED_LIST [JSON_VALUE]
+ do
+ l_json_array:=a_json_array.array_representation
+ to_json.append ("[")
+ from
+ l_json_array.start
+ until
+ l_json_array.off
+ loop
+ value := l_json_array.item
+ value.accept (Current)
+ l_json_array.forth
+ if not l_json_array.after then
+ to_json.append(",")
+ end
+ end
+ to_json.append ("]")
+ end
+
+ visit_json_boolean (a_json_boolean: JSON_BOOLEAN)
+ -- Visit `a_json_boolean'.
+ do
+ to_json.append (a_json_boolean.item.out)
+ end
+
+ visit_json_null (a_json_null: JSON_NULL)
+ -- Visit `a_json_null'.
+ do
+ to_json.append ("null")
+ end
+
+ visit_json_number (a_json_number: JSON_NUMBER)
+ -- Visit `a_json_number'.
+ do
+ to_json.append (a_json_number.item)
+ end
+
+ visit_json_object (a_json_object: JSON_OBJECT)
+ -- Visit `a_json_object'.
+ local
+ l_pairs: HASH_TABLE[JSON_VALUE,JSON_STRING]
+ do
+ l_pairs := a_json_object.map_representation
+ to_json.append ("{")
+ from
+ l_pairs.start
+ until
+ l_pairs.off
+ loop
+ l_pairs.key_for_iteration.accept (Current)
+ to_json.append (":")
+ l_pairs.item_for_iteration.accept (Current)
+ l_pairs.forth
+ if not l_pairs.after then
+ to_json.append (",")
+ end
+ end
+ to_json.append ("}")
+ end
+
+ visit_json_string (a_json_string: JSON_STRING)
+ -- Visit `a_json_string'.
+ do
+ to_json.append ("%"")
+ to_json.append (a_json_string.item)
+ to_json.append ("%"")
+ end
+
+end
diff --git a/library/gobo/converters/json_ds_hash_table_converter.e b/library/gobo/converters/json_ds_hash_table_converter.e
index 9f244fe0..46cf0ff9 100644
--- a/library/gobo/converters/json_ds_hash_table_converter.e
+++ b/library/gobo/converters/json_ds_hash_table_converter.e
@@ -1,85 +1,85 @@
-note
- description: "A JSON converter for DS_HASH_TABLE [ANY, HASHABLE]"
- author: "Paul Cohen"
- date: "$Date: $"
- revision: "$Revision: $"
- file: "$HeadURL: $"
-
-class JSON_DS_HASH_TABLE_CONVERTER
-
-inherit
- JSON_CONVERTER
-
-create
- make
-
-feature {NONE} -- Initialization
-
- make
- do
- create object.make (0)
- end
-
-feature -- Access
-
- value: JSON_OBJECT
-
- object: DS_HASH_TABLE [ANY, HASHABLE]
-
-feature -- Conversion
-
- from_json (j: like value): detachable like object
- local
- keys: ARRAY [JSON_STRING]
- i: INTEGER
- h: HASHABLE
- a: ANY
- do
- keys := j.current_keys
- create Result.make (keys.count)
- from
- i := 1
- until
- i > keys.count
- loop
- h ?= json.object (keys [i], void)
- check h /= Void end
- a := json.object (j.item (keys [i]), Void)
- Result.put (a, h)
- i := i + 1
- end
- end
-
- to_json (o: like object): like value
- local
- c: DS_HASH_TABLE_CURSOR [ANY, HASHABLE]
- js: JSON_STRING
- jv: JSON_VALUE
- failed: BOOLEAN
- do
- create Result.make
- from
- c := o.new_cursor
- c.start
- until
- c.after
- loop
- if attached {JSON_STRING} json.value (c.key) as l_key then
- js := l_key
- else
- create js.make_json (c.key.out)
- end
- jv := json.value (c.item)
- if jv /= Void then
- Result.put (jv, js)
- else
- failed := True
- end
- c.forth
- end
- if failed then
- Result := Void
- end
- end
-
-end -- class JSON_DS_HASH_TABLE_CONVERTER
+note
+ description: "A JSON converter for DS_HASH_TABLE [ANY, HASHABLE]"
+ author: "Paul Cohen"
+ date: "$Date: $"
+ revision: "$Revision: $"
+ file: "$HeadURL: $"
+
+class JSON_DS_HASH_TABLE_CONVERTER
+
+inherit
+ JSON_CONVERTER
+
+create
+ make
+
+feature {NONE} -- Initialization
+
+ make
+ do
+ create object.make (0)
+ end
+
+feature -- Access
+
+ value: JSON_OBJECT
+
+ object: DS_HASH_TABLE [ANY, HASHABLE]
+
+feature -- Conversion
+
+ from_json (j: like value): detachable like object
+ local
+ keys: ARRAY [JSON_STRING]
+ i: INTEGER
+ h: HASHABLE
+ a: ANY
+ do
+ keys := j.current_keys
+ create Result.make (keys.count)
+ from
+ i := 1
+ until
+ i > keys.count
+ loop
+ h ?= json.object (keys [i], void)
+ check h /= Void end
+ a := json.object (j.item (keys [i]), Void)
+ Result.put (a, h)
+ i := i + 1
+ end
+ end
+
+ to_json (o: like object): like value
+ local
+ c: DS_HASH_TABLE_CURSOR [ANY, HASHABLE]
+ js: JSON_STRING
+ jv: JSON_VALUE
+ failed: BOOLEAN
+ do
+ create Result.make
+ from
+ c := o.new_cursor
+ c.start
+ until
+ c.after
+ loop
+ if attached {JSON_STRING} json.value (c.key) as l_key then
+ js := l_key
+ else
+ create js.make_json (c.key.out)
+ end
+ jv := json.value (c.item)
+ if jv /= Void then
+ Result.put (jv, js)
+ else
+ failed := True
+ end
+ c.forth
+ end
+ if failed then
+ Result := Void
+ end
+ end
+
+end -- class JSON_DS_HASH_TABLE_CONVERTER
diff --git a/library/gobo/converters/json_ds_linked_list_converter.e b/library/gobo/converters/json_ds_linked_list_converter.e
index bf1aa516..4696051e 100644
--- a/library/gobo/converters/json_ds_linked_list_converter.e
+++ b/library/gobo/converters/json_ds_linked_list_converter.e
@@ -1,62 +1,62 @@
-note
- description: "A JSON converter for DS_LINKED_LIST [ANY]"
- author: "Paul Cohen"
- date: "$Date: $"
- revision: "$Revision: $"
- file: "$HeadURL: $"
-
-class JSON_DS_LINKED_LIST_CONVERTER
-
-inherit
- JSON_CONVERTER
-
-create
- make
-
-feature {NONE} -- Initialization
-
- make
- do
- create object.make
- end
-
-feature -- Access
-
- value: JSON_ARRAY
-
- object: DS_LINKED_LIST [ANY]
-
-feature -- Conversion
-
- from_json (j: like value): detachable like object
- local
- i: INTEGER
- do
- create Result.make
- from
- i := 1
- until
- i > j.count
- loop
- Result.put_last (json.object (j [i], Void))
- i := i + 1
- end
- end
-
- to_json (o: like object): like value
- local
- c: DS_LIST_CURSOR [ANY]
- do
- create Result.make_array
- from
- c := o.new_cursor
- c.start
- until
- c.after
- loop
- Result.add (json.value (c.item))
- c.forth
- end
- end
-
-end -- class JSON_DS_LINKED_LIST_CONVERTER
+note
+ description: "A JSON converter for DS_LINKED_LIST [ANY]"
+ author: "Paul Cohen"
+ date: "$Date: $"
+ revision: "$Revision: $"
+ file: "$HeadURL: $"
+
+class JSON_DS_LINKED_LIST_CONVERTER
+
+inherit
+ JSON_CONVERTER
+
+create
+ make
+
+feature {NONE} -- Initialization
+
+ make
+ do
+ create object.make
+ end
+
+feature -- Access
+
+ value: JSON_ARRAY
+
+ object: DS_LINKED_LIST [ANY]
+
+feature -- Conversion
+
+ from_json (j: like value): detachable like object
+ local
+ i: INTEGER
+ do
+ create Result.make
+ from
+ i := 1
+ until
+ i > j.count
+ loop
+ Result.put_last (json.object (j [i], Void))
+ i := i + 1
+ end
+ end
+
+ to_json (o: like object): like value
+ local
+ c: DS_LIST_CURSOR [ANY]
+ do
+ create Result.make_array
+ from
+ c := o.new_cursor
+ c.start
+ until
+ c.after
+ loop
+ Result.add (json.value (c.item))
+ c.forth
+ end
+ end
+
+end -- class JSON_DS_LINKED_LIST_CONVERTER
diff --git a/library/json.ecf b/library/json.ecf
index ee954e09..8d6dc612 100644
--- a/library/json.ecf
+++ b/library/json.ecf
@@ -1,28 +1,28 @@
-
-
-
-
-
- /EIFGENs$
- /CVS$
- /.svn$
-
-
-
-
-
- ^/gobo$
- ^/kernel$
- ^/extras$
-
-
-
-
-
-
+
+
+
+
+
+ /EIFGENs$
+ /CVS$
+ /.svn$
+
+
+
+
+
+ ^/gobo$
+ ^/kernel$
+ ^/extras$
+
+
+
+
+
+
diff --git a/library/json.rc b/library/json.rc
index d3f5a12f..8b137891 100644
--- a/library/json.rc
+++ b/library/json.rc
@@ -1 +1 @@
-
+
diff --git a/library/kernel/ejson.e b/library/kernel/ejson.e
index 802d785b..cb5ed967 100644
--- a/library/kernel/ejson.e
+++ b/library/kernel/ejson.e
@@ -1,268 +1,268 @@
-note
- description: "Core factory class for creating JSON objects and corresponding Eiffel objects."
- author: "Paul Cohen"
- date: "$Date$"
- revision: "$Revision$"
- file: "$HeadURL: $"
-
-class EJSON
-
-inherit
- EXCEPTIONS
-
-feature -- Access
-
- value (an_object: detachable ANY): detachable JSON_VALUE
- -- JSON value from Eiffel object. Raises an "eJSON exception" if
- -- unable to convert value.
- local
- i: INTEGER
- ja: JSON_ARRAY
- do
- -- Try to convert from basic Eiffel types. Note that we check with
- -- `conforms_to' since the client may have subclassed the base class
- -- that these basic types are derived from.
- if an_object = Void then
- create {JSON_NULL} Result
- elseif attached {BOOLEAN} an_object as b then
- create {JSON_BOOLEAN} Result.make_boolean (b)
- elseif attached {INTEGER_8} an_object as i8 then
- create {JSON_NUMBER} Result.make_integer (i8)
- elseif attached {INTEGER_16} an_object as i16 then
- create {JSON_NUMBER} Result.make_integer (i16)
- elseif attached {INTEGER_32} an_object as i32 then
- create {JSON_NUMBER} Result.make_integer (i32)
- elseif attached {INTEGER_64} an_object as i64 then
- create {JSON_NUMBER} Result.make_integer (i64)
- elseif attached {NATURAL_8} an_object as n8 then
- create {JSON_NUMBER} Result.make_natural (n8)
- elseif attached {NATURAL_16} an_object as n16 then
- create {JSON_NUMBER} Result.make_natural (n16)
- elseif attached {NATURAL_32} an_object as n32 then
- create {JSON_NUMBER} Result.make_natural (n32)
- elseif attached {NATURAL_64} an_object as n64 then
- create {JSON_NUMBER} Result.make_natural (n64)
- elseif attached {REAL_32} an_object as r32 then
- create {JSON_NUMBER} Result.make_real (r32)
- elseif attached {REAL_64} an_object as r64 then
- create {JSON_NUMBER} Result.make_real (r64)
- elseif attached {ARRAY [detachable ANY]} an_object as a then
- create ja.make_array
- from
- i := a.lower
- until
- i > a.upper
- loop
- if attached value (a @ i) as v then
- ja.add (v)
- else
- check value_attached: False end
- end
- i := i + 1
- end
- Result := ja
- elseif attached {CHARACTER_8} an_object as c8 then
- create {JSON_STRING} Result.make_json (c8.out)
- elseif attached {CHARACTER_32} an_object as c32 then
- create {JSON_STRING} Result.make_json (c32.out)
-
- elseif attached {STRING_8} an_object as s8 then
- create {JSON_STRING} Result.make_json (s8)
- elseif attached {STRING_32} an_object as s32 then
- create {JSON_STRING} Result.make_json_from_string_32 (s32)
- end
-
- if Result = Void then
- -- Now check the converters
- if an_object /= Void and then attached converter_for (an_object) as jc then
- Result := jc.to_json (an_object)
- else
- raise (exception_failed_to_convert_to_json (an_object))
- end
- end
- end
-
- object (a_value: detachable JSON_VALUE; base_class: detachable STRING): detachable ANY
- -- Eiffel object from JSON value. If `base_class' /= Void an eiffel
- -- object based on `base_class' will be returned. Raises an "eJSON
- -- exception" if unable to convert value.
- local
- i: INTEGER
- ll: LINKED_LIST [detachable ANY]
- t: HASH_TABLE [detachable ANY, STRING_GENERAL]
- keys: ARRAY [JSON_STRING]
- do
- if a_value = Void then
- Result := Void
- else
- if base_class = Void then
- if a_value = Void then
- Result := Void
- elseif attached {JSON_NULL} a_value then
- Result := Void
- elseif attached {JSON_BOOLEAN} a_value as jb then
- Result := jb.item
- elseif attached {JSON_NUMBER} a_value as jn then
- if jn.item.is_integer_8 then
- Result := jn.item.to_integer_8
- elseif jn.item.is_integer_16 then
- Result := jn.item.to_integer_16
- elseif jn.item.is_integer_32 then
- Result := jn.item.to_integer_32
- elseif jn.item.is_integer_64 then
- Result := jn.item.to_integer_64
- elseif jn.item.is_natural_64 then
- Result := jn.item.to_natural_64
- elseif jn.item.is_double then
- Result := jn.item.to_double
- end
- elseif attached {JSON_STRING} a_value as js then
- create {STRING_32} Result.make_from_string (js.unescaped_string_32)
- elseif attached {JSON_ARRAY} a_value as ja then
- from
- create ll.make
- i := 1
- until
- i > ja.count
- loop
- ll.extend (object (ja [i], Void))
- i := i + 1
- end
- Result := ll
- elseif attached {JSON_OBJECT} a_value as jo then
- keys := jo.current_keys
- create t.make (keys.count)
- from
- i := keys.lower
- until
- i > keys.upper
- loop
- if attached {STRING_GENERAL} object (keys [i], Void) as s then
- t.put (object (jo.item (keys [i]), Void), s)
- end
- i := i + 1
- end
- Result := t
- end
- else
- if converters.has_key (base_class) and then attached converters.found_item as jc then
- Result := jc.from_json (a_value)
- else
- raise (exception_failed_to_convert_to_eiffel (a_value, base_class))
- end
- end
- end
- end
-
- object_from_json (json: STRING; base_class: detachable STRING): detachable ANY
- -- Eiffel object from JSON representation. If `base_class' /= Void an
- -- Eiffel object based on `base_class' will be returned. Raises an
- -- "eJSON exception" if unable to convert value.
- require
- json_not_void: json /= Void
- local
- jv: detachable JSON_VALUE
- do
- json_parser.set_representation (json)
- jv := json_parser.parse
- if jv /= Void then
- Result := object (jv, base_class)
- end
- end
-
- converter_for (an_object: ANY): detachable JSON_CONVERTER
- -- Converter for objects. Returns Void if none found.
- require
- an_object_not_void: an_object /= Void
- do
- if converters.has_key (an_object.generator) then
- Result := converters.found_item
- end
- end
-
- json_reference (s: STRING): JSON_OBJECT
- -- A JSON (Dojo style) reference object using `s' as the
- -- reference value. The caller is responsable for ensuring
- -- the validity of `s' as a json reference.
- require
- s_not_void: s /= Void
- local
- js_key, js_value: JSON_STRING
- do
- create Result.make
- create js_key.make_json ("$ref")
- create js_value.make_json (s)
- Result.put (js_value, js_key)
- end
-
- json_references (l: LIST [STRING]): JSON_ARRAY
- -- A JSON array of JSON (Dojo style) reference objects using the
- -- strings in `l' as reference values. The caller is responsable
- -- for ensuring the validity of all strings in `l' as json
- -- references.
- require
- l_not_void: l /= Void
- local
- c: ITERATION_CURSOR [STRING]
- do
- create Result.make_array
- from
- c := l.new_cursor
- until
- c.after
- loop
- Result.add (json_reference (c.item))
- c.forth
- end
- end
-
-feature -- Change
-
- add_converter (jc: JSON_CONVERTER)
- -- Add the converter `jc'.
- require
- jc_not_void: jc /= Void
- do
- converters.force (jc, jc.object.generator)
- ensure
- has_converter: converter_for (jc.object) /= Void
- end
-
-feature {NONE} -- Implementation
-
- converters: HASH_TABLE [JSON_CONVERTER, STRING]
- -- Converters hashed by generator (base class)
- once
- create Result.make (10)
- end
-
-feature {NONE} -- Implementation (Exceptions)
-
- exception_prefix: STRING = "eJSON exception: "
-
- exception_failed_to_convert_to_eiffel (a_value: JSON_VALUE; base_class: detachable STRING): STRING
- -- Exception message for failing to convert a JSON_VALUE to an instance of `a'.
- do
- Result := exception_prefix + "Failed to convert JSON_VALUE to an Eiffel object: " + a_value.generator
- if base_class /= Void then
- Result.append (" -> {" + base_class + "}")
- end
- end
-
- exception_failed_to_convert_to_json (an_object: detachable ANY): STRING
- -- Exception message for failing to convert `a' to a JSON_VALUE.
- do
- Result := exception_prefix + "Failed to convert Eiffel object to a JSON_VALUE"
- if an_object /= Void then
- Result.append (" : {" + an_object.generator + "}")
- end
- end
-
-feature {NONE} -- Implementation (JSON parser)
-
- json_parser: JSON_PARSER
- once
- create Result.make_parser ("")
- end
-
-end -- class EJSON
+note
+ description: "Core factory class for creating JSON objects and corresponding Eiffel objects."
+ author: "Paul Cohen"
+ date: "$Date$"
+ revision: "$Revision$"
+ file: "$HeadURL: $"
+
+class EJSON
+
+inherit
+ EXCEPTIONS
+
+feature -- Access
+
+ value (an_object: detachable ANY): detachable JSON_VALUE
+ -- JSON value from Eiffel object. Raises an "eJSON exception" if
+ -- unable to convert value.
+ local
+ i: INTEGER
+ ja: JSON_ARRAY
+ do
+ -- Try to convert from basic Eiffel types. Note that we check with
+ -- `conforms_to' since the client may have subclassed the base class
+ -- that these basic types are derived from.
+ if an_object = Void then
+ create {JSON_NULL} Result
+ elseif attached {BOOLEAN} an_object as b then
+ create {JSON_BOOLEAN} Result.make_boolean (b)
+ elseif attached {INTEGER_8} an_object as i8 then
+ create {JSON_NUMBER} Result.make_integer (i8)
+ elseif attached {INTEGER_16} an_object as i16 then
+ create {JSON_NUMBER} Result.make_integer (i16)
+ elseif attached {INTEGER_32} an_object as i32 then
+ create {JSON_NUMBER} Result.make_integer (i32)
+ elseif attached {INTEGER_64} an_object as i64 then
+ create {JSON_NUMBER} Result.make_integer (i64)
+ elseif attached {NATURAL_8} an_object as n8 then
+ create {JSON_NUMBER} Result.make_natural (n8)
+ elseif attached {NATURAL_16} an_object as n16 then
+ create {JSON_NUMBER} Result.make_natural (n16)
+ elseif attached {NATURAL_32} an_object as n32 then
+ create {JSON_NUMBER} Result.make_natural (n32)
+ elseif attached {NATURAL_64} an_object as n64 then
+ create {JSON_NUMBER} Result.make_natural (n64)
+ elseif attached {REAL_32} an_object as r32 then
+ create {JSON_NUMBER} Result.make_real (r32)
+ elseif attached {REAL_64} an_object as r64 then
+ create {JSON_NUMBER} Result.make_real (r64)
+ elseif attached {ARRAY [detachable ANY]} an_object as a then
+ create ja.make_array
+ from
+ i := a.lower
+ until
+ i > a.upper
+ loop
+ if attached value (a @ i) as v then
+ ja.add (v)
+ else
+ check value_attached: False end
+ end
+ i := i + 1
+ end
+ Result := ja
+ elseif attached {CHARACTER_8} an_object as c8 then
+ create {JSON_STRING} Result.make_json (c8.out)
+ elseif attached {CHARACTER_32} an_object as c32 then
+ create {JSON_STRING} Result.make_json (c32.out)
+
+ elseif attached {STRING_8} an_object as s8 then
+ create {JSON_STRING} Result.make_json (s8)
+ elseif attached {STRING_32} an_object as s32 then
+ create {JSON_STRING} Result.make_json_from_string_32 (s32)
+ end
+
+ if Result = Void then
+ -- Now check the converters
+ if an_object /= Void and then attached converter_for (an_object) as jc then
+ Result := jc.to_json (an_object)
+ else
+ raise (exception_failed_to_convert_to_json (an_object))
+ end
+ end
+ end
+
+ object (a_value: detachable JSON_VALUE; base_class: detachable STRING): detachable ANY
+ -- Eiffel object from JSON value. If `base_class' /= Void an eiffel
+ -- object based on `base_class' will be returned. Raises an "eJSON
+ -- exception" if unable to convert value.
+ local
+ i: INTEGER
+ ll: LINKED_LIST [detachable ANY]
+ t: HASH_TABLE [detachable ANY, STRING_GENERAL]
+ keys: ARRAY [JSON_STRING]
+ do
+ if a_value = Void then
+ Result := Void
+ else
+ if base_class = Void then
+ if a_value = Void then
+ Result := Void
+ elseif attached {JSON_NULL} a_value then
+ Result := Void
+ elseif attached {JSON_BOOLEAN} a_value as jb then
+ Result := jb.item
+ elseif attached {JSON_NUMBER} a_value as jn then
+ if jn.item.is_integer_8 then
+ Result := jn.item.to_integer_8
+ elseif jn.item.is_integer_16 then
+ Result := jn.item.to_integer_16
+ elseif jn.item.is_integer_32 then
+ Result := jn.item.to_integer_32
+ elseif jn.item.is_integer_64 then
+ Result := jn.item.to_integer_64
+ elseif jn.item.is_natural_64 then
+ Result := jn.item.to_natural_64
+ elseif jn.item.is_double then
+ Result := jn.item.to_double
+ end
+ elseif attached {JSON_STRING} a_value as js then
+ create {STRING_32} Result.make_from_string (js.unescaped_string_32)
+ elseif attached {JSON_ARRAY} a_value as ja then
+ from
+ create ll.make
+ i := 1
+ until
+ i > ja.count
+ loop
+ ll.extend (object (ja [i], Void))
+ i := i + 1
+ end
+ Result := ll
+ elseif attached {JSON_OBJECT} a_value as jo then
+ keys := jo.current_keys
+ create t.make (keys.count)
+ from
+ i := keys.lower
+ until
+ i > keys.upper
+ loop
+ if attached {STRING_GENERAL} object (keys [i], Void) as s then
+ t.put (object (jo.item (keys [i]), Void), s)
+ end
+ i := i + 1
+ end
+ Result := t
+ end
+ else
+ if converters.has_key (base_class) and then attached converters.found_item as jc then
+ Result := jc.from_json (a_value)
+ else
+ raise (exception_failed_to_convert_to_eiffel (a_value, base_class))
+ end
+ end
+ end
+ end
+
+ object_from_json (json: STRING; base_class: detachable STRING): detachable ANY
+ -- Eiffel object from JSON representation. If `base_class' /= Void an
+ -- Eiffel object based on `base_class' will be returned. Raises an
+ -- "eJSON exception" if unable to convert value.
+ require
+ json_not_void: json /= Void
+ local
+ jv: detachable JSON_VALUE
+ do
+ json_parser.set_representation (json)
+ jv := json_parser.parse
+ if jv /= Void then
+ Result := object (jv, base_class)
+ end
+ end
+
+ converter_for (an_object: ANY): detachable JSON_CONVERTER
+ -- Converter for objects. Returns Void if none found.
+ require
+ an_object_not_void: an_object /= Void
+ do
+ if converters.has_key (an_object.generator) then
+ Result := converters.found_item
+ end
+ end
+
+ json_reference (s: STRING): JSON_OBJECT
+ -- A JSON (Dojo style) reference object using `s' as the
+ -- reference value. The caller is responsable for ensuring
+ -- the validity of `s' as a json reference.
+ require
+ s_not_void: s /= Void
+ local
+ js_key, js_value: JSON_STRING
+ do
+ create Result.make
+ create js_key.make_json ("$ref")
+ create js_value.make_json (s)
+ Result.put (js_value, js_key)
+ end
+
+ json_references (l: LIST [STRING]): JSON_ARRAY
+ -- A JSON array of JSON (Dojo style) reference objects using the
+ -- strings in `l' as reference values. The caller is responsable
+ -- for ensuring the validity of all strings in `l' as json
+ -- references.
+ require
+ l_not_void: l /= Void
+ local
+ c: ITERATION_CURSOR [STRING]
+ do
+ create Result.make_array
+ from
+ c := l.new_cursor
+ until
+ c.after
+ loop
+ Result.add (json_reference (c.item))
+ c.forth
+ end
+ end
+
+feature -- Change
+
+ add_converter (jc: JSON_CONVERTER)
+ -- Add the converter `jc'.
+ require
+ jc_not_void: jc /= Void
+ do
+ converters.force (jc, jc.object.generator)
+ ensure
+ has_converter: converter_for (jc.object) /= Void
+ end
+
+feature {NONE} -- Implementation
+
+ converters: HASH_TABLE [JSON_CONVERTER, STRING]
+ -- Converters hashed by generator (base class)
+ once
+ create Result.make (10)
+ end
+
+feature {NONE} -- Implementation (Exceptions)
+
+ exception_prefix: STRING = "eJSON exception: "
+
+ exception_failed_to_convert_to_eiffel (a_value: JSON_VALUE; base_class: detachable STRING): STRING
+ -- Exception message for failing to convert a JSON_VALUE to an instance of `a'.
+ do
+ Result := exception_prefix + "Failed to convert JSON_VALUE to an Eiffel object: " + a_value.generator
+ if base_class /= Void then
+ Result.append (" -> {" + base_class + "}")
+ end
+ end
+
+ exception_failed_to_convert_to_json (an_object: detachable ANY): STRING
+ -- Exception message for failing to convert `a' to a JSON_VALUE.
+ do
+ Result := exception_prefix + "Failed to convert Eiffel object to a JSON_VALUE"
+ if an_object /= Void then
+ Result.append (" : {" + an_object.generator + "}")
+ end
+ end
+
+feature {NONE} -- Implementation (JSON parser)
+
+ json_parser: JSON_PARSER
+ once
+ create Result.make_parser ("")
+ end
+
+end -- class EJSON
diff --git a/library/kernel/json_array.e b/library/kernel/json_array.e
index 60757c84..62480452 100644
--- a/library/kernel/json_array.e
+++ b/library/kernel/json_array.e
@@ -1,176 +1,176 @@
-note
- description: "[
- JSON_ARRAY represent an array in JSON.
- An array in JSON is an ordered set of names.
- Examples
- array
- []
- [elements]
- ]"
-
- author: "Javier Velilla"
- date: "2008/08/24"
- revision: "Revision 0.1"
-
-class
- JSON_ARRAY
-
-inherit
- JSON_VALUE
-
- ITERABLE [JSON_VALUE]
-
-create
- make_array
-
-feature {NONE} -- Initialization
-
- make_array
- -- Initialize JSON Array
- do
- create values.make (10)
- end
-
-feature -- Access
-
- i_th alias "[]" (i: INTEGER): JSON_VALUE
- -- Item at `i'-th position
- require
- is_valid_index: valid_index (i)
- do
- Result := values.i_th (i)
- end
-
- representation: STRING
- local
- i: INTEGER
- do
- Result := "["
- from
- i := 1
- until
- i > count
- loop
- Result.append (i_th (i).representation)
- i := i + 1
- if i <= count then
- Result.append_character (',')
- end
- end
- Result.append_character (']')
- end
-
-feature -- Visitor pattern
-
- accept (a_visitor: JSON_VISITOR)
- -- Accept `a_visitor'.
- -- (Call `visit_json_array' procedure on `a_visitor'.)
- do
- a_visitor.visit_json_array (Current)
- end
-
-feature -- Access
-
- new_cursor: ITERATION_CURSOR [JSON_VALUE]
- -- Fresh cursor associated with current structure
- do
- Result := values.new_cursor
- end
-
-feature -- Mesurement
-
- count: INTEGER
- -- Number of items.
- do
- Result := values.count
- end
-
-feature -- Status report
-
- valid_index (i: INTEGER): BOOLEAN
- -- Is `i' a valid index?
- do
- Result := (1 <= i) and (i <= count)
- end
-
-feature -- Change Element
-
- put_front (v: JSON_VALUE)
- require
- v_not_void: v /= Void
- do
- values.put_front (v)
- ensure
- has_new_value: old values.count + 1 = values.count and
- values.first = v
- end
-
- add, extend (v: JSON_VALUE)
- require
- v_not_void: v /= Void
- do
- values.extend (v)
- ensure
- has_new_value: old values.count + 1 = values.count and
- values.has (v)
- end
-
- prune_all (v: JSON_VALUE)
- -- Remove all occurrences of `v'.
- require
- v_not_void: v /= Void
- do
- values.prune_all (v)
- ensure
- not_has_new_value: not values.has (v)
- end
-
- wipe_out
- -- Remove all items.
- do
- values.wipe_out
- end
-
-feature -- Report
-
- hash_code: INTEGER
- -- Hash code value
- do
- from
- values.start
- Result := values.item.hash_code
- until
- values.off
- loop
- Result:= ((Result \\ 8388593) |<< 8) + values.item.hash_code
- values.forth
- end
- Result := Result \\ values.count
- end
-
-feature -- Conversion
-
- array_representation: ARRAYED_LIST [JSON_VALUE]
- -- Representation as a sequences of values
- -- be careful, modifying the return object may have impact on the original JSON_ARRAY object
- do
- Result := values
- end
-
-feature -- Status report
-
- debug_output: STRING
- -- String that should be displayed in debugger to represent `Current'.
- do
- Result := count.out + " item(s)"
- end
-
-feature {NONE} -- Implementation
-
- values: ARRAYED_LIST [JSON_VALUE]
- -- Value container
-
-invariant
- value_not_void: values /= Void
-
-end
+note
+ description: "[
+ JSON_ARRAY represent an array in JSON.
+ An array in JSON is an ordered set of names.
+ Examples
+ array
+ []
+ [elements]
+ ]"
+
+ author: "Javier Velilla"
+ date: "2008/08/24"
+ revision: "Revision 0.1"
+
+class
+ JSON_ARRAY
+
+inherit
+ JSON_VALUE
+
+ ITERABLE [JSON_VALUE]
+
+create
+ make_array
+
+feature {NONE} -- Initialization
+
+ make_array
+ -- Initialize JSON Array
+ do
+ create values.make (10)
+ end
+
+feature -- Access
+
+ i_th alias "[]" (i: INTEGER): JSON_VALUE
+ -- Item at `i'-th position
+ require
+ is_valid_index: valid_index (i)
+ do
+ Result := values.i_th (i)
+ end
+
+ representation: STRING
+ local
+ i: INTEGER
+ do
+ Result := "["
+ from
+ i := 1
+ until
+ i > count
+ loop
+ Result.append (i_th (i).representation)
+ i := i + 1
+ if i <= count then
+ Result.append_character (',')
+ end
+ end
+ Result.append_character (']')
+ end
+
+feature -- Visitor pattern
+
+ accept (a_visitor: JSON_VISITOR)
+ -- Accept `a_visitor'.
+ -- (Call `visit_json_array' procedure on `a_visitor'.)
+ do
+ a_visitor.visit_json_array (Current)
+ end
+
+feature -- Access
+
+ new_cursor: ITERATION_CURSOR [JSON_VALUE]
+ -- Fresh cursor associated with current structure
+ do
+ Result := values.new_cursor
+ end
+
+feature -- Mesurement
+
+ count: INTEGER
+ -- Number of items.
+ do
+ Result := values.count
+ end
+
+feature -- Status report
+
+ valid_index (i: INTEGER): BOOLEAN
+ -- Is `i' a valid index?
+ do
+ Result := (1 <= i) and (i <= count)
+ end
+
+feature -- Change Element
+
+ put_front (v: JSON_VALUE)
+ require
+ v_not_void: v /= Void
+ do
+ values.put_front (v)
+ ensure
+ has_new_value: old values.count + 1 = values.count and
+ values.first = v
+ end
+
+ add, extend (v: JSON_VALUE)
+ require
+ v_not_void: v /= Void
+ do
+ values.extend (v)
+ ensure
+ has_new_value: old values.count + 1 = values.count and
+ values.has (v)
+ end
+
+ prune_all (v: JSON_VALUE)
+ -- Remove all occurrences of `v'.
+ require
+ v_not_void: v /= Void
+ do
+ values.prune_all (v)
+ ensure
+ not_has_new_value: not values.has (v)
+ end
+
+ wipe_out
+ -- Remove all items.
+ do
+ values.wipe_out
+ end
+
+feature -- Report
+
+ hash_code: INTEGER
+ -- Hash code value
+ do
+ from
+ values.start
+ Result := values.item.hash_code
+ until
+ values.off
+ loop
+ Result:= ((Result \\ 8388593) |<< 8) + values.item.hash_code
+ values.forth
+ end
+ Result := Result \\ values.count
+ end
+
+feature -- Conversion
+
+ array_representation: ARRAYED_LIST [JSON_VALUE]
+ -- Representation as a sequences of values
+ -- be careful, modifying the return object may have impact on the original JSON_ARRAY object
+ do
+ Result := values
+ end
+
+feature -- Status report
+
+ debug_output: STRING
+ -- String that should be displayed in debugger to represent `Current'.
+ do
+ Result := count.out + " item(s)"
+ end
+
+feature {NONE} -- Implementation
+
+ values: ARRAYED_LIST [JSON_VALUE]
+ -- Value container
+
+invariant
+ value_not_void: values /= Void
+
+end
diff --git a/library/kernel/json_boolean.e b/library/kernel/json_boolean.e
index 32e7634a..cc17681c 100644
--- a/library/kernel/json_boolean.e
+++ b/library/kernel/json_boolean.e
@@ -1,61 +1,61 @@
-note
- description: "JSON Truth values"
- author: "Javier Velilla"
- date: "2008/08/24"
- revision: "Revision 0.1"
-
-class
- JSON_BOOLEAN
-
-inherit
- JSON_VALUE
-
-create
- make_boolean
-
-feature {NONE} -- Initialization
-
- make_boolean (an_item: BOOLEAN)
- --Initialize.
- do
- item := an_item
- end
-
-feature -- Access
-
- item: BOOLEAN
- -- Content
-
- hash_code: INTEGER
- -- Hash code value
- do
- Result := item.hash_code
- end
-
- representation: STRING
- do
- if item then
- Result := "true"
- else
- Result := "false"
- end
- end
-
-feature -- Visitor pattern
-
- accept (a_visitor: JSON_VISITOR)
- -- Accept `a_visitor'.
- -- (Call `visit_json_boolean' procedure on `a_visitor'.)
- do
- a_visitor.visit_json_boolean (Current)
- end
-
-feature -- Status report
-
- debug_output: STRING
- -- String that should be displayed in debugger to represent `Current'.
- do
- Result := item.out
- end
-
-end
+note
+ description: "JSON Truth values"
+ author: "Javier Velilla"
+ date: "2008/08/24"
+ revision: "Revision 0.1"
+
+class
+ JSON_BOOLEAN
+
+inherit
+ JSON_VALUE
+
+create
+ make_boolean
+
+feature {NONE} -- Initialization
+
+ make_boolean (an_item: BOOLEAN)
+ --Initialize.
+ do
+ item := an_item
+ end
+
+feature -- Access
+
+ item: BOOLEAN
+ -- Content
+
+ hash_code: INTEGER
+ -- Hash code value
+ do
+ Result := item.hash_code
+ end
+
+ representation: STRING
+ do
+ if item then
+ Result := "true"
+ else
+ Result := "false"
+ end
+ end
+
+feature -- Visitor pattern
+
+ accept (a_visitor: JSON_VISITOR)
+ -- Accept `a_visitor'.
+ -- (Call `visit_json_boolean' procedure on `a_visitor'.)
+ do
+ a_visitor.visit_json_boolean (Current)
+ end
+
+feature -- Status report
+
+ debug_output: STRING
+ -- String that should be displayed in debugger to represent `Current'.
+ do
+ Result := item.out
+ end
+
+end
diff --git a/library/kernel/json_null.e b/library/kernel/json_null.e
index 176b7d38..9c6f4ed7 100644
--- a/library/kernel/json_null.e
+++ b/library/kernel/json_null.e
@@ -1,47 +1,47 @@
-note
- description: "JSON Null Values"
- author: "Javier Velilla"
- date: "2008/08/24"
- revision: "Revision 0.1"
-
-class
- JSON_NULL
-
-inherit
- JSON_VALUE
-
-feature --Access
-
- hash_code: INTEGER
- -- Hash code value
- do
- Result := null_value.hash_code
- end
-
- representation: STRING
- do
- Result := "null"
- end
-
-feature -- Visitor pattern
-
- accept (a_visitor: JSON_VISITOR)
- -- Accept `a_visitor'.
- -- (Call `visit_element_a' procedure on `a_visitor'.)
- do
- a_visitor.visit_json_null (Current)
- end
-
-feature -- Status report
-
- debug_output: STRING
- -- String that should be displayed in debugger to represent `Current'.
- do
- Result := null_value
- end
-
-feature {NONE}-- Implementation
-
- null_value: STRING = "null"
-
-end
+note
+ description: "JSON Null Values"
+ author: "Javier Velilla"
+ date: "2008/08/24"
+ revision: "Revision 0.1"
+
+class
+ JSON_NULL
+
+inherit
+ JSON_VALUE
+
+feature --Access
+
+ hash_code: INTEGER
+ -- Hash code value
+ do
+ Result := null_value.hash_code
+ end
+
+ representation: STRING
+ do
+ Result := "null"
+ end
+
+feature -- Visitor pattern
+
+ accept (a_visitor: JSON_VISITOR)
+ -- Accept `a_visitor'.
+ -- (Call `visit_element_a' procedure on `a_visitor'.)
+ do
+ a_visitor.visit_json_null (Current)
+ end
+
+feature -- Status report
+
+ debug_output: STRING
+ -- String that should be displayed in debugger to represent `Current'.
+ do
+ Result := null_value
+ end
+
+feature {NONE}-- Implementation
+
+ null_value: STRING = "null"
+
+end
diff --git a/library/kernel/json_number.e b/library/kernel/json_number.e
index 69b5011e..5f8ea60f 100644
--- a/library/kernel/json_number.e
+++ b/library/kernel/json_number.e
@@ -1,99 +1,99 @@
-note
-
- description: "JSON Numbers, octal and hexadecimal formats are not used."
- author: "Javier Velilla"
- date: "2008/08/24"
- revision: "Revision 0.1"
- license:"MIT (see http://www.opensource.org/licenses/mit-license.php)"
-
-class
- JSON_NUMBER
-
-inherit
- JSON_VALUE
- redefine
- is_equal
- end
-
-create
- make_integer,
- make_natural,
- make_real
-
-feature {NONE} -- initialization
-
- make_integer (an_argument: INTEGER_64)
- -- Initialize an instance of JSON_NUMBER from the integer value of `an_argument'.
- do
- item := an_argument.out
- numeric_type := INTEGER_TYPE
- end
-
- make_natural (an_argument: NATURAL_64)
- -- Initialize an instance of JSON_NUMBER from the unsigned integer value of `an_argument'.
- do
- item := an_argument.out
- numeric_type := NATURAL_TYPE
- end
-
- make_real (an_argument: DOUBLE)
- -- Initialize an instance of JSON_NUMBER from the floating point value of `an_argument'.
- do
- item := an_argument.out
- numeric_type := DOUBLE_TYPE
- end
-
-feature -- Access
-
- item: STRING
- -- Content
-
- hash_code: INTEGER
- --Hash code value
- do
- Result := item.hash_code
- end
-
- representation: STRING
- do
- Result := item
- end
-
-feature -- Visitor pattern
-
- accept (a_visitor: JSON_VISITOR)
- -- Accept `a_visitor'.
- -- (Call `visit_json_number' procedure on `a_visitor'.)
- do
- a_visitor.visit_json_number (Current)
- end
-
-feature -- Status
-
- is_equal (other: like Current): BOOLEAN
- -- Is `other' attached to an object of the same type
- -- as current object and identical to it?
- do
- Result := item.is_equal (other.item)
- end
-
-feature -- Status report
-
- debug_output: STRING
- -- String that should be displayed in debugger to represent `Current'.
- do
- Result := item
- end
-
-feature -- Implementation
-
- INTEGER_TYPE: INTEGER = 1
- DOUBLE_TYPE: INTEGER = 2
- NATURAL_TYPE: INTEGER = 3
-
- numeric_type: INTEGER
-
-invariant
- item_not_void: item /= Void
-
-end
+note
+
+ description: "JSON Numbers, octal and hexadecimal formats are not used."
+ author: "Javier Velilla"
+ date: "2008/08/24"
+ revision: "Revision 0.1"
+ license:"MIT (see http://www.opensource.org/licenses/mit-license.php)"
+
+class
+ JSON_NUMBER
+
+inherit
+ JSON_VALUE
+ redefine
+ is_equal
+ end
+
+create
+ make_integer,
+ make_natural,
+ make_real
+
+feature {NONE} -- initialization
+
+ make_integer (an_argument: INTEGER_64)
+ -- Initialize an instance of JSON_NUMBER from the integer value of `an_argument'.
+ do
+ item := an_argument.out
+ numeric_type := INTEGER_TYPE
+ end
+
+ make_natural (an_argument: NATURAL_64)
+ -- Initialize an instance of JSON_NUMBER from the unsigned integer value of `an_argument'.
+ do
+ item := an_argument.out
+ numeric_type := NATURAL_TYPE
+ end
+
+ make_real (an_argument: DOUBLE)
+ -- Initialize an instance of JSON_NUMBER from the floating point value of `an_argument'.
+ do
+ item := an_argument.out
+ numeric_type := DOUBLE_TYPE
+ end
+
+feature -- Access
+
+ item: STRING
+ -- Content
+
+ hash_code: INTEGER
+ --Hash code value
+ do
+ Result := item.hash_code
+ end
+
+ representation: STRING
+ do
+ Result := item
+ end
+
+feature -- Visitor pattern
+
+ accept (a_visitor: JSON_VISITOR)
+ -- Accept `a_visitor'.
+ -- (Call `visit_json_number' procedure on `a_visitor'.)
+ do
+ a_visitor.visit_json_number (Current)
+ end
+
+feature -- Status
+
+ is_equal (other: like Current): BOOLEAN
+ -- Is `other' attached to an object of the same type
+ -- as current object and identical to it?
+ do
+ Result := item.is_equal (other.item)
+ end
+
+feature -- Status report
+
+ debug_output: STRING
+ -- String that should be displayed in debugger to represent `Current'.
+ do
+ Result := item
+ end
+
+feature -- Implementation
+
+ INTEGER_TYPE: INTEGER = 1
+ DOUBLE_TYPE: INTEGER = 2
+ NATURAL_TYPE: INTEGER = 3
+
+ numeric_type: INTEGER
+
+invariant
+ item_not_void: item /= Void
+
+end
diff --git a/library/kernel/json_string.e b/library/kernel/json_string.e
index ccd8e60d..d5401c37 100644
--- a/library/kernel/json_string.e
+++ b/library/kernel/json_string.e
@@ -1,329 +1,329 @@
-note
-
- description: "[
- A JSON_STRING represent a string in JSON.
- A string is a collection of zero or more Unicodes characters, wrapped in double
- quotes, using blackslash espaces.
- ]"
-
- author: "Javier Velilla"
- date: "2008/08/24"
- revision: "Revision 0.1"
- license:"MIT (see http://www.opensource.org/licenses/mit-license.php)"
-
-
-class
- JSON_STRING
-
-inherit
- JSON_VALUE
- redefine
- is_equal
- end
-
-create
- make_json,
- make_json_from_string_32,
- make_with_escaped_json
-
-convert
- make_json ({READABLE_STRING_8, STRING_8, IMMUTABLE_STRING_8}),
- make_json_from_string_32 ({READABLE_STRING_32, STRING_32, IMMUTABLE_STRING_32})
-
-feature {NONE} -- Initialization
-
- make_json (s: READABLE_STRING_8)
- -- Initialize.
- require
- item_not_void: s /= Void
- do
- make_with_escaped_json (escaped_json_string (s))
- end
-
- make_json_from_string_32 (s: READABLE_STRING_32)
- -- Initialize from STRING_32 `s'.
- require
- item_not_void: s /= Void
- do
- make_with_escaped_json (escaped_json_string_32 (s))
- end
-
- make_with_escaped_json (s: READABLE_STRING_8)
- -- Initialize with an_item already escaped
- require
- item_not_void: s /= Void
- do
- item := s
- end
-
-feature -- Access
-
- item: STRING
- -- Contents with escaped entities if any
-
- unescaped_string_8: STRING_8
- -- Unescaped string from `item'
- local
- s: like item
- i, n: INTEGER
- c: CHARACTER
- do
- s := item
- n := s.count
- create Result.make (n)
- from i := 1 until i > n loop
- c := s[i]
- if c = '\' then
- if i < n then
- inspect s[i+1]
- when '\' then
- Result.append_character ('\')
- i := i + 2
- when '%"' then
- Result.append_character ('%"')
- i := i + 2
- when 'n' then
- Result.append_character ('%N')
- i := i + 2
- when 'r' then
- Result.append_character ('%R')
- i := i + 2
- when 'u' then
- --| Leave unicode \uXXXX unescaped
- Result.append_character ('\')
- i := i + 1
- else
- Result.append_character ('\')
- i := i + 1
- end
- else
- Result.append_character ('\')
- i := i + 1
- end
- else
- Result.append_character (c)
- i := i + 1
- end
- end
- end
-
- unescaped_string_32: STRING_32
- -- Unescaped string 32 from `item'
- local
- s: like item
- i, n: INTEGER
- c: CHARACTER
- hex: STRING
- do
- s := item
- n := s.count
- create Result.make (n)
- from i := 1 until i > n loop
- c := s[i]
- if c = '\' then
- if i < n then
- inspect s[i+1]
- when '\' then
- Result.append_character ('\')
- i := i + 2
- when '%"' then
- Result.append_character ('%"')
- i := i + 2
- when 'n' then
- Result.append_character ('%N')
- i := i + 2
- when 'r' then
- Result.append_character ('%R')
- i := i + 2
- when 'u' then
- hex := s.substring (i+2, i+2+4 - 1)
- if hex.count = 4 then
- Result.append_code (hexadecimal_to_natural_32 (hex))
- end
- i := i + 2 + 4
- else
- Result.append_character ('\')
- i := i + 1
- end
- else
- Result.append_character ('\')
- i := i + 1
- end
- else
- Result.append_character (c.to_character_32)
- i := i + 1
- end
- end
- end
-
- representation: STRING
- -- String representation of `item' with escaped entities if any
- do
- create Result.make (item.count + 2)
- Result.append_character ('%"')
- Result.append (item)
- Result.append_character ('%"')
- end
-
-feature -- Visitor pattern
-
- accept (a_visitor: JSON_VISITOR)
- -- Accept `a_visitor'.
- -- (Call `visit_json_string' procedure on `a_visitor'.)
- do
- a_visitor.visit_json_string (Current)
- end
-
-feature -- Comparison
-
- is_equal (other: like Current): BOOLEAN
- -- Is JSON_STRING made of same character sequence as `other'
- -- (possibly with a different capacity)?
- do
- Result := item.same_string (other.item)
- end
-
-feature -- Change Element
-
- append (a_string: STRING)
- -- Add a_string
- require
- a_string_not_void: a_string /= Void
- do
- item.append_string (a_string)
- end
-
-feature -- Status report
-
- hash_code: INTEGER
- -- Hash code value
- do
- Result := item.hash_code
- end
-
-feature -- Status report
-
- debug_output: STRING
- -- String that should be displayed in debugger to represent `Current'.
- do
- Result := item
- end
-
-feature {NONE} -- Implementation
-
- is_hexadecimal (s: READABLE_STRING_8): BOOLEAN
- -- Is `s' an hexadecimal value?
- do
- Result := across s as scur all scur.item.is_hexa_digit end
- end
-
- hexadecimal_to_natural_32 (s: READABLE_STRING_8): NATURAL_32
- -- Hexadecimal string `s' converted to NATURAL_32 value
- require
- s_not_void: s /= Void
- is_hexadecimal: is_hexadecimal (s)
- local
- i, nb: INTEGER
- char: CHARACTER
- do
- nb := s.count
-
- if nb >= 2 and then s.item (2) = 'x' then
- i := 3
- else
- i := 1
- end
-
- from
- until
- i > nb
- loop
- Result := Result * 16
- char := s.item (i)
- if char >= '0' and then char <= '9' then
- Result := Result + (char |-| '0').to_natural_32
- else
- Result := Result + (char.lower |-| 'a' + 10).to_natural_32
- end
- i := i + 1
- end
- end
-
- escaped_json_string (s: READABLE_STRING_8): STRING_8
- -- JSON string with '"' and '\' characters escaped
- require
- s_not_void: s /= Void
- local
- i, n: INTEGER
- c: CHARACTER_8
- do
- n := s.count
- create Result.make (n + n // 10)
- from i := 1 until i > n loop
- c := s.item (i)
- inspect c
- when '%"' then Result.append_string ("\%"")
- when '\' then Result.append_string ("\\")
- when '%R' then Result.append_string ("\r")
- when '%N' then Result.append_string ("\n")
- else
- Result.extend (c)
- end
- i := i + 1
- end
- end
-
- escaped_json_string_32 (s: READABLE_STRING_32): STRING_8
- -- JSON string with '"' and '\' characters and unicode escaped
- require
- s_not_void: s /= Void
- local
- i, j, n: INTEGER
- uc: CHARACTER_32
- c: CHARACTER_8
- h: STRING_8
- do
- n := s.count
- create Result.make (n + n // 10)
- from i := 1 until i > n loop
- uc := s.item (i)
- if uc.is_character_8 then
- c := uc.to_character_8
- inspect c
- when '%"' then Result.append_string ("\%"")
- when '\' then Result.append_string ("\\")
- when '%R' then Result.append_string ("\r")
- when '%N' then Result.append_string ("\n")
- else
- Result.extend (c)
- end
- else
- Result.append ("\u")
- h := uc.code.to_hex_string
- -- Remove first 0 and keep 4 hexa digit
- from
- j := 1
- until
- h.count = 4 or (j <= h.count and then h.item (j) /= '0')
- loop
- j := j + 1
- end
- h := h.substring (j, h.count)
-
- from
- until
- h.count >= 4
- loop
- h.prepend_integer (0)
- end
- check h.count = 4 end
- Result.append (h)
- end
- i := i + 1
- end
- end
-
-invariant
- item_not_void: item /= Void
-
-end
+note
+
+ description: "[
+ A JSON_STRING represent a string in JSON.
+ A string is a collection of zero or more Unicodes characters, wrapped in double
+ quotes, using blackslash espaces.
+ ]"
+
+ author: "Javier Velilla"
+ date: "2008/08/24"
+ revision: "Revision 0.1"
+ license:"MIT (see http://www.opensource.org/licenses/mit-license.php)"
+
+
+class
+ JSON_STRING
+
+inherit
+ JSON_VALUE
+ redefine
+ is_equal
+ end
+
+create
+ make_json,
+ make_json_from_string_32,
+ make_with_escaped_json
+
+convert
+ make_json ({READABLE_STRING_8, STRING_8, IMMUTABLE_STRING_8}),
+ make_json_from_string_32 ({READABLE_STRING_32, STRING_32, IMMUTABLE_STRING_32})
+
+feature {NONE} -- Initialization
+
+ make_json (s: READABLE_STRING_8)
+ -- Initialize.
+ require
+ item_not_void: s /= Void
+ do
+ make_with_escaped_json (escaped_json_string (s))
+ end
+
+ make_json_from_string_32 (s: READABLE_STRING_32)
+ -- Initialize from STRING_32 `s'.
+ require
+ item_not_void: s /= Void
+ do
+ make_with_escaped_json (escaped_json_string_32 (s))
+ end
+
+ make_with_escaped_json (s: READABLE_STRING_8)
+ -- Initialize with an_item already escaped
+ require
+ item_not_void: s /= Void
+ do
+ item := s
+ end
+
+feature -- Access
+
+ item: STRING
+ -- Contents with escaped entities if any
+
+ unescaped_string_8: STRING_8
+ -- Unescaped string from `item'
+ local
+ s: like item
+ i, n: INTEGER
+ c: CHARACTER
+ do
+ s := item
+ n := s.count
+ create Result.make (n)
+ from i := 1 until i > n loop
+ c := s[i]
+ if c = '\' then
+ if i < n then
+ inspect s[i+1]
+ when '\' then
+ Result.append_character ('\')
+ i := i + 2
+ when '%"' then
+ Result.append_character ('%"')
+ i := i + 2
+ when 'n' then
+ Result.append_character ('%N')
+ i := i + 2
+ when 'r' then
+ Result.append_character ('%R')
+ i := i + 2
+ when 'u' then
+ --| Leave unicode \uXXXX unescaped
+ Result.append_character ('\')
+ i := i + 1
+ else
+ Result.append_character ('\')
+ i := i + 1
+ end
+ else
+ Result.append_character ('\')
+ i := i + 1
+ end
+ else
+ Result.append_character (c)
+ i := i + 1
+ end
+ end
+ end
+
+ unescaped_string_32: STRING_32
+ -- Unescaped string 32 from `item'
+ local
+ s: like item
+ i, n: INTEGER
+ c: CHARACTER
+ hex: STRING
+ do
+ s := item
+ n := s.count
+ create Result.make (n)
+ from i := 1 until i > n loop
+ c := s[i]
+ if c = '\' then
+ if i < n then
+ inspect s[i+1]
+ when '\' then
+ Result.append_character ('\')
+ i := i + 2
+ when '%"' then
+ Result.append_character ('%"')
+ i := i + 2
+ when 'n' then
+ Result.append_character ('%N')
+ i := i + 2
+ when 'r' then
+ Result.append_character ('%R')
+ i := i + 2
+ when 'u' then
+ hex := s.substring (i+2, i+2+4 - 1)
+ if hex.count = 4 then
+ Result.append_code (hexadecimal_to_natural_32 (hex))
+ end
+ i := i + 2 + 4
+ else
+ Result.append_character ('\')
+ i := i + 1
+ end
+ else
+ Result.append_character ('\')
+ i := i + 1
+ end
+ else
+ Result.append_character (c.to_character_32)
+ i := i + 1
+ end
+ end
+ end
+
+ representation: STRING
+ -- String representation of `item' with escaped entities if any
+ do
+ create Result.make (item.count + 2)
+ Result.append_character ('%"')
+ Result.append (item)
+ Result.append_character ('%"')
+ end
+
+feature -- Visitor pattern
+
+ accept (a_visitor: JSON_VISITOR)
+ -- Accept `a_visitor'.
+ -- (Call `visit_json_string' procedure on `a_visitor'.)
+ do
+ a_visitor.visit_json_string (Current)
+ end
+
+feature -- Comparison
+
+ is_equal (other: like Current): BOOLEAN
+ -- Is JSON_STRING made of same character sequence as `other'
+ -- (possibly with a different capacity)?
+ do
+ Result := item.same_string (other.item)
+ end
+
+feature -- Change Element
+
+ append (a_string: STRING)
+ -- Add a_string
+ require
+ a_string_not_void: a_string /= Void
+ do
+ item.append_string (a_string)
+ end
+
+feature -- Status report
+
+ hash_code: INTEGER
+ -- Hash code value
+ do
+ Result := item.hash_code
+ end
+
+feature -- Status report
+
+ debug_output: STRING
+ -- String that should be displayed in debugger to represent `Current'.
+ do
+ Result := item
+ end
+
+feature {NONE} -- Implementation
+
+ is_hexadecimal (s: READABLE_STRING_8): BOOLEAN
+ -- Is `s' an hexadecimal value?
+ do
+ Result := across s as scur all scur.item.is_hexa_digit end
+ end
+
+ hexadecimal_to_natural_32 (s: READABLE_STRING_8): NATURAL_32
+ -- Hexadecimal string `s' converted to NATURAL_32 value
+ require
+ s_not_void: s /= Void
+ is_hexadecimal: is_hexadecimal (s)
+ local
+ i, nb: INTEGER
+ char: CHARACTER
+ do
+ nb := s.count
+
+ if nb >= 2 and then s.item (2) = 'x' then
+ i := 3
+ else
+ i := 1
+ end
+
+ from
+ until
+ i > nb
+ loop
+ Result := Result * 16
+ char := s.item (i)
+ if char >= '0' and then char <= '9' then
+ Result := Result + (char |-| '0').to_natural_32
+ else
+ Result := Result + (char.lower |-| 'a' + 10).to_natural_32
+ end
+ i := i + 1
+ end
+ end
+
+ escaped_json_string (s: READABLE_STRING_8): STRING_8
+ -- JSON string with '"' and '\' characters escaped
+ require
+ s_not_void: s /= Void
+ local
+ i, n: INTEGER
+ c: CHARACTER_8
+ do
+ n := s.count
+ create Result.make (n + n // 10)
+ from i := 1 until i > n loop
+ c := s.item (i)
+ inspect c
+ when '%"' then Result.append_string ("\%"")
+ when '\' then Result.append_string ("\\")
+ when '%R' then Result.append_string ("\r")
+ when '%N' then Result.append_string ("\n")
+ else
+ Result.extend (c)
+ end
+ i := i + 1
+ end
+ end
+
+ escaped_json_string_32 (s: READABLE_STRING_32): STRING_8
+ -- JSON string with '"' and '\' characters and unicode escaped
+ require
+ s_not_void: s /= Void
+ local
+ i, j, n: INTEGER
+ uc: CHARACTER_32
+ c: CHARACTER_8
+ h: STRING_8
+ do
+ n := s.count
+ create Result.make (n + n // 10)
+ from i := 1 until i > n loop
+ uc := s.item (i)
+ if uc.is_character_8 then
+ c := uc.to_character_8
+ inspect c
+ when '%"' then Result.append_string ("\%"")
+ when '\' then Result.append_string ("\\")
+ when '%R' then Result.append_string ("\r")
+ when '%N' then Result.append_string ("\n")
+ else
+ Result.extend (c)
+ end
+ else
+ Result.append ("\u")
+ h := uc.code.to_hex_string
+ -- Remove first 0 and keep 4 hexa digit
+ from
+ j := 1
+ until
+ h.count = 4 or (j <= h.count and then h.item (j) /= '0')
+ loop
+ j := j + 1
+ end
+ h := h.substring (j, h.count)
+
+ from
+ until
+ h.count >= 4
+ loop
+ h.prepend_integer (0)
+ end
+ check h.count = 4 end
+ Result.append (h)
+ end
+ i := i + 1
+ end
+ end
+
+invariant
+ item_not_void: item /= Void
+
+end
diff --git a/library/kernel/scanner/json_parser.e b/library/kernel/scanner/json_parser.e
index 3eaa7388..d90264e5 100644
--- a/library/kernel/scanner/json_parser.e
+++ b/library/kernel/scanner/json_parser.e
@@ -1,513 +1,513 @@
-note
-
- description: "Parse serialized JSON data"
- author: "jvelilla"
- date: "2008/08/24"
- revision: "Revision 0.1"
-
-class
- JSON_PARSER
-
-inherit
- JSON_READER
- JSON_TOKENS
-
-create
- make_parser
-
-feature {NONE} -- Initialize
-
- make_parser (a_json: STRING)
- -- Initialize.
- require
- json_not_empty: a_json /= Void and then not a_json.is_empty
- do
- make (a_json)
- is_parsed := True
- create errors.make
- end
-
-feature -- Status report
-
- is_parsed: BOOLEAN
- -- Is parsed?
-
- errors: LINKED_LIST [STRING]
- -- Current errors
-
- current_errors: STRING
- -- Current errors as string
- do
- create Result.make_empty
- from
- errors.start
- until
- errors.after
- loop
- Result.append_string (errors.item + "%N")
- errors.forth
- end
- end
-
-feature -- Element change
-
- report_error (e: STRING)
- -- Report error `e'
- require
- e_not_void: e /= Void
- do
- errors.force (e)
- end
-
-feature -- Commands
-
- parse_json: detachable JSON_VALUE
- -- Parse JSON data `representation'
- -- start ::= object | array
- do
- if is_valid_start_symbol then
- Result := parse
- if extra_elements then
- is_parsed := False
- end
- else
- is_parsed := False
- report_error ("Syntax error unexpected token, expecting `{' or `['")
- end
- end
-
- parse: detachable JSON_VALUE
- -- Parse JSON data `representation'
- local
- c: CHARACTER
- do
- if is_parsed then
- skip_white_spaces
- c := actual
- inspect c
- when j_OBJECT_OPEN then
- Result := parse_object
- when j_STRING then
- Result := parse_string
- when j_ARRAY_OPEN then
- Result := parse_array
- else
- if c.is_digit or c = j_MINUS then
- Result := parse_number
- elseif is_null then
- Result := create {JSON_NULL}
- next
- next
- next
- elseif is_true then
- Result := create {JSON_BOOLEAN}.make_boolean (True)
- next
- next
- next
- elseif is_false then
- Result := create {JSON_BOOLEAN}.make_boolean (False)
- next
- next
- next
- next
- else
- is_parsed := False
- report_error ("JSON is not well formed in parse")
- Result := Void
- end
- end
- end
- ensure
- is_parsed_implies_result_not_void: is_parsed implies Result /= Void
- end
-
- parse_object: JSON_OBJECT
- -- object
- -- {}
- -- {"key" : "value" [,]}
- local
- has_more: BOOLEAN
- l_json_string: detachable JSON_STRING
- l_value: detachable JSON_VALUE
- do
- create Result.make
- -- check if is an empty object {}
- next
- skip_white_spaces
- if actual = j_OBJECT_CLOSE then
- --is an empty object
- else
- -- a complex object {"key" : "value"}
- previous
- from has_more := True until not has_more loop
- next
- skip_white_spaces
- l_json_string := parse_string
- next
- skip_white_spaces
- if actual = ':' then
- next
- skip_white_spaces
- else
- is_parsed := False
- report_error ("%N Input string is a not well formed JSON, expected: : found: " + actual.out)
- has_more := False
- end
-
- l_value := parse
- if is_parsed and then (l_value /= Void and l_json_string /= Void) then
- Result.put (l_value, l_json_string)
- next
- skip_white_spaces
- if actual = j_OBJECT_CLOSE then
- has_more := False
- elseif actual /= ',' then
- has_more := False
- is_parsed := False
- report_error ("JSON Object syntactically malformed expected , found: [" + actual.out + "]")
- end
- else
- has_more := False
- -- explain the error
- end
- end
- end
- end
-
- parse_string: detachable JSON_STRING
- -- Parsed string
- local
- has_more: BOOLEAN
- l_json_string: STRING
- l_unicode: STRING
- c: like actual
- do
- create l_json_string.make_empty
- if actual = j_STRING then
- from
- has_more := True
- until
- not has_more
- loop
- next
- c := actual
- if c = j_STRING then
- has_more := False
- elseif c = '%H' then
- next
- c := actual
- if c = 'u' then
- create l_unicode.make_from_string ("\u")
- l_unicode.append (read_unicode)
- c := actual
- if is_valid_unicode (l_unicode) then
- l_json_string.append (l_unicode)
- else
- has_more := False
- is_parsed := False
- report_error ("Input String is not well formed JSON, expected a Unicode value, found [" + c.out + " ]")
- end
- elseif (not is_special_character (c) and not is_special_control (c)) or c = '%N' then
- has_more := False
- is_parsed := False
- report_error ("Input String is not well formed JSON, found [" + c.out + " ]")
- else
- l_json_string.append_character ('\')
- l_json_string.append_character (c)
- end
- else
- if is_special_character (c) and c /= '/' then
- has_more := False
- is_parsed := False
- report_error ("Input String is not well formed JSON, found [" + c.out + " ]")
- else
- l_json_string.append_character (c)
- end
- end
- end
- create Result.make_with_escaped_json (l_json_string)
- else
- Result := Void
- end
- end
-
- parse_array: JSON_ARRAY
- -- array
- -- []
- -- [elements [,]]
- local
- flag: BOOLEAN
- l_value: detachable JSON_VALUE
- c: like actual
- do
- create Result.make_array
- --check if is an empty array []
- next
- skip_white_spaces
- if actual = j_array_close then
- --is an empty array
- else
- previous
- from
- flag := True
- until
- not flag
- loop
- next
- skip_white_spaces
- l_value := parse
- if is_parsed and then l_value /= Void then
- Result.add (l_value)
- next
- skip_white_spaces
- c := actual
- if c = j_ARRAY_CLOSE then
- flag := False
- elseif c /= ',' then
- flag := False
- is_parsed := False
- report_error ("Array is not well formed JSON, found [" + c.out + " ]")
- end
- else
- flag := False
- report_error ("Array is not well formed JSON, found [" + actual.out + " ]")
- end
- end
- end
- end
-
- parse_number: detachable JSON_NUMBER
- -- Parsed number
- local
- sb: STRING
- flag: BOOLEAN
- is_integer: BOOLEAN
- c: like actual
- do
- create sb.make_empty
- sb.append_character (actual)
-
- from
- flag := True
- until
- not flag
- loop
- next
- c := actual
- if not has_next or is_close_token (c)
- or c = ',' or c = '%N' or c = '%R'
- then
- flag := False
- previous
- else
- sb.append_character (c)
- end
- end
-
- if is_valid_number (sb) then
- if sb.is_integer then
- create Result.make_integer (sb.to_integer)
- is_integer := True
- elseif sb.is_double and not is_integer then
- create Result.make_real (sb.to_double)
- end
- else
- is_parsed := False
- report_error ("Expected a number, found: [ " + sb + " ]")
- end
- end
-
- is_null: BOOLEAN
- -- Word at index represents null?
- local
- l_null: STRING
- l_string: STRING
- do
- l_null := null_id
- l_string := json_substring (index,index + l_null.count - 1)
- if l_string.is_equal (l_null) then
- Result := True
- end
- end
-
- is_false: BOOLEAN
- -- Word at index represents false?
- local
- l_false: STRING
- l_string: STRING
- do
- l_false := false_id
- l_string := json_substring (index, index + l_false.count - 1)
- if l_string.is_equal (l_false) then
- Result := True
- end
- end
-
- is_true: BOOLEAN
- -- Word at index represents true?
- local
- l_true: STRING
- l_string: STRING
- do
- l_true := true_id
- l_string := json_substring (index,index + l_true.count - 1)
- if l_string.is_equal (l_true) then
- Result := True
- end
- end
-
- read_unicode: STRING
- -- Read unicode and return value
- local
- i: INTEGER
- do
- create Result.make_empty
- from
- i := 1
- until
- i > 4 or not has_next
- loop
- next
- Result.append_character (actual)
- i := i + 1
- end
- end
-
-feature {NONE} -- Implementation
-
- is_valid_number (a_number: STRING): BOOLEAN
- -- is 'a_number' a valid number based on this regular expression
- -- "-?(?: 0|[1-9]\d+)(?: \.\d+)?(?: [eE][+-]?\d+)?\b"?
- local
- s: detachable STRING
- c: CHARACTER
- i,n: INTEGER
- do
- create s.make_empty
- n := a_number.count
- if n = 0 then
- Result := False
- else
- Result := True
- i := 1
- --| "-?"
- c := a_number[i]
- if c = '-' then
- s.extend (c); i := i + 1; c := a_number[i]
- end
- --| "0|[1-9]\d*
- if c.is_digit then
- if c = '0' then
- --| "0"
- s.extend (c); i := i + 1; c := a_number[i]
- else
- --| "[1-9]"
- s.extend (c); i := i + 1; c := a_number[i]
- --| "\d*"
- from until i > n or not c.is_digit loop
- s.extend (c); i := i + 1; c := a_number[i]
- end
- end
- end
- end
- if Result then
- --| "(\.\d+)?"
- if c = '.' then
- --| "\.\d+" = "\.\d\d*"
- s.extend (c); i := i + 1; c := a_number[i]
- if c.is_digit then
- from until i > n or not c.is_digit loop
- s.extend (c); i := i + 1; c := a_number[i]
- end
- else
- Result := False --| expecting digit
- end
- end
- end
- if Result then --| "(?:[eE][+-]?\d+)?\b"
- if c = 'e' or c = 'E' then
- --| "[eE][+-]?\d+"
- s.extend (c); i := i + 1; c := a_number[i]
- if c = '+' or c = '-' then
- s.extend (c); i := i + 1; c := a_number[i]
- end
- if c.is_digit then
- from until i > n or not c.is_digit loop
- s.extend (c); i := i + 1; c := a_number[i]
- end
- else
- Result := False --| expecting digit
- end
- end
- end
- if Result then --| "\b"
- from until i > n or not c.is_space loop
- s.extend (c); i := i + 1; c := a_number[i]
- end
- Result := i > n and then s.same_string (a_number)
- end
- end
-
- is_valid_unicode (a_unicode: STRING): BOOLEAN
- -- is 'a_unicode' a valid unicode based on this regular expression
- -- "\\u[0-9a-fA-F]{4}"
- local
- i: INTEGER
- do
- if
- a_unicode.count = 6 and then
- a_unicode[1] = '\' and then
- a_unicode[2] = 'u'
- then
- from
- Result := True
- i := 3
- until
- i > 6 or Result = False
- loop
- inspect a_unicode[i]
- when '0'..'9', 'a'..'f', 'A'..'F' then
- else
- Result := False
- end
- i := i + 1
- end
- end
- end
-
- extra_elements: BOOLEAN
- -- has more elements?
- local
- c: like actual
- do
- if has_next then
- next
- end
- from
- c := actual
- until
- c /= ' ' or c /= '%R' or c /= '%U' or c /= '%T' or c /= '%N' or not has_next
- loop
- next
- end
- Result := has_next
- end
-
- is_valid_start_symbol : BOOLEAN
- -- expecting `{' or `[' as start symbol
- do
- if attached representation as s and then s.count > 0 then
- Result := s[1] = '{' or s[1] = '['
- end
- end
-
-feature {NONE} -- Constants
-
- false_id: STRING = "false"
-
- true_id: STRING = "true"
-
- null_id: STRING = "null"
-
-
-end
+note
+
+ description: "Parse serialized JSON data"
+ author: "jvelilla"
+ date: "2008/08/24"
+ revision: "Revision 0.1"
+
+class
+ JSON_PARSER
+
+inherit
+ JSON_READER
+ JSON_TOKENS
+
+create
+ make_parser
+
+feature {NONE} -- Initialize
+
+ make_parser (a_json: STRING)
+ -- Initialize.
+ require
+ json_not_empty: a_json /= Void and then not a_json.is_empty
+ do
+ make (a_json)
+ is_parsed := True
+ create errors.make
+ end
+
+feature -- Status report
+
+ is_parsed: BOOLEAN
+ -- Is parsed?
+
+ errors: LINKED_LIST [STRING]
+ -- Current errors
+
+ current_errors: STRING
+ -- Current errors as string
+ do
+ create Result.make_empty
+ from
+ errors.start
+ until
+ errors.after
+ loop
+ Result.append_string (errors.item + "%N")
+ errors.forth
+ end
+ end
+
+feature -- Element change
+
+ report_error (e: STRING)
+ -- Report error `e'
+ require
+ e_not_void: e /= Void
+ do
+ errors.force (e)
+ end
+
+feature -- Commands
+
+ parse_json: detachable JSON_VALUE
+ -- Parse JSON data `representation'
+ -- start ::= object | array
+ do
+ if is_valid_start_symbol then
+ Result := parse
+ if extra_elements then
+ is_parsed := False
+ end
+ else
+ is_parsed := False
+ report_error ("Syntax error unexpected token, expecting `{' or `['")
+ end
+ end
+
+ parse: detachable JSON_VALUE
+ -- Parse JSON data `representation'
+ local
+ c: CHARACTER
+ do
+ if is_parsed then
+ skip_white_spaces
+ c := actual
+ inspect c
+ when j_OBJECT_OPEN then
+ Result := parse_object
+ when j_STRING then
+ Result := parse_string
+ when j_ARRAY_OPEN then
+ Result := parse_array
+ else
+ if c.is_digit or c = j_MINUS then
+ Result := parse_number
+ elseif is_null then
+ Result := create {JSON_NULL}
+ next
+ next
+ next
+ elseif is_true then
+ Result := create {JSON_BOOLEAN}.make_boolean (True)
+ next
+ next
+ next
+ elseif is_false then
+ Result := create {JSON_BOOLEAN}.make_boolean (False)
+ next
+ next
+ next
+ next
+ else
+ is_parsed := False
+ report_error ("JSON is not well formed in parse")
+ Result := Void
+ end
+ end
+ end
+ ensure
+ is_parsed_implies_result_not_void: is_parsed implies Result /= Void
+ end
+
+ parse_object: JSON_OBJECT
+ -- object
+ -- {}
+ -- {"key" : "value" [,]}
+ local
+ has_more: BOOLEAN
+ l_json_string: detachable JSON_STRING
+ l_value: detachable JSON_VALUE
+ do
+ create Result.make
+ -- check if is an empty object {}
+ next
+ skip_white_spaces
+ if actual = j_OBJECT_CLOSE then
+ --is an empty object
+ else
+ -- a complex object {"key" : "value"}
+ previous
+ from has_more := True until not has_more loop
+ next
+ skip_white_spaces
+ l_json_string := parse_string
+ next
+ skip_white_spaces
+ if actual = ':' then
+ next
+ skip_white_spaces
+ else
+ is_parsed := False
+ report_error ("%N Input string is a not well formed JSON, expected: : found: " + actual.out)
+ has_more := False
+ end
+
+ l_value := parse
+ if is_parsed and then (l_value /= Void and l_json_string /= Void) then
+ Result.put (l_value, l_json_string)
+ next
+ skip_white_spaces
+ if actual = j_OBJECT_CLOSE then
+ has_more := False
+ elseif actual /= ',' then
+ has_more := False
+ is_parsed := False
+ report_error ("JSON Object syntactically malformed expected , found: [" + actual.out + "]")
+ end
+ else
+ has_more := False
+ -- explain the error
+ end
+ end
+ end
+ end
+
+ parse_string: detachable JSON_STRING
+ -- Parsed string
+ local
+ has_more: BOOLEAN
+ l_json_string: STRING
+ l_unicode: STRING
+ c: like actual
+ do
+ create l_json_string.make_empty
+ if actual = j_STRING then
+ from
+ has_more := True
+ until
+ not has_more
+ loop
+ next
+ c := actual
+ if c = j_STRING then
+ has_more := False
+ elseif c = '%H' then
+ next
+ c := actual
+ if c = 'u' then
+ create l_unicode.make_from_string ("\u")
+ l_unicode.append (read_unicode)
+ c := actual
+ if is_valid_unicode (l_unicode) then
+ l_json_string.append (l_unicode)
+ else
+ has_more := False
+ is_parsed := False
+ report_error ("Input String is not well formed JSON, expected a Unicode value, found [" + c.out + " ]")
+ end
+ elseif (not is_special_character (c) and not is_special_control (c)) or c = '%N' then
+ has_more := False
+ is_parsed := False
+ report_error ("Input String is not well formed JSON, found [" + c.out + " ]")
+ else
+ l_json_string.append_character ('\')
+ l_json_string.append_character (c)
+ end
+ else
+ if is_special_character (c) and c /= '/' then
+ has_more := False
+ is_parsed := False
+ report_error ("Input String is not well formed JSON, found [" + c.out + " ]")
+ else
+ l_json_string.append_character (c)
+ end
+ end
+ end
+ create Result.make_with_escaped_json (l_json_string)
+ else
+ Result := Void
+ end
+ end
+
+ parse_array: JSON_ARRAY
+ -- array
+ -- []
+ -- [elements [,]]
+ local
+ flag: BOOLEAN
+ l_value: detachable JSON_VALUE
+ c: like actual
+ do
+ create Result.make_array
+ --check if is an empty array []
+ next
+ skip_white_spaces
+ if actual = j_array_close then
+ --is an empty array
+ else
+ previous
+ from
+ flag := True
+ until
+ not flag
+ loop
+ next
+ skip_white_spaces
+ l_value := parse
+ if is_parsed and then l_value /= Void then
+ Result.add (l_value)
+ next
+ skip_white_spaces
+ c := actual
+ if c = j_ARRAY_CLOSE then
+ flag := False
+ elseif c /= ',' then
+ flag := False
+ is_parsed := False
+ report_error ("Array is not well formed JSON, found [" + c.out + " ]")
+ end
+ else
+ flag := False
+ report_error ("Array is not well formed JSON, found [" + actual.out + " ]")
+ end
+ end
+ end
+ end
+
+ parse_number: detachable JSON_NUMBER
+ -- Parsed number
+ local
+ sb: STRING
+ flag: BOOLEAN
+ is_integer: BOOLEAN
+ c: like actual
+ do
+ create sb.make_empty
+ sb.append_character (actual)
+
+ from
+ flag := True
+ until
+ not flag
+ loop
+ next
+ c := actual
+ if not has_next or is_close_token (c)
+ or c = ',' or c = '%N' or c = '%R'
+ then
+ flag := False
+ previous
+ else
+ sb.append_character (c)
+ end
+ end
+
+ if is_valid_number (sb) then
+ if sb.is_integer then
+ create Result.make_integer (sb.to_integer)
+ is_integer := True
+ elseif sb.is_double and not is_integer then
+ create Result.make_real (sb.to_double)
+ end
+ else
+ is_parsed := False
+ report_error ("Expected a number, found: [ " + sb + " ]")
+ end
+ end
+
+ is_null: BOOLEAN
+ -- Word at index represents null?
+ local
+ l_null: STRING
+ l_string: STRING
+ do
+ l_null := null_id
+ l_string := json_substring (index,index + l_null.count - 1)
+ if l_string.is_equal (l_null) then
+ Result := True
+ end
+ end
+
+ is_false: BOOLEAN
+ -- Word at index represents false?
+ local
+ l_false: STRING
+ l_string: STRING
+ do
+ l_false := false_id
+ l_string := json_substring (index, index + l_false.count - 1)
+ if l_string.is_equal (l_false) then
+ Result := True
+ end
+ end
+
+ is_true: BOOLEAN
+ -- Word at index represents true?
+ local
+ l_true: STRING
+ l_string: STRING
+ do
+ l_true := true_id
+ l_string := json_substring (index,index + l_true.count - 1)
+ if l_string.is_equal (l_true) then
+ Result := True
+ end
+ end
+
+ read_unicode: STRING
+ -- Read unicode and return value
+ local
+ i: INTEGER
+ do
+ create Result.make_empty
+ from
+ i := 1
+ until
+ i > 4 or not has_next
+ loop
+ next
+ Result.append_character (actual)
+ i := i + 1
+ end
+ end
+
+feature {NONE} -- Implementation
+
+ is_valid_number (a_number: STRING): BOOLEAN
+ -- is 'a_number' a valid number based on this regular expression
+ -- "-?(?: 0|[1-9]\d+)(?: \.\d+)?(?: [eE][+-]?\d+)?\b"?
+ local
+ s: detachable STRING
+ c: CHARACTER
+ i,n: INTEGER
+ do
+ create s.make_empty
+ n := a_number.count
+ if n = 0 then
+ Result := False
+ else
+ Result := True
+ i := 1
+ --| "-?"
+ c := a_number[i]
+ if c = '-' then
+ s.extend (c); i := i + 1; c := a_number[i]
+ end
+ --| "0|[1-9]\d*
+ if c.is_digit then
+ if c = '0' then
+ --| "0"
+ s.extend (c); i := i + 1; c := a_number[i]
+ else
+ --| "[1-9]"
+ s.extend (c); i := i + 1; c := a_number[i]
+ --| "\d*"
+ from until i > n or not c.is_digit loop
+ s.extend (c); i := i + 1; c := a_number[i]
+ end
+ end
+ end
+ end
+ if Result then
+ --| "(\.\d+)?"
+ if c = '.' then
+ --| "\.\d+" = "\.\d\d*"
+ s.extend (c); i := i + 1; c := a_number[i]
+ if c.is_digit then
+ from until i > n or not c.is_digit loop
+ s.extend (c); i := i + 1; c := a_number[i]
+ end
+ else
+ Result := False --| expecting digit
+ end
+ end
+ end
+ if Result then --| "(?:[eE][+-]?\d+)?\b"
+ if c = 'e' or c = 'E' then
+ --| "[eE][+-]?\d+"
+ s.extend (c); i := i + 1; c := a_number[i]
+ if c = '+' or c = '-' then
+ s.extend (c); i := i + 1; c := a_number[i]
+ end
+ if c.is_digit then
+ from until i > n or not c.is_digit loop
+ s.extend (c); i := i + 1; c := a_number[i]
+ end
+ else
+ Result := False --| expecting digit
+ end
+ end
+ end
+ if Result then --| "\b"
+ from until i > n or not c.is_space loop
+ s.extend (c); i := i + 1; c := a_number[i]
+ end
+ Result := i > n and then s.same_string (a_number)
+ end
+ end
+
+ is_valid_unicode (a_unicode: STRING): BOOLEAN
+ -- is 'a_unicode' a valid unicode based on this regular expression
+ -- "\\u[0-9a-fA-F]{4}"
+ local
+ i: INTEGER
+ do
+ if
+ a_unicode.count = 6 and then
+ a_unicode[1] = '\' and then
+ a_unicode[2] = 'u'
+ then
+ from
+ Result := True
+ i := 3
+ until
+ i > 6 or Result = False
+ loop
+ inspect a_unicode[i]
+ when '0'..'9', 'a'..'f', 'A'..'F' then
+ else
+ Result := False
+ end
+ i := i + 1
+ end
+ end
+ end
+
+ extra_elements: BOOLEAN
+ -- has more elements?
+ local
+ c: like actual
+ do
+ if has_next then
+ next
+ end
+ from
+ c := actual
+ until
+ c /= ' ' or c /= '%R' or c /= '%U' or c /= '%T' or c /= '%N' or not has_next
+ loop
+ next
+ end
+ Result := has_next
+ end
+
+ is_valid_start_symbol : BOOLEAN
+ -- expecting `{' or `[' as start symbol
+ do
+ if attached representation as s and then s.count > 0 then
+ Result := s[1] = '{' or s[1] = '['
+ end
+ end
+
+feature {NONE} -- Constants
+
+ false_id: STRING = "false"
+
+ true_id: STRING = "true"
+
+ null_id: STRING = "null"
+
+
+end
diff --git a/library/kernel/scanner/json_reader.e b/library/kernel/scanner/json_reader.e
index 112857bd..977e91ae 100644
--- a/library/kernel/scanner/json_reader.e
+++ b/library/kernel/scanner/json_reader.e
@@ -1,118 +1,118 @@
-note
- description: "Objects that ..."
- author: "jvelilla"
- date: "2008/08/24"
- revision: "0.1"
-
-class
- JSON_READER
-
-create
- make
-
-feature {NONE} -- Initialization
-
- make (a_json: STRING)
- -- Initialize Reader
- do
- set_representation (a_json)
- end
-
-feature -- Commands
-
- set_representation (a_json: STRING)
- -- Set `representation'.
- do
- a_json.left_adjust
- a_json.right_adjust
- representation := a_json
- index := 1
- end
-
- read: CHARACTER
- -- Read character
- do
- if not representation.is_empty then
- Result := representation.item (index)
- end
- end
-
- next
- -- Move to next index
- require
- has_more_elements: has_next
- do
- index := index + 1
- ensure
- incremented: old index + 1 = index
- end
-
- previous
- -- Move to previous index
- require
- not_is_first: has_previous
- do
- index := index - 1
- ensure
- incremented: old index - 1 = index
- end
-
- skip_white_spaces
- -- Remove white spaces
- local
- c: like actual
- do
- from
- c := actual
- until
- (c /= ' ' and c /= '%N' and c /= '%R' and c /= '%U' and c /= '%T' ) or not has_next
- loop
- next
- c := actual
- end
- end
-
- json_substring (start_index, end_index: INTEGER_32): STRING
- -- JSON representation between `start_index' and `end_index'
- do
- Result := representation.substring (start_index, end_index)
- end
-
-feature -- Status report
-
- has_next: BOOLEAN
- -- Has a next character?
- do
- Result := index <= representation.count
- end
-
- has_previous: BOOLEAN
- -- Has a previous character?
- do
- Result := index >= 1
- end
-
-feature -- Access
-
- representation: STRING
- -- Serialized representation of the original JSON string
-
-feature {NONE} -- Implementation
-
- actual: CHARACTER
- -- Current character or '%U' if none
- do
- if index > representation.count then
- Result := '%U'
- else
- Result := representation.item (index)
- end
- end
-
- index: INTEGER
- -- Actual index
-
-invariant
- representation_not_void: representation /= Void
-
-end
+note
+ description: "Objects that ..."
+ author: "jvelilla"
+ date: "2008/08/24"
+ revision: "0.1"
+
+class
+ JSON_READER
+
+create
+ make
+
+feature {NONE} -- Initialization
+
+ make (a_json: STRING)
+ -- Initialize Reader
+ do
+ set_representation (a_json)
+ end
+
+feature -- Commands
+
+ set_representation (a_json: STRING)
+ -- Set `representation'.
+ do
+ a_json.left_adjust
+ a_json.right_adjust
+ representation := a_json
+ index := 1
+ end
+
+ read: CHARACTER
+ -- Read character
+ do
+ if not representation.is_empty then
+ Result := representation.item (index)
+ end
+ end
+
+ next
+ -- Move to next index
+ require
+ has_more_elements: has_next
+ do
+ index := index + 1
+ ensure
+ incremented: old index + 1 = index
+ end
+
+ previous
+ -- Move to previous index
+ require
+ not_is_first: has_previous
+ do
+ index := index - 1
+ ensure
+ incremented: old index - 1 = index
+ end
+
+ skip_white_spaces
+ -- Remove white spaces
+ local
+ c: like actual
+ do
+ from
+ c := actual
+ until
+ (c /= ' ' and c /= '%N' and c /= '%R' and c /= '%U' and c /= '%T' ) or not has_next
+ loop
+ next
+ c := actual
+ end
+ end
+
+ json_substring (start_index, end_index: INTEGER_32): STRING
+ -- JSON representation between `start_index' and `end_index'
+ do
+ Result := representation.substring (start_index, end_index)
+ end
+
+feature -- Status report
+
+ has_next: BOOLEAN
+ -- Has a next character?
+ do
+ Result := index <= representation.count
+ end
+
+ has_previous: BOOLEAN
+ -- Has a previous character?
+ do
+ Result := index >= 1
+ end
+
+feature -- Access
+
+ representation: STRING
+ -- Serialized representation of the original JSON string
+
+feature {NONE} -- Implementation
+
+ actual: CHARACTER
+ -- Current character or '%U' if none
+ do
+ if index > representation.count then
+ Result := '%U'
+ else
+ Result := representation.item (index)
+ end
+ end
+
+ index: INTEGER
+ -- Actual index
+
+invariant
+ representation_not_void: representation /= Void
+
+end
diff --git a/library/kernel/scanner/json_tokens.e b/library/kernel/scanner/json_tokens.e
index db8dd9df..86f86ba3 100644
--- a/library/kernel/scanner/json_tokens.e
+++ b/library/kernel/scanner/json_tokens.e
@@ -1,77 +1,77 @@
-note
- description: ""
- author: "jvelilla"
- date: "2008/08/24"
- revision: "0.1"
-
-class
- JSON_TOKENS
-
-feature -- Access
-
- j_OBJECT_OPEN: CHARACTER = '{'
- j_ARRAY_OPEN: CHARACTER = '['
- j_OBJECT_CLOSE: CHARACTER = '}'
- j_ARRAY_CLOSE: CHARACTER = ']'
-
- j_STRING: CHARACTER = '"'
- j_PLUS: CHARACTER = '+'
- j_MINUS: CHARACTER = '-'
- j_DOT: CHARACTER = '.'
-
-feature -- Status report
-
- is_open_token (c: CHARACTER): BOOLEAN
- -- Characters which open a type
- do
- inspect c
- when j_OBJECT_OPEN, j_ARRAY_OPEN, j_STRING, j_PLUS, j_MINUS, j_DOT then
- Result := True
- else
-
- end
- end
-
- is_close_token (c: CHARACTER): BOOLEAN
- -- Characters which close a type
- do
- inspect c
- when j_OBJECT_CLOSE, j_ARRAY_CLOSE, j_STRING then
- Result := True
- else
-
- end
- end
-
- is_special_character (c: CHARACTER): BOOLEAN
- -- Control Characters
- -- %F Form feed
- -- %H backslasH
- -- %N Newline
- -- %R carriage Return
- -- %T horizontal Tab
- -- %B Backspace
- -- / Solidus
- -- " Quotation
- do
- inspect c
- when '%F', '%H', '%N', '%R', '%T', '%B', '/', '"' then
- Result := True
- else
-
- end
- end
-
- is_special_control (c: CHARACTER): BOOLEAN
- --Control Characters
- -- \b\f\n\r\t
- do
- inspect c
- when 'b', 'f', 'n', 'r', 't' then
- Result := True
- else
-
- end
- end
-
-end
+note
+ description: ""
+ author: "jvelilla"
+ date: "2008/08/24"
+ revision: "0.1"
+
+class
+ JSON_TOKENS
+
+feature -- Access
+
+ j_OBJECT_OPEN: CHARACTER = '{'
+ j_ARRAY_OPEN: CHARACTER = '['
+ j_OBJECT_CLOSE: CHARACTER = '}'
+ j_ARRAY_CLOSE: CHARACTER = ']'
+
+ j_STRING: CHARACTER = '"'
+ j_PLUS: CHARACTER = '+'
+ j_MINUS: CHARACTER = '-'
+ j_DOT: CHARACTER = '.'
+
+feature -- Status report
+
+ is_open_token (c: CHARACTER): BOOLEAN
+ -- Characters which open a type
+ do
+ inspect c
+ when j_OBJECT_OPEN, j_ARRAY_OPEN, j_STRING, j_PLUS, j_MINUS, j_DOT then
+ Result := True
+ else
+
+ end
+ end
+
+ is_close_token (c: CHARACTER): BOOLEAN
+ -- Characters which close a type
+ do
+ inspect c
+ when j_OBJECT_CLOSE, j_ARRAY_CLOSE, j_STRING then
+ Result := True
+ else
+
+ end
+ end
+
+ is_special_character (c: CHARACTER): BOOLEAN
+ -- Control Characters
+ -- %F Form feed
+ -- %H backslasH
+ -- %N Newline
+ -- %R carriage Return
+ -- %T horizontal Tab
+ -- %B Backspace
+ -- / Solidus
+ -- " Quotation
+ do
+ inspect c
+ when '%F', '%H', '%N', '%R', '%T', '%B', '/', '"' then
+ Result := True
+ else
+
+ end
+ end
+
+ is_special_control (c: CHARACTER): BOOLEAN
+ --Control Characters
+ -- \b\f\n\r\t
+ do
+ inspect c
+ when 'b', 'f', 'n', 'r', 't' then
+ Result := True
+ else
+
+ end
+ end
+
+end
diff --git a/test/autotest/test_suite/json_menu_example.txt b/test/autotest/test_suite/json_menu_example.txt
index bce42e86..fe6c37de 100644
--- a/test/autotest/test_suite/json_menu_example.txt
+++ b/test/autotest/test_suite/json_menu_example.txt
@@ -1,11 +1,11 @@
-{"menu": {
- "id": "file",
- "value": "File",
- "popup": {
- "menuitem": [
- {"value": "New", "onclick": "CreateNewDoc()"},
- {"value": "Open", "onclick": "OpenDoc()"},
- {"value": "Close", "onclick": "CloseDoc()"}
- ]
- }
+{"menu": {
+ "id": "file",
+ "value": "File",
+ "popup": {
+ "menuitem": [
+ {"value": "New", "onclick": "CreateNewDoc()"},
+ {"value": "Open", "onclick": "OpenDoc()"},
+ {"value": "Close", "onclick": "CloseDoc()"}
+ ]
+ }
}}
\ No newline at end of file
diff --git a/test/autotest/test_suite/test_json_core.e b/test/autotest/test_suite/test_json_core.e
index ec17537a..9c2febac 100644
--- a/test/autotest/test_suite/test_json_core.e
+++ b/test/autotest/test_suite/test_json_core.e
@@ -1,833 +1,833 @@
-class TEST_JSON_CORE
-
-inherit
- SHARED_EJSON
- rename default_create as shared_default_create end
- EQA_TEST_SET
- select default_create end
-
-feature -- Test
-
- test_json_number_and_integer
- local
- i: INTEGER
- jn: JSON_NUMBER
- jrep: STRING
- parser: JSON_PARSER
- do
- i := 42
- -- Eiffel value -> JSON value -> JSON representation
- create jn.make_integer (i)
- assert ("jn.representation.same_string (%"42%")", jn.representation.same_string ("42"))
- -- Eiffel value -> JSON value -> JSON representation with factory
- if attached {JSON_NUMBER} json.value (i) as l_jn then
- assert ("l_jn.representation.same_string (%"42%")", jn.representation.same_string ("42"))
- else
- assert ("json.value (i) is a JSON_NUMBER", False)
- end
-
- -- JSON representation-> JSON value -> Eiffel value
- -- Note: The JSON_FACTORY will return the smallest INTEGER_* object
- -- that can represent the value of the JSON number, in this case
- -- we know it is INTEGER_8 since the value is 42
- jrep := "42"
- create parser.make_parser (jrep)
- if attached {JSON_NUMBER} parser.parse as l_jn then
- if attached {INTEGER_8} json.object (jn, Void) as l_i8 then
- assert ("l_i8 = 42", l_i8 = 42)
- else
- assert ("json.object (jn, Void) is a INTEGER_8", False)
- end
- else
- assert ("parser.parse is a JSON_NUMBER", False)
- end
- end
-
- test_json_number_and_integer_8
- local
- i8: INTEGER_8
- jn: JSON_NUMBER
- jrep: STRING
- parser: JSON_PARSER
- do
- i8 := 42
- -- Eiffel value -> JSON value -> JSON representation
- create jn.make_integer (i8)
- assert ("jn.representation.same_string (%"42%")", jn.representation.same_string ("42"))
- -- Eiffel value -> JSON value -> JSON representation with factory
- if attached {JSON_NUMBER} json.value (i8) as l_jn then
- assert ("l_jn.representation.same_string (%"42%")", jn.representation.same_string ("42"))
- else
- assert ("json.value (i8) is a JSON_NUMBER", False)
- end
-
- -- JSON representation -> JSON value -> Eiffel value
- -- Note: The JSON_FACTORY will return the smallest INTEGER_* object
- -- that can represent the value of the JSON number, in this case
- -- we know it is INTEGER_8 since the value is 42
- jrep := "42"
- create parser.make_parser (jrep)
- if attached {JSON_NUMBER} parser.parse as l_jn then
- if attached {INTEGER_8} json.object (jn, Void) as l_i8 then
- assert ("l_i8 = 42", l_i8 = 42)
- else
- assert ("json.object (jn, Void) is a INTEGER_8", False)
- end
- else
- assert ("parser.parse is a JSON_NUMBER", False)
- end
- end
-
- test_json_number_and_integer_16
- local
- i16: INTEGER_16
- jn: JSON_NUMBER
- jrep: STRING
- parser: JSON_PARSER
- do
- i16 := 300
- -- Eiffel value -> JSON value -> JSON representation
- create jn.make_integer (i16)
- assert ("jn.representation.same_string (%"300%")", jn.representation.same_string ("300"))
- -- Eiffel value -> JSON with factory
- if attached {JSON_NUMBER} json.value (i16) as l_jn then
- assert ("l_jn.representation.same_string (%"300%")", l_jn.representation.same_string ("300"))
- else
- assert ("json.value (i16) is a JSON_NUMBER", False)
- end
-
- -- JSON representation -> JSON value -> Eiffel value
- -- Note: The JSON_FACTORY will return the smallest INTEGER_* object
- -- that can represent the value of the JSON number, in this case
- -- we know it is INTEGER_16 since the value is 300
- jrep := "300"
- create parser.make_parser (jrep)
- if attached {JSON_NUMBER} parser.parse as l_jn then
- if attached {INTEGER_16} json.object (jn, Void) as l_i16 then
- assert ("l_i16 = 300", l_i16 = 300)
- else
- assert ("json.object (jn, Void) is a INTEGER_16", False)
- end
- else
- assert ("parser.parse is a JSON_NUMBER", False)
- end
- end
-
- test_json_number_and_integer_32
- local
- i32: INTEGER_32
- jn: JSON_NUMBER
- jrep: STRING
- parser: JSON_PARSER
- do
- i32 := 100000
- -- Eiffel value -> JSON representation -> JSON value
- create jn.make_integer (i32)
- assert ("jn.representation.same_string (%"100000%")", jn.representation.same_string ("100000"))
- -- Eiffel value -> JSON representation -> JSON value with factory
- if attached {JSON_NUMBER} json.value (i32) as l_jn then
- assert ("l_jn.representation.same_string (%"100000%")", l_jn.representation.same_string ("100000"))
- else
- assert ("json.value (i32) is a JSON_NUMBER", False)
- end
-
- -- JSON representation -> JSON value -> Eiffel value
- -- Note: The JSON_FACTORY will return the smallest INTEGER_* object
- -- that can represent the value of the JSON number, in this case
- -- we know it is INTEGER_32 since the value is 100000
- jrep := "100000"
- create parser.make_parser (jrep)
- if attached {JSON_NUMBER} parser.parse as l_jn then
- if attached {INTEGER_32} json.object (jn, Void) as l_i32 then
- assert ("l_i32 = 100000", l_i32 = 100000)
- else
- assert ("json.object (jn, Void) is a INTEGER_32", False)
- end
- else
- assert ("parser.parse is a JSON_NUMBER", False)
- end
- end
-
- test_json_number_and_integer_64
- local
- i64: INTEGER_64
- jn: JSON_NUMBER
- jrep: STRING
- parser: JSON_PARSER
- do
- i64 := 42949672960
- -- Eiffel value -> JSON value -> JSON representation
- create jn.make_integer (i64)
- assert ("jn.representation.same_string (%"42949672960%")", jn.representation.same_string ("42949672960"))
- -- Eiffel value -> JSON value -> JSON representation with factory
- if attached {JSON_NUMBER} json.value (i64) as l_jn then
- assert ("l_jn.representation.same_string (%"42949672960%")", l_jn.representation.same_string ("42949672960"))
- else
- assert ("json.value (i64) is a JSON_NUMBER", False)
- end
-
- -- JSON representation -> JSON value -> Eiffel value
- -- Note: The JSON_FACTORY will return the smallest INTEGER_* object
- -- that can represent the value of the JSON number, in this case
- -- we know it is INTEGER_32 since the value is 42949672960
- jrep := "42949672960"
- create parser.make_parser (jrep)
- if attached {JSON_NUMBER} parser.parse as l_jn then
- if attached {INTEGER_64} json.object (jn, Void) as l_i64 then
- assert ("l_i64 = 42949672960", l_i64 = 42949672960)
- else
- assert ("json.object (jn, Void) is a INTEGER_64", False)
- end
- else
- assert ("parser.parse is a JSON_NUMBER", False)
- end
- end
-
- test_json_number_and_natural_8
- local
- n8: NATURAL_8
- jn: JSON_NUMBER
- jrep: STRING
- parser: JSON_PARSER
- do
- n8 := 200
- -- Eiffel value -> JSON value -> JSON representation
- create jn.make_natural (n8)
- assert ("jn.representation.same_string (%"200%")", jn.representation.same_string ("200"))
- -- Eiffel value -> JSON value -> JSON representation with factory
- if attached {JSON_NUMBER} json.value (n8) as l_jn then
- assert ("l_jn.representation.same_string (%"200%")", l_jn.representation.same_string ("200"))
- else
- assert ("json.value (n8) is a JSON_NUMBER}", False)
- end
-
- -- JSON representation -> JSON value -> Eiffel value
- -- Note: The JSON_FACTORY will return the smallest INTEGER_* object
- -- that can represent the value of the JSON number, in this case
- -- we know it is INTEGER_16 since the value is 200
- jrep := "200"
- create parser.make_parser (jrep)
- if attached {JSON_NUMBER} parser.parse as l_jn then
- if attached {INTEGER_16} json.object (jn, Void) as i16 then
- assert ("i16 = 200", i16 = 200)
- else
- assert ("json.object (jn, Void) is an INTEGER_16", False)
- end
- else
- assert ("parser.parse is a JSON_NUMBER", False)
- end
- end
-
- test_json_number_and_natural_16
- local
- n16: NATURAL_16
- jn: JSON_NUMBER
- jrep: STRING
- parser: JSON_PARSER
- do
- n16 := 32768
- -- Eiffel value -> JSON value -> JSON representation
- create jn.make_natural (n16)
- assert ("jn.representation.same_string (%"32768%")", jn.representation.same_string ("32768"))
- -- Eiffel value -> JSON value -> JSON representation with factory
- if attached {JSON_NUMBER} json.value (n16) as l_jn then
- assert ("l_jn.representation.same_string (%"32768%")", l_jn.representation.same_string ("32768"))
- else
- assert ("json.value (n16) is a JSON_NUMBER", False)
- end
-
- -- JSON representation -> JSON value -> Eiffel value
- -- Note: The JSON_FACTORY will return the smallest INTEGER_* object
- -- that can represent the value of the JSON number, in this case
- -- we know it is INTEGER_32 since the value is 32768
- jrep := "32768"
- create parser.make_parser (jrep)
- if attached {JSON_NUMBER} parser.parse as l_jn then
- if attached {INTEGER_32} json.object (jn, Void) as i32 then
- assert ("i32 = 32768", i32 = 32768)
- else
- assert ("json.object (jn, Void) is a INTEGER_32", False)
- end
- else
- assert ("parser.parse is a JSON_NUMBER", False)
- end
- end
-
- test_json_number_and_natural_32
- local
- n32: NATURAL_32
- jn: JSON_NUMBER
- jrep: STRING
- parser: JSON_PARSER
- do
- n32 := 2147483648
- -- Eiffel value -> JSON value -> JSON representation
- create jn.make_natural (n32)
- assert ("jn.representation.same_string (%"2147483648%")", jn.representation.same_string ("2147483648"))
- -- Eiffel value -> JSON value -> JSON representation with factory
- if attached json.value (n32) as l_jn then
- assert ("l_jn.representation.same_string (%"2147483648%")", l_jn.representation.same_string ("2147483648"))
- else
- assert ("json.value (n32) is a JSON_NUMBER", False)
- end
-
- -- JSON representation -> JSON value -> Eiffel value
- -- Note: The JSON_FACTORY will return the smallest INTEGER_* object
- -- that can represent the value of the JSON number, in this case
- -- we know it is INTEGER_64 since the value is 2147483648
- jrep := "2147483648"
- create parser.make_parser (jrep)
- if attached {JSON_NUMBER} parser.parse as l_jn then
- if attached {INTEGER_64} json.object (jn, Void) as i64 then
- assert ("i64 = 2147483648", i64 = 2147483648)
- else
- assert ("json.object (jn, Void) is a INTEGER_64", False)
- end
- else
- assert ("parser.parse is a JSON_NUMBER", False)
- end
- end
-
- test_json_number_and_large_integers
- local
- jrep: STRING
- n64: NATURAL_64
- jn: JSON_NUMBER
- parser: JSON_PARSER
- do
- n64 := 9223372036854775808
- -- Eiffel value -> JSON value -> JSON representation
- create jn.make_natural (n64)
- assert ("jn.representation.same_string (%"9223372036854775808%")", jn.representation.same_string ("9223372036854775808"))
- -- Eiffel value -> JSON value -> JSON representation with factory
- if attached {JSON_NUMBER} json.value (n64) as l_jn then
- assert ("l_jn.representation.same_string (%"9223372036854775808%")", l_jn.representation.same_string ("9223372036854775808"))
- else
- assert ("json.value (n64) is a JSON_NUMBER", False)
- end
-
- -- JSON representation -> JSON value -> Eiffel value
- -- Note: The JSON_FACTORY will return the smallest INTEGER_* object
- -- that can represent the value of the JSON number, in this case
- -- we know it is INTEGER_32 since the value is 42949672960
- jrep := "9223372036854775808" -- 1 higher than largest positive number that can be represented by INTEGER 64
- create parser.make_parser (jrep)
- if attached {JSON_NUMBER} parser.parse as l_jn then
- if attached {NATURAL_64} json.object (jn, Void) as l_n64 then
- assert ("l_n64 = 9223372036854775808", l_n64 = 9223372036854775808)
- else
- assert ("json.object (jn, Void) is a NATURAL_64", False)
- end
- else
- assert ("parser.parse is a JSON_NUMBER", False)
- end
- end
-
- test_json_number_and_eiffel_real
- local
- r: REAL
- jn: JSON_NUMBER
- jrep: STRING
- parser: JSON_PARSER
- do
- r := 3.14
- -- Eiffel value -> JSON value -> JSON representation
- create jn.make_real (r)
- assert ("jn.representation.same_string (%"3.1400001049041748%")", jn.representation.same_string ("3.1400001049041748"))
- -- Eiffel value -> JSON value -> JSON representation with factory
- if attached {JSON_NUMBER} json.value (r) as l_jn then
- assert ("l_jn.representation.same_string (%"3.1400001049041748%")", l_jn.representation.same_string ("3.1400001049041748"))
- else
- assert ("json.value (r) is a JSON_NUMBER", False)
- end
-
- -- JSON representation -> JSON value -> Eiffel value
- -- Note: The JSON_FACTORY will always return a REAL_64 if the value
- -- of the JSON number is a floating point number
- jrep := "3.14"
- create parser.make_parser (jrep)
- if attached {JSON_NUMBER} parser.parse as l_jn then
- if attached {REAL_64} json.object (jn, Void) as r64 then
- assert ("3.14 <= r64 and r64 <= 3.141", 3.14 <= r64 and r64 <= 3.141)
- else
- assert ("json.object (jn, Void) is a REAL_64", False)
- end
- else
- assert ("parser.parse is a JSON_NUMBER", False)
- end
- end
-
- test_json_number_and_eiffel_real_32
- local
- r32: REAL_32
- jn: JSON_NUMBER
- jrep: STRING
- parser: JSON_PARSER
- do
- r32 := 3.14
- -- Eiffel value -> JSON value -> JSON representation
- create jn.make_real (r32)
- assert ("jn.representation.same_string (%"3.1400001049041748%")", jn.representation.same_string ("3.1400001049041748"))
- -- Eiffel value -> JSON value -> JSON representation with factory
- if attached {JSON_NUMBER} json.value (r32) as l_jn then
- assert ("l_jn.representation.same_string (%"3.1400001049041748%")", l_jn.representation.same_string ("3.1400001049041748"))
- else
- assert ("json.value (r32) is a JSON_NUMBER", False)
- end
-
- -- JSON representation -> JSON value -> Eiffel value
- jrep := "3.1400001049041748"
- create parser.make_parser (jrep)
- if attached {JSON_NUMBER} parser.parse as l_jn then
- if attached {REAL_64} json.object (l_jn, Void) as r64 then
- assert ("r64 = 3.1400001049041748", r64 = 3.1400001049041748)
- else
- assert ("json.object (l_jn, Void) is a REAL_64", False)
- end
- else
- assert ("parser.parse is a JSON_NUMBER", False)
- end
- end
-
- test_json_number_and_eiffel_real_64
- local
- r64: REAL_64
- jn: JSON_NUMBER
- jrep: STRING
- parser: JSON_PARSER
- do
- r64 := 3.1415926535897931
- -- Eiffel value -> JSON value -> JSON representation
- create jn.make_real (r64)
- assert ("jn.representation.same_string (%"3.1415926535897931%")", jn.representation.same_string ("3.1415926535897931"))
-
- -- Eiffel value -> JSON value -> JSON representation with factory
- if attached {JSON_NUMBER} json.value (r64) as l_jn then
- assert ("l_jn.representation.same_string (%"3.1415926535897931%")", l_jn.representation.same_string ("3.1415926535897931"))
- else
- assert ("json.value (r64) is a JSON_NUMBER", False)
- end
-
- -- JSON representation -> JSON value -> Eiffel value
- jrep := "3.1415926535897931"
- create parser.make_parser (jrep)
- if attached {JSON_NUMBER} parser.parse as l_jn then
- if attached {REAL_64} json.object (jn, Void) as l_r64 then
- assert ("l_r64 = 3.1415926535897931", l_r64 = 3.1415926535897931)
- else
- assert ("json.object (jn, Void) is a REAL_64", False)
- end
- else
- assert ("parser.parse is a JSON_NUMBER", False)
- end
- end
-
- test_json_boolean
- local
- parser: JSON_PARSER
- jb: JSON_BOOLEAN
- b: BOOLEAN
- do
- -- Eiffel value -> JSON value -> JSON representation
- b := True
- create jb.make_boolean (b)
- assert ("jb.representation.is_equal (%"true%")", jb.representation.is_equal ("true"))
- -- Eiffel value -> JSON value -> JSON representation with factory
- if attached {JSON_BOOLEAN} json.value (b) as l_jb then
- assert ("l_jb.representation.same_string (%"true%")", l_jb.representation.same_string ("true"))
- else
- assert ("l_jb /= Void", False)
- end
-
- -- JSON representation -> JSON value -> Eiffel value
- create parser.make_parser ("true")
- if attached {JSON_BOOLEAN} parser.parse as l_jb then
- if attached {BOOLEAN} json.object (l_jb, Void) as l_b then
- assert ("l_b = True", l_b = True)
- else
- assert ("json.object (l_jb, Void) is BOOLEAN", False)
- end
- else
- assert ("parser.parse is a JSON_BOOLEAN", False)
- end
-
- -- Eiffel value -> JSON value -> JSON representation
- b := False
- create jb.make_boolean (b)
- assert ("jb.representation.same_string (%"false%")", jb.representation.same_string ("false"))
- -- Eiffel value -> JSON value -> JSON representation with factory
- if attached {JSON_BOOLEAN} json.value (b) as l_jb then
- assert ("l_jb.representation.same_string (%"false%")", l_jb.representation.same_string ("false"))
- else
- assert ("json.value (b) is a JSON_BOOLEAN", False)
- end
-
- -- JSON representation -> JSON value -> Eiffel value
- create parser.make_parser ("false")
- if attached {JSON_BOOLEAN} parser.parse as l_jb then
- if attached {BOOLEAN} json.object (l_jb, Void) as l_b then
- assert ("l_b = False", l_b = False)
- else
- assert ("json.object (l_jb, Void) is a BOOLEAN", False)
- end
- else
- assert ("parser.parse is a JSON_BOOLEAN", False)
- end
- end
-
- test_json_null
- local
- a: detachable ANY
- dummy_object: STRING
- jn: detachable JSON_NULL
- jrep: STRING
- parser: JSON_PARSER
- do
- -- Eiffel value -> JSON value -> JSON representation
- create jn
- assert ("jn /= Void", jn /= Void)
- assert ("jn.representation.is_equal (%"%"null%"%")", jn.representation.is_equal ("null"))
- -- Eiffel value -> JSON value -> JSON representation with factory
- jn ?= json.value (Void)
- assert ("jn /= Void", jn /= Void)
- if attached jn as l_jn then
- assert ("jn.representation.is_equal (%"null%")", l_jn.representation.is_equal ("null"))
- end
-
- -- JSON representation -> JSON value -> Eiffel value
- jrep := "null"
- create parser.make_parser (jrep)
- jn := Void
- jn ?= parser.parse
- assert ("jn /= Void", jn /= Void)
- create dummy_object.make_empty
- a := dummy_object
- a ?= json.object (jn, Void)
- assert ("a = Void", a = Void)
- end
-
- test_json_string_and_character
- local
- c: CHARACTER
- js: detachable JSON_STRING
- jrep: STRING
- parser: JSON_PARSER
- do
- c := 'a'
- -- Eiffel value -> JSON value -> JSON representation
- create js.make_json (c.out)
- assert ("js /= Void", js /= Void)
- assert ("js.representation.is_equal (%"%"a%"%")", js.representation.is_equal ("%"a%""))
- -- Eiffel value -> JSON value -> JSON representation with factory
- js ?= json.value (c)
- assert ("js /= Void", js /= Void)
- if attached js as l_js then
- assert ("js.representation.is_equal (%"%"a%"%")", l_js.representation.is_equal ("%"a%""))
- end
-
- -- JSON representation -> JSON value -> Eiffel value
- jrep := "%"a%""
- create parser.make_parser (jrep)
- js := Void
- js ?= parser.parse
- assert ("js /= Void", js /= Void)
- if attached {STRING_32} json.object (js, Void) as ucs then
- assert ("ucs.string.is_equal (%"a%")", ucs.string.is_equal ("a"))
- end
-
- end
-
- test_json_string_and_string
- local
- s: STRING
- js: detachable JSON_STRING
- jrep: STRING
- parser: JSON_PARSER
- do
- s := "foobar"
- -- Eiffel value -> JSON value -> JSON representation
- create js.make_json (s)
- assert ("js /= Void", js /= Void)
- assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.is_equal ("%"foobar%""))
- -- Eiffel value -> JSON value -> JSON representation with factory
- js ?= json.value (s)
- assert ("js /= Void", js /= Void)
- if attached js as l_js then
- assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.is_equal ("%"foobar%""))
- end
-
- -- JSON representation -> JSON value -> Eiffel value
- jrep := "%"foobar%""
- create parser.make_parser (jrep)
- js := Void
- js ?= parser.parse
- assert ("js /= Void", js /= Void)
- if attached {STRING_32} json.object (js, Void) as l_ucs then
- assert ("ucs.string.is_equal (%"foobar%")", l_ucs.string.is_equal ("foobar"))
- end
- end
-
- test_json_string_and_uc_string
- local
- js: detachable JSON_STRING
- ucs: detachable STRING_32
- jrep: STRING
- parser: JSON_PARSER
- do
- create ucs.make_from_string ("foobar")
- -- Eiffel value -> JSON value -> JSON representation
- create js.make_json (ucs)
- assert ("js /= Void", js /= Void)
- assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.is_equal ("%"foobar%""))
- -- Eiffel value -> JSON value -> JSON representation with factory
- js ?= json.value (ucs)
- assert ("js /= Void", js /= Void)
- if attached js as l_js then
- assert ("js.representation.is_equal (%"%"foobar%"%")", l_js.representation.is_equal ("%"foobar%""))
- end
-
- -- JSON representation -> JSON value -> Eiffel value
- jrep := "%"foobar%""
- create parser.make_parser (jrep)
- js := Void
- js ?= parser.parse
- assert ("js /= Void", js /= Void)
- ucs := Void
- ucs ?= json.object (js, Void)
- if attached ucs as l_ucs then
- assert ("ucs.string.is_equal (%"foobar%")", l_ucs.string.is_equal ("foobar"))
- end
- end
-
- test_json_string_and_special_characters
- local
- js: detachable JSON_STRING
- s: detachable STRING_8
- ucs: detachable STRING_32
- jrep: STRING
- parser: JSON_PARSER
- do
- create s.make_from_string ("foo\bar")
- create js.make_json (s)
-
- assert ("js.representation.same_string (%"%"foo\\bar%"%")", js.representation.same_string ("%"foo\\bar%""))
-
- -- Eiffel value -> JSON value -> JSON representation with factory
- js ?= json.value (s)
- assert ("js /= Void", js /= Void)
- if js /= Void then
- assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.same_string ("%"foo\\bar%""))
- end
-
- -- JSON representation -> JSON value -> Eiffel value
- jrep := "%"foo\\bar%""
- create parser.make_parser (jrep)
- js ?= parser.parse
- assert ("js /= Void", js /= Void)
- ucs ?= json.object (js, Void)
- if ucs /= Void then
- assert ("ucs.same_string (%"foo\bar%")", ucs.same_string ("foo\bar"))
- end
-
- jrep := "%"foo\\bar%""
- create parser.make_parser (jrep)
- if attached {JSON_STRING} parser.parse as jstring then
- assert ("unescaped string %"foo\\bar%" to %"foo\bar%"", jstring.unescaped_string_8.same_string ("foo\bar"))
- end
-
- create js.make_json_from_string_32 ({STRING_32}"%/20320/%/22909/")
- assert ("escaping unicode string32 %"%%/20320/%%/22909/%" %"\u4F60\u597D%"", js.item.same_string ("\u4F60\u597D"))
-
- jrep := "%"\u4F60\u597D%"" --| Ni hao
- create parser.make_parser (jrep)
- if attached {JSON_STRING} parser.parse as jstring then
- assert ("same unicode string32 %"%%/20320/%%/22909/%"", jstring.unescaped_string_32.same_string ({STRING_32}"%/20320/%/22909/"))
- end
- end
-
- test_json_array
- local
- ll: LINKED_LIST [INTEGER_8]
- ll2: detachable LINKED_LIST [detachable ANY]
- ja: detachable JSON_ARRAY
- jn: JSON_NUMBER
- jrep: STRING
- parser: JSON_PARSER
- do
- -- Eiffel value -> JSON value -> JSON representation
- create ll.make
- ll.extend (0)
- ll.extend (1)
- ll.extend (1)
- ll.extend (2)
- ll.extend (3)
- ll.extend (5)
- -- Note: Currently there is no simple way of creating a JSON_ARRAY
- -- from an LINKED_LIST.
- create ja.make_array
- from
- ll.start
- until
- ll.after
- loop
- create jn.make_integer (ll.item)
- ja.add (jn)
- ll.forth
- end
- assert ("ja /= Void", ja /= Void)
- assert ("ja.representation.is_equal (%"[0,1,1,2,3,5]%")", ja.representation.is_equal ("[0,1,1,2,3,5]"))
- -- Eiffel value -> JSON value -> JSON representation with factory
- ja := Void
- ja ?= json.value (ll)
- assert ("ja /= Void", ja /= Void)
- if attached ja as l_ja then
- assert ("ja.representation.is_equal (%"[0,1,1,2,3,5]%")", l_ja.representation.is_equal ("[0,1,1,2,3,5]"))
- end
-
- -- JSON representation -> JSON value -> Eiffel value
- -- Note: The JSON_FACTORY will return the smallest INTEGER_* object
- -- that can represent the value of the JSON number, in this case
- -- it means we will get an LINKED_LIST [ANY] containing the INTEGER_8
- -- values 0, 1, 1, 2, 3, 5
- jrep := "[0,1,1,2,3,5]"
- create parser.make_parser (jrep)
- ja := Void
- ja ?= parser.parse
- assert ("ja /= Void", ja /= Void)
- ll2 ?= json.object (ja, Void)
- assert ("ll2 /= Void", ll2 /= Void)
- --ll.compare_objects
- --ll2.compare_objects
- if attached ll2 as l_ll2 then
- assert ("ll2.is_equal (ll)", l_ll2.is_equal (ll))
- end
-
- end
-
- test_json_object
- local
- t, t2: detachable HASH_TABLE [detachable ANY, STRING_GENERAL]
- i: INTEGER
- ucs_key, ucs: STRING_32
- a: ARRAY [INTEGER]
- jo: detachable JSON_OBJECT
- jn: JSON_NUMBER
- js_key, js: JSON_STRING
- ja: JSON_ARRAY
- jrep: STRING
- parser: JSON_PARSER
- do
- -- Eiffel value -> JSON value -> JSON representation
- -- Note: Currently there is now way of creating a JSON_OBJECT from
- -- a HASH_TABLE, so we do it manually.
- -- t = {"name": "foobar", "size": 42, "contents", [0, 1, 1, 2, 3, 5]}
- create jo.make
- create js_key.make_json ("name")
- create js.make_json ("foobar")
- jo.put (js, js_key)
- create js_key.make_json ("size")
- create jn.make_integer (42)
- jo.put (jn, js_key)
- create js_key.make_json ("contents")
- create ja.make_array
- create jn.make_integer (0)
- ja.add (jn)
- create jn.make_integer (1)
- ja.add (jn)
- create jn.make_integer (1)
- ja.add (jn)
- create jn.make_integer (2)
- ja.add (jn)
- create jn.make_integer (3)
- ja.add (jn)
- create jn.make_integer (5)
- ja.add (jn)
- jo.put (ja, js_key)
- assert ("jo /= Void", jo /= Void)
- assert ("jo.representation.is_equal (%"{%"name%":%"foobar%",%"size%":42,%"contents%":[0,1,1,2,3,5]}%")", jo.representation.is_equal ("{%"name%":%"foobar%",%"size%":42,%"contents%":[0,1,1,2,3,5]}"))
- -- Eiffel value -> JSON value -> JSON representation with factory
- create t.make (3)
- create ucs_key.make_from_string ("name")
- create ucs.make_from_string ("foobar")
- t.put (ucs, ucs_key)
- create ucs_key.make_from_string ("size")
- i := 42
- t.put (i, ucs_key)
- create ucs_key.make_from_string ("contents")
- a := <<0, 1, 1, 2, 3, 5>>
- t.put (a, ucs_key)
- jo := Void
- jo ?= json.value (t)
- assert ("jo /= Void", jo /= Void)
- if attached jo as l_jo then
- assert ("jo.representation.is_equal (%"{%"name%":%"foobar%",%"size%":42,%"contents%":[0,1,1,2,3,5]}%")", l_jo.representation.is_equal ("{%"name%":%"foobar%",%"size%":42,%"contents%":[0,1,1,2,3,5]}"))
- end
- -- JSON representation -> JSON value -> Eiffel value -> JSON value -> JSON representation
- jrep := "{%"name%":%"foobar%",%"size%":42,%"contents%":[0,1,1,2,3,5]}"
- create parser.make_parser (jrep)
- jo := Void
- jo ?= parser.parse
- assert ("jo /= Void", jo /= Void)
- t2 ?= json.object (jo, Void)
- assert ("t2 /= Void", t2 /= Void)
- jo ?= json.value (t2)
- assert ("jo /= Void", jo /= Void)
- if attached jo as l_jo then
- assert ("jrep.is_equal (jo.representation)", jrep.is_equal (jo.representation))
- end
-
- end
-
- test_json_object_hash_code
- local
- ht: HASH_TABLE [ANY, JSON_VALUE]
- jo: JSON_OBJECT
- do
- create ht.make (1)
- create jo.make
- ht.force ("", jo)
- assert ("ht.has_key (jo)", ht.has_key (jo))
- end
-
- test_json_failed_json_conversion
- -- Test converting an Eiffel object to JSON that is based on a class
- -- for which no JSON converter has been registered.
- local
- gv: OPERATING_ENVIRONMENT
- jv: detachable JSON_VALUE
- exception: BOOLEAN
- do
- if not exception then
- create gv
- jv := json.value (gv)
- else
- assert ("exceptions.is_developer_exception", json.is_developer_exception)
--- assert ("exceptions.is_developer_exception_of_name", json.is_developer_exception_of_name ("eJSON exception: Failed to convert Eiffel object to a JSON_VALUE: OPERATING_ENVIRONMENT"))
- end
- rescue
- exception := True
- retry
- end
-
- test_json_failed_eiffel_conversion
- -- Test converting from a JSON value to an Eiffel object based on a
- -- class for which no JSON converter has been registered.
- local
- gv : detachable OPERATING_ENVIRONMENT
- jo: JSON_OBJECT
- exception: BOOLEAN
- do
- if not exception then
- create jo.make
- gv ?= json.object (jo, "OPERATING_ENVIRONMENT")
- else
- assert ("exceptions.is_developer_exception", json.is_developer_exception)
--- assert ("exceptions.is_developer_exception_of_name", json.is_developer_exception_of_name ("eJSON exception: Failed to convert JSON_VALUE to an Eiffel object: JSON_OBJECT -> OPERATING_ENVIRONMENT"))
-
- end
- rescue
- exception := True
- retry
- end
-
-end -- class TEST_JSON_CORE
+class TEST_JSON_CORE
+
+inherit
+ SHARED_EJSON
+ rename default_create as shared_default_create end
+ EQA_TEST_SET
+ select default_create end
+
+feature -- Test
+
+ test_json_number_and_integer
+ local
+ i: INTEGER
+ jn: JSON_NUMBER
+ jrep: STRING
+ parser: JSON_PARSER
+ do
+ i := 42
+ -- Eiffel value -> JSON value -> JSON representation
+ create jn.make_integer (i)
+ assert ("jn.representation.same_string (%"42%")", jn.representation.same_string ("42"))
+ -- Eiffel value -> JSON value -> JSON representation with factory
+ if attached {JSON_NUMBER} json.value (i) as l_jn then
+ assert ("l_jn.representation.same_string (%"42%")", jn.representation.same_string ("42"))
+ else
+ assert ("json.value (i) is a JSON_NUMBER", False)
+ end
+
+ -- JSON representation-> JSON value -> Eiffel value
+ -- Note: The JSON_FACTORY will return the smallest INTEGER_* object
+ -- that can represent the value of the JSON number, in this case
+ -- we know it is INTEGER_8 since the value is 42
+ jrep := "42"
+ create parser.make_parser (jrep)
+ if attached {JSON_NUMBER} parser.parse as l_jn then
+ if attached {INTEGER_8} json.object (jn, Void) as l_i8 then
+ assert ("l_i8 = 42", l_i8 = 42)
+ else
+ assert ("json.object (jn, Void) is a INTEGER_8", False)
+ end
+ else
+ assert ("parser.parse is a JSON_NUMBER", False)
+ end
+ end
+
+ test_json_number_and_integer_8
+ local
+ i8: INTEGER_8
+ jn: JSON_NUMBER
+ jrep: STRING
+ parser: JSON_PARSER
+ do
+ i8 := 42
+ -- Eiffel value -> JSON value -> JSON representation
+ create jn.make_integer (i8)
+ assert ("jn.representation.same_string (%"42%")", jn.representation.same_string ("42"))
+ -- Eiffel value -> JSON value -> JSON representation with factory
+ if attached {JSON_NUMBER} json.value (i8) as l_jn then
+ assert ("l_jn.representation.same_string (%"42%")", jn.representation.same_string ("42"))
+ else
+ assert ("json.value (i8) is a JSON_NUMBER", False)
+ end
+
+ -- JSON representation -> JSON value -> Eiffel value
+ -- Note: The JSON_FACTORY will return the smallest INTEGER_* object
+ -- that can represent the value of the JSON number, in this case
+ -- we know it is INTEGER_8 since the value is 42
+ jrep := "42"
+ create parser.make_parser (jrep)
+ if attached {JSON_NUMBER} parser.parse as l_jn then
+ if attached {INTEGER_8} json.object (jn, Void) as l_i8 then
+ assert ("l_i8 = 42", l_i8 = 42)
+ else
+ assert ("json.object (jn, Void) is a INTEGER_8", False)
+ end
+ else
+ assert ("parser.parse is a JSON_NUMBER", False)
+ end
+ end
+
+ test_json_number_and_integer_16
+ local
+ i16: INTEGER_16
+ jn: JSON_NUMBER
+ jrep: STRING
+ parser: JSON_PARSER
+ do
+ i16 := 300
+ -- Eiffel value -> JSON value -> JSON representation
+ create jn.make_integer (i16)
+ assert ("jn.representation.same_string (%"300%")", jn.representation.same_string ("300"))
+ -- Eiffel value -> JSON with factory
+ if attached {JSON_NUMBER} json.value (i16) as l_jn then
+ assert ("l_jn.representation.same_string (%"300%")", l_jn.representation.same_string ("300"))
+ else
+ assert ("json.value (i16) is a JSON_NUMBER", False)
+ end
+
+ -- JSON representation -> JSON value -> Eiffel value
+ -- Note: The JSON_FACTORY will return the smallest INTEGER_* object
+ -- that can represent the value of the JSON number, in this case
+ -- we know it is INTEGER_16 since the value is 300
+ jrep := "300"
+ create parser.make_parser (jrep)
+ if attached {JSON_NUMBER} parser.parse as l_jn then
+ if attached {INTEGER_16} json.object (jn, Void) as l_i16 then
+ assert ("l_i16 = 300", l_i16 = 300)
+ else
+ assert ("json.object (jn, Void) is a INTEGER_16", False)
+ end
+ else
+ assert ("parser.parse is a JSON_NUMBER", False)
+ end
+ end
+
+ test_json_number_and_integer_32
+ local
+ i32: INTEGER_32
+ jn: JSON_NUMBER
+ jrep: STRING
+ parser: JSON_PARSER
+ do
+ i32 := 100000
+ -- Eiffel value -> JSON representation -> JSON value
+ create jn.make_integer (i32)
+ assert ("jn.representation.same_string (%"100000%")", jn.representation.same_string ("100000"))
+ -- Eiffel value -> JSON representation -> JSON value with factory
+ if attached {JSON_NUMBER} json.value (i32) as l_jn then
+ assert ("l_jn.representation.same_string (%"100000%")", l_jn.representation.same_string ("100000"))
+ else
+ assert ("json.value (i32) is a JSON_NUMBER", False)
+ end
+
+ -- JSON representation -> JSON value -> Eiffel value
+ -- Note: The JSON_FACTORY will return the smallest INTEGER_* object
+ -- that can represent the value of the JSON number, in this case
+ -- we know it is INTEGER_32 since the value is 100000
+ jrep := "100000"
+ create parser.make_parser (jrep)
+ if attached {JSON_NUMBER} parser.parse as l_jn then
+ if attached {INTEGER_32} json.object (jn, Void) as l_i32 then
+ assert ("l_i32 = 100000", l_i32 = 100000)
+ else
+ assert ("json.object (jn, Void) is a INTEGER_32", False)
+ end
+ else
+ assert ("parser.parse is a JSON_NUMBER", False)
+ end
+ end
+
+ test_json_number_and_integer_64
+ local
+ i64: INTEGER_64
+ jn: JSON_NUMBER
+ jrep: STRING
+ parser: JSON_PARSER
+ do
+ i64 := 42949672960
+ -- Eiffel value -> JSON value -> JSON representation
+ create jn.make_integer (i64)
+ assert ("jn.representation.same_string (%"42949672960%")", jn.representation.same_string ("42949672960"))
+ -- Eiffel value -> JSON value -> JSON representation with factory
+ if attached {JSON_NUMBER} json.value (i64) as l_jn then
+ assert ("l_jn.representation.same_string (%"42949672960%")", l_jn.representation.same_string ("42949672960"))
+ else
+ assert ("json.value (i64) is a JSON_NUMBER", False)
+ end
+
+ -- JSON representation -> JSON value -> Eiffel value
+ -- Note: The JSON_FACTORY will return the smallest INTEGER_* object
+ -- that can represent the value of the JSON number, in this case
+ -- we know it is INTEGER_32 since the value is 42949672960
+ jrep := "42949672960"
+ create parser.make_parser (jrep)
+ if attached {JSON_NUMBER} parser.parse as l_jn then
+ if attached {INTEGER_64} json.object (jn, Void) as l_i64 then
+ assert ("l_i64 = 42949672960", l_i64 = 42949672960)
+ else
+ assert ("json.object (jn, Void) is a INTEGER_64", False)
+ end
+ else
+ assert ("parser.parse is a JSON_NUMBER", False)
+ end
+ end
+
+ test_json_number_and_natural_8
+ local
+ n8: NATURAL_8
+ jn: JSON_NUMBER
+ jrep: STRING
+ parser: JSON_PARSER
+ do
+ n8 := 200
+ -- Eiffel value -> JSON value -> JSON representation
+ create jn.make_natural (n8)
+ assert ("jn.representation.same_string (%"200%")", jn.representation.same_string ("200"))
+ -- Eiffel value -> JSON value -> JSON representation with factory
+ if attached {JSON_NUMBER} json.value (n8) as l_jn then
+ assert ("l_jn.representation.same_string (%"200%")", l_jn.representation.same_string ("200"))
+ else
+ assert ("json.value (n8) is a JSON_NUMBER}", False)
+ end
+
+ -- JSON representation -> JSON value -> Eiffel value
+ -- Note: The JSON_FACTORY will return the smallest INTEGER_* object
+ -- that can represent the value of the JSON number, in this case
+ -- we know it is INTEGER_16 since the value is 200
+ jrep := "200"
+ create parser.make_parser (jrep)
+ if attached {JSON_NUMBER} parser.parse as l_jn then
+ if attached {INTEGER_16} json.object (jn, Void) as i16 then
+ assert ("i16 = 200", i16 = 200)
+ else
+ assert ("json.object (jn, Void) is an INTEGER_16", False)
+ end
+ else
+ assert ("parser.parse is a JSON_NUMBER", False)
+ end
+ end
+
+ test_json_number_and_natural_16
+ local
+ n16: NATURAL_16
+ jn: JSON_NUMBER
+ jrep: STRING
+ parser: JSON_PARSER
+ do
+ n16 := 32768
+ -- Eiffel value -> JSON value -> JSON representation
+ create jn.make_natural (n16)
+ assert ("jn.representation.same_string (%"32768%")", jn.representation.same_string ("32768"))
+ -- Eiffel value -> JSON value -> JSON representation with factory
+ if attached {JSON_NUMBER} json.value (n16) as l_jn then
+ assert ("l_jn.representation.same_string (%"32768%")", l_jn.representation.same_string ("32768"))
+ else
+ assert ("json.value (n16) is a JSON_NUMBER", False)
+ end
+
+ -- JSON representation -> JSON value -> Eiffel value
+ -- Note: The JSON_FACTORY will return the smallest INTEGER_* object
+ -- that can represent the value of the JSON number, in this case
+ -- we know it is INTEGER_32 since the value is 32768
+ jrep := "32768"
+ create parser.make_parser (jrep)
+ if attached {JSON_NUMBER} parser.parse as l_jn then
+ if attached {INTEGER_32} json.object (jn, Void) as i32 then
+ assert ("i32 = 32768", i32 = 32768)
+ else
+ assert ("json.object (jn, Void) is a INTEGER_32", False)
+ end
+ else
+ assert ("parser.parse is a JSON_NUMBER", False)
+ end
+ end
+
+ test_json_number_and_natural_32
+ local
+ n32: NATURAL_32
+ jn: JSON_NUMBER
+ jrep: STRING
+ parser: JSON_PARSER
+ do
+ n32 := 2147483648
+ -- Eiffel value -> JSON value -> JSON representation
+ create jn.make_natural (n32)
+ assert ("jn.representation.same_string (%"2147483648%")", jn.representation.same_string ("2147483648"))
+ -- Eiffel value -> JSON value -> JSON representation with factory
+ if attached json.value (n32) as l_jn then
+ assert ("l_jn.representation.same_string (%"2147483648%")", l_jn.representation.same_string ("2147483648"))
+ else
+ assert ("json.value (n32) is a JSON_NUMBER", False)
+ end
+
+ -- JSON representation -> JSON value -> Eiffel value
+ -- Note: The JSON_FACTORY will return the smallest INTEGER_* object
+ -- that can represent the value of the JSON number, in this case
+ -- we know it is INTEGER_64 since the value is 2147483648
+ jrep := "2147483648"
+ create parser.make_parser (jrep)
+ if attached {JSON_NUMBER} parser.parse as l_jn then
+ if attached {INTEGER_64} json.object (jn, Void) as i64 then
+ assert ("i64 = 2147483648", i64 = 2147483648)
+ else
+ assert ("json.object (jn, Void) is a INTEGER_64", False)
+ end
+ else
+ assert ("parser.parse is a JSON_NUMBER", False)
+ end
+ end
+
+ test_json_number_and_large_integers
+ local
+ jrep: STRING
+ n64: NATURAL_64
+ jn: JSON_NUMBER
+ parser: JSON_PARSER
+ do
+ n64 := 9223372036854775808
+ -- Eiffel value -> JSON value -> JSON representation
+ create jn.make_natural (n64)
+ assert ("jn.representation.same_string (%"9223372036854775808%")", jn.representation.same_string ("9223372036854775808"))
+ -- Eiffel value -> JSON value -> JSON representation with factory
+ if attached {JSON_NUMBER} json.value (n64) as l_jn then
+ assert ("l_jn.representation.same_string (%"9223372036854775808%")", l_jn.representation.same_string ("9223372036854775808"))
+ else
+ assert ("json.value (n64) is a JSON_NUMBER", False)
+ end
+
+ -- JSON representation -> JSON value -> Eiffel value
+ -- Note: The JSON_FACTORY will return the smallest INTEGER_* object
+ -- that can represent the value of the JSON number, in this case
+ -- we know it is INTEGER_32 since the value is 42949672960
+ jrep := "9223372036854775808" -- 1 higher than largest positive number that can be represented by INTEGER 64
+ create parser.make_parser (jrep)
+ if attached {JSON_NUMBER} parser.parse as l_jn then
+ if attached {NATURAL_64} json.object (jn, Void) as l_n64 then
+ assert ("l_n64 = 9223372036854775808", l_n64 = 9223372036854775808)
+ else
+ assert ("json.object (jn, Void) is a NATURAL_64", False)
+ end
+ else
+ assert ("parser.parse is a JSON_NUMBER", False)
+ end
+ end
+
+ test_json_number_and_eiffel_real
+ local
+ r: REAL
+ jn: JSON_NUMBER
+ jrep: STRING
+ parser: JSON_PARSER
+ do
+ r := 3.14
+ -- Eiffel value -> JSON value -> JSON representation
+ create jn.make_real (r)
+ assert ("jn.representation.same_string (%"3.1400001049041748%")", jn.representation.same_string ("3.1400001049041748"))
+ -- Eiffel value -> JSON value -> JSON representation with factory
+ if attached {JSON_NUMBER} json.value (r) as l_jn then
+ assert ("l_jn.representation.same_string (%"3.1400001049041748%")", l_jn.representation.same_string ("3.1400001049041748"))
+ else
+ assert ("json.value (r) is a JSON_NUMBER", False)
+ end
+
+ -- JSON representation -> JSON value -> Eiffel value
+ -- Note: The JSON_FACTORY will always return a REAL_64 if the value
+ -- of the JSON number is a floating point number
+ jrep := "3.14"
+ create parser.make_parser (jrep)
+ if attached {JSON_NUMBER} parser.parse as l_jn then
+ if attached {REAL_64} json.object (jn, Void) as r64 then
+ assert ("3.14 <= r64 and r64 <= 3.141", 3.14 <= r64 and r64 <= 3.141)
+ else
+ assert ("json.object (jn, Void) is a REAL_64", False)
+ end
+ else
+ assert ("parser.parse is a JSON_NUMBER", False)
+ end
+ end
+
+ test_json_number_and_eiffel_real_32
+ local
+ r32: REAL_32
+ jn: JSON_NUMBER
+ jrep: STRING
+ parser: JSON_PARSER
+ do
+ r32 := 3.14
+ -- Eiffel value -> JSON value -> JSON representation
+ create jn.make_real (r32)
+ assert ("jn.representation.same_string (%"3.1400001049041748%")", jn.representation.same_string ("3.1400001049041748"))
+ -- Eiffel value -> JSON value -> JSON representation with factory
+ if attached {JSON_NUMBER} json.value (r32) as l_jn then
+ assert ("l_jn.representation.same_string (%"3.1400001049041748%")", l_jn.representation.same_string ("3.1400001049041748"))
+ else
+ assert ("json.value (r32) is a JSON_NUMBER", False)
+ end
+
+ -- JSON representation -> JSON value -> Eiffel value
+ jrep := "3.1400001049041748"
+ create parser.make_parser (jrep)
+ if attached {JSON_NUMBER} parser.parse as l_jn then
+ if attached {REAL_64} json.object (l_jn, Void) as r64 then
+ assert ("r64 = 3.1400001049041748", r64 = 3.1400001049041748)
+ else
+ assert ("json.object (l_jn, Void) is a REAL_64", False)
+ end
+ else
+ assert ("parser.parse is a JSON_NUMBER", False)
+ end
+ end
+
+ test_json_number_and_eiffel_real_64
+ local
+ r64: REAL_64
+ jn: JSON_NUMBER
+ jrep: STRING
+ parser: JSON_PARSER
+ do
+ r64 := 3.1415926535897931
+ -- Eiffel value -> JSON value -> JSON representation
+ create jn.make_real (r64)
+ assert ("jn.representation.same_string (%"3.1415926535897931%")", jn.representation.same_string ("3.1415926535897931"))
+
+ -- Eiffel value -> JSON value -> JSON representation with factory
+ if attached {JSON_NUMBER} json.value (r64) as l_jn then
+ assert ("l_jn.representation.same_string (%"3.1415926535897931%")", l_jn.representation.same_string ("3.1415926535897931"))
+ else
+ assert ("json.value (r64) is a JSON_NUMBER", False)
+ end
+
+ -- JSON representation -> JSON value -> Eiffel value
+ jrep := "3.1415926535897931"
+ create parser.make_parser (jrep)
+ if attached {JSON_NUMBER} parser.parse as l_jn then
+ if attached {REAL_64} json.object (jn, Void) as l_r64 then
+ assert ("l_r64 = 3.1415926535897931", l_r64 = 3.1415926535897931)
+ else
+ assert ("json.object (jn, Void) is a REAL_64", False)
+ end
+ else
+ assert ("parser.parse is a JSON_NUMBER", False)
+ end
+ end
+
+ test_json_boolean
+ local
+ parser: JSON_PARSER
+ jb: JSON_BOOLEAN
+ b: BOOLEAN
+ do
+ -- Eiffel value -> JSON value -> JSON representation
+ b := True
+ create jb.make_boolean (b)
+ assert ("jb.representation.is_equal (%"true%")", jb.representation.is_equal ("true"))
+ -- Eiffel value -> JSON value -> JSON representation with factory
+ if attached {JSON_BOOLEAN} json.value (b) as l_jb then
+ assert ("l_jb.representation.same_string (%"true%")", l_jb.representation.same_string ("true"))
+ else
+ assert ("l_jb /= Void", False)
+ end
+
+ -- JSON representation -> JSON value -> Eiffel value
+ create parser.make_parser ("true")
+ if attached {JSON_BOOLEAN} parser.parse as l_jb then
+ if attached {BOOLEAN} json.object (l_jb, Void) as l_b then
+ assert ("l_b = True", l_b = True)
+ else
+ assert ("json.object (l_jb, Void) is BOOLEAN", False)
+ end
+ else
+ assert ("parser.parse is a JSON_BOOLEAN", False)
+ end
+
+ -- Eiffel value -> JSON value -> JSON representation
+ b := False
+ create jb.make_boolean (b)
+ assert ("jb.representation.same_string (%"false%")", jb.representation.same_string ("false"))
+ -- Eiffel value -> JSON value -> JSON representation with factory
+ if attached {JSON_BOOLEAN} json.value (b) as l_jb then
+ assert ("l_jb.representation.same_string (%"false%")", l_jb.representation.same_string ("false"))
+ else
+ assert ("json.value (b) is a JSON_BOOLEAN", False)
+ end
+
+ -- JSON representation -> JSON value -> Eiffel value
+ create parser.make_parser ("false")
+ if attached {JSON_BOOLEAN} parser.parse as l_jb then
+ if attached {BOOLEAN} json.object (l_jb, Void) as l_b then
+ assert ("l_b = False", l_b = False)
+ else
+ assert ("json.object (l_jb, Void) is a BOOLEAN", False)
+ end
+ else
+ assert ("parser.parse is a JSON_BOOLEAN", False)
+ end
+ end
+
+ test_json_null
+ local
+ a: detachable ANY
+ dummy_object: STRING
+ jn: detachable JSON_NULL
+ jrep: STRING
+ parser: JSON_PARSER
+ do
+ -- Eiffel value -> JSON value -> JSON representation
+ create jn
+ assert ("jn /= Void", jn /= Void)
+ assert ("jn.representation.is_equal (%"%"null%"%")", jn.representation.is_equal ("null"))
+ -- Eiffel value -> JSON value -> JSON representation with factory
+ jn ?= json.value (Void)
+ assert ("jn /= Void", jn /= Void)
+ if attached jn as l_jn then
+ assert ("jn.representation.is_equal (%"null%")", l_jn.representation.is_equal ("null"))
+ end
+
+ -- JSON representation -> JSON value -> Eiffel value
+ jrep := "null"
+ create parser.make_parser (jrep)
+ jn := Void
+ jn ?= parser.parse
+ assert ("jn /= Void", jn /= Void)
+ create dummy_object.make_empty
+ a := dummy_object
+ a ?= json.object (jn, Void)
+ assert ("a = Void", a = Void)
+ end
+
+ test_json_string_and_character
+ local
+ c: CHARACTER
+ js: detachable JSON_STRING
+ jrep: STRING
+ parser: JSON_PARSER
+ do
+ c := 'a'
+ -- Eiffel value -> JSON value -> JSON representation
+ create js.make_json (c.out)
+ assert ("js /= Void", js /= Void)
+ assert ("js.representation.is_equal (%"%"a%"%")", js.representation.is_equal ("%"a%""))
+ -- Eiffel value -> JSON value -> JSON representation with factory
+ js ?= json.value (c)
+ assert ("js /= Void", js /= Void)
+ if attached js as l_js then
+ assert ("js.representation.is_equal (%"%"a%"%")", l_js.representation.is_equal ("%"a%""))
+ end
+
+ -- JSON representation -> JSON value -> Eiffel value
+ jrep := "%"a%""
+ create parser.make_parser (jrep)
+ js := Void
+ js ?= parser.parse
+ assert ("js /= Void", js /= Void)
+ if attached {STRING_32} json.object (js, Void) as ucs then
+ assert ("ucs.string.is_equal (%"a%")", ucs.string.is_equal ("a"))
+ end
+
+ end
+
+ test_json_string_and_string
+ local
+ s: STRING
+ js: detachable JSON_STRING
+ jrep: STRING
+ parser: JSON_PARSER
+ do
+ s := "foobar"
+ -- Eiffel value -> JSON value -> JSON representation
+ create js.make_json (s)
+ assert ("js /= Void", js /= Void)
+ assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.is_equal ("%"foobar%""))
+ -- Eiffel value -> JSON value -> JSON representation with factory
+ js ?= json.value (s)
+ assert ("js /= Void", js /= Void)
+ if attached js as l_js then
+ assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.is_equal ("%"foobar%""))
+ end
+
+ -- JSON representation -> JSON value -> Eiffel value
+ jrep := "%"foobar%""
+ create parser.make_parser (jrep)
+ js := Void
+ js ?= parser.parse
+ assert ("js /= Void", js /= Void)
+ if attached {STRING_32} json.object (js, Void) as l_ucs then
+ assert ("ucs.string.is_equal (%"foobar%")", l_ucs.string.is_equal ("foobar"))
+ end
+ end
+
+ test_json_string_and_uc_string
+ local
+ js: detachable JSON_STRING
+ ucs: detachable STRING_32
+ jrep: STRING
+ parser: JSON_PARSER
+ do
+ create ucs.make_from_string ("foobar")
+ -- Eiffel value -> JSON value -> JSON representation
+ create js.make_json (ucs)
+ assert ("js /= Void", js /= Void)
+ assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.is_equal ("%"foobar%""))
+ -- Eiffel value -> JSON value -> JSON representation with factory
+ js ?= json.value (ucs)
+ assert ("js /= Void", js /= Void)
+ if attached js as l_js then
+ assert ("js.representation.is_equal (%"%"foobar%"%")", l_js.representation.is_equal ("%"foobar%""))
+ end
+
+ -- JSON representation -> JSON value -> Eiffel value
+ jrep := "%"foobar%""
+ create parser.make_parser (jrep)
+ js := Void
+ js ?= parser.parse
+ assert ("js /= Void", js /= Void)
+ ucs := Void
+ ucs ?= json.object (js, Void)
+ if attached ucs as l_ucs then
+ assert ("ucs.string.is_equal (%"foobar%")", l_ucs.string.is_equal ("foobar"))
+ end
+ end
+
+ test_json_string_and_special_characters
+ local
+ js: detachable JSON_STRING
+ s: detachable STRING_8
+ ucs: detachable STRING_32
+ jrep: STRING
+ parser: JSON_PARSER
+ do
+ create s.make_from_string ("foo\bar")
+ create js.make_json (s)
+
+ assert ("js.representation.same_string (%"%"foo\\bar%"%")", js.representation.same_string ("%"foo\\bar%""))
+
+ -- Eiffel value -> JSON value -> JSON representation with factory
+ js ?= json.value (s)
+ assert ("js /= Void", js /= Void)
+ if js /= Void then
+ assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.same_string ("%"foo\\bar%""))
+ end
+
+ -- JSON representation -> JSON value -> Eiffel value
+ jrep := "%"foo\\bar%""
+ create parser.make_parser (jrep)
+ js ?= parser.parse
+ assert ("js /= Void", js /= Void)
+ ucs ?= json.object (js, Void)
+ if ucs /= Void then
+ assert ("ucs.same_string (%"foo\bar%")", ucs.same_string ("foo\bar"))
+ end
+
+ jrep := "%"foo\\bar%""
+ create parser.make_parser (jrep)
+ if attached {JSON_STRING} parser.parse as jstring then
+ assert ("unescaped string %"foo\\bar%" to %"foo\bar%"", jstring.unescaped_string_8.same_string ("foo\bar"))
+ end
+
+ create js.make_json_from_string_32 ({STRING_32}"%/20320/%/22909/")
+ assert ("escaping unicode string32 %"%%/20320/%%/22909/%" %"\u4F60\u597D%"", js.item.same_string ("\u4F60\u597D"))
+
+ jrep := "%"\u4F60\u597D%"" --| Ni hao
+ create parser.make_parser (jrep)
+ if attached {JSON_STRING} parser.parse as jstring then
+ assert ("same unicode string32 %"%%/20320/%%/22909/%"", jstring.unescaped_string_32.same_string ({STRING_32}"%/20320/%/22909/"))
+ end
+ end
+
+ test_json_array
+ local
+ ll: LINKED_LIST [INTEGER_8]
+ ll2: detachable LINKED_LIST [detachable ANY]
+ ja: detachable JSON_ARRAY
+ jn: JSON_NUMBER
+ jrep: STRING
+ parser: JSON_PARSER
+ do
+ -- Eiffel value -> JSON value -> JSON representation
+ create ll.make
+ ll.extend (0)
+ ll.extend (1)
+ ll.extend (1)
+ ll.extend (2)
+ ll.extend (3)
+ ll.extend (5)
+ -- Note: Currently there is no simple way of creating a JSON_ARRAY
+ -- from an LINKED_LIST.
+ create ja.make_array
+ from
+ ll.start
+ until
+ ll.after
+ loop
+ create jn.make_integer (ll.item)
+ ja.add (jn)
+ ll.forth
+ end
+ assert ("ja /= Void", ja /= Void)
+ assert ("ja.representation.is_equal (%"[0,1,1,2,3,5]%")", ja.representation.is_equal ("[0,1,1,2,3,5]"))
+ -- Eiffel value -> JSON value -> JSON representation with factory
+ ja := Void
+ ja ?= json.value (ll)
+ assert ("ja /= Void", ja /= Void)
+ if attached ja as l_ja then
+ assert ("ja.representation.is_equal (%"[0,1,1,2,3,5]%")", l_ja.representation.is_equal ("[0,1,1,2,3,5]"))
+ end
+
+ -- JSON representation -> JSON value -> Eiffel value
+ -- Note: The JSON_FACTORY will return the smallest INTEGER_* object
+ -- that can represent the value of the JSON number, in this case
+ -- it means we will get an LINKED_LIST [ANY] containing the INTEGER_8
+ -- values 0, 1, 1, 2, 3, 5
+ jrep := "[0,1,1,2,3,5]"
+ create parser.make_parser (jrep)
+ ja := Void
+ ja ?= parser.parse
+ assert ("ja /= Void", ja /= Void)
+ ll2 ?= json.object (ja, Void)
+ assert ("ll2 /= Void", ll2 /= Void)
+ --ll.compare_objects
+ --ll2.compare_objects
+ if attached ll2 as l_ll2 then
+ assert ("ll2.is_equal (ll)", l_ll2.is_equal (ll))
+ end
+
+ end
+
+ test_json_object
+ local
+ t, t2: detachable HASH_TABLE [detachable ANY, STRING_GENERAL]
+ i: INTEGER
+ ucs_key, ucs: STRING_32
+ a: ARRAY [INTEGER]
+ jo: detachable JSON_OBJECT
+ jn: JSON_NUMBER
+ js_key, js: JSON_STRING
+ ja: JSON_ARRAY
+ jrep: STRING
+ parser: JSON_PARSER
+ do
+ -- Eiffel value -> JSON value -> JSON representation
+ -- Note: Currently there is now way of creating a JSON_OBJECT from
+ -- a HASH_TABLE, so we do it manually.
+ -- t = {"name": "foobar", "size": 42, "contents", [0, 1, 1, 2, 3, 5]}
+ create jo.make
+ create js_key.make_json ("name")
+ create js.make_json ("foobar")
+ jo.put (js, js_key)
+ create js_key.make_json ("size")
+ create jn.make_integer (42)
+ jo.put (jn, js_key)
+ create js_key.make_json ("contents")
+ create ja.make_array
+ create jn.make_integer (0)
+ ja.add (jn)
+ create jn.make_integer (1)
+ ja.add (jn)
+ create jn.make_integer (1)
+ ja.add (jn)
+ create jn.make_integer (2)
+ ja.add (jn)
+ create jn.make_integer (3)
+ ja.add (jn)
+ create jn.make_integer (5)
+ ja.add (jn)
+ jo.put (ja, js_key)
+ assert ("jo /= Void", jo /= Void)
+ assert ("jo.representation.is_equal (%"{%"name%":%"foobar%",%"size%":42,%"contents%":[0,1,1,2,3,5]}%")", jo.representation.is_equal ("{%"name%":%"foobar%",%"size%":42,%"contents%":[0,1,1,2,3,5]}"))
+ -- Eiffel value -> JSON value -> JSON representation with factory
+ create t.make (3)
+ create ucs_key.make_from_string ("name")
+ create ucs.make_from_string ("foobar")
+ t.put (ucs, ucs_key)
+ create ucs_key.make_from_string ("size")
+ i := 42
+ t.put (i, ucs_key)
+ create ucs_key.make_from_string ("contents")
+ a := <<0, 1, 1, 2, 3, 5>>
+ t.put (a, ucs_key)
+ jo := Void
+ jo ?= json.value (t)
+ assert ("jo /= Void", jo /= Void)
+ if attached jo as l_jo then
+ assert ("jo.representation.is_equal (%"{%"name%":%"foobar%",%"size%":42,%"contents%":[0,1,1,2,3,5]}%")", l_jo.representation.is_equal ("{%"name%":%"foobar%",%"size%":42,%"contents%":[0,1,1,2,3,5]}"))
+ end
+ -- JSON representation -> JSON value -> Eiffel value -> JSON value -> JSON representation
+ jrep := "{%"name%":%"foobar%",%"size%":42,%"contents%":[0,1,1,2,3,5]}"
+ create parser.make_parser (jrep)
+ jo := Void
+ jo ?= parser.parse
+ assert ("jo /= Void", jo /= Void)
+ t2 ?= json.object (jo, Void)
+ assert ("t2 /= Void", t2 /= Void)
+ jo ?= json.value (t2)
+ assert ("jo /= Void", jo /= Void)
+ if attached jo as l_jo then
+ assert ("jrep.is_equal (jo.representation)", jrep.is_equal (jo.representation))
+ end
+
+ end
+
+ test_json_object_hash_code
+ local
+ ht: HASH_TABLE [ANY, JSON_VALUE]
+ jo: JSON_OBJECT
+ do
+ create ht.make (1)
+ create jo.make
+ ht.force ("", jo)
+ assert ("ht.has_key (jo)", ht.has_key (jo))
+ end
+
+ test_json_failed_json_conversion
+ -- Test converting an Eiffel object to JSON that is based on a class
+ -- for which no JSON converter has been registered.
+ local
+ gv: OPERATING_ENVIRONMENT
+ jv: detachable JSON_VALUE
+ exception: BOOLEAN
+ do
+ if not exception then
+ create gv
+ jv := json.value (gv)
+ else
+ assert ("exceptions.is_developer_exception", json.is_developer_exception)
+-- assert ("exceptions.is_developer_exception_of_name", json.is_developer_exception_of_name ("eJSON exception: Failed to convert Eiffel object to a JSON_VALUE: OPERATING_ENVIRONMENT"))
+ end
+ rescue
+ exception := True
+ retry
+ end
+
+ test_json_failed_eiffel_conversion
+ -- Test converting from a JSON value to an Eiffel object based on a
+ -- class for which no JSON converter has been registered.
+ local
+ gv : detachable OPERATING_ENVIRONMENT
+ jo: JSON_OBJECT
+ exception: BOOLEAN
+ do
+ if not exception then
+ create jo.make
+ gv ?= json.object (jo, "OPERATING_ENVIRONMENT")
+ else
+ assert ("exceptions.is_developer_exception", json.is_developer_exception)
+-- assert ("exceptions.is_developer_exception_of_name", json.is_developer_exception_of_name ("eJSON exception: Failed to convert JSON_VALUE to an Eiffel object: JSON_OBJECT -> OPERATING_ENVIRONMENT"))
+
+ end
+ rescue
+ exception := True
+ retry
+ end
+
+end -- class TEST_JSON_CORE
diff --git a/test/autotest/test_suite/test_json_suite.e b/test/autotest/test_suite/test_json_suite.e
index 812fb391..30849c92 100644
--- a/test/autotest/test_suite/test_json_suite.e
+++ b/test/autotest/test_suite/test_json_suite.e
@@ -1,514 +1,514 @@
-note
- description: "[
- Eiffel tests that can be executed by testing tool.
- ]"
- author: "EiffelStudio test wizard"
- date: "$Date$"
- revision: "$Revision$"
- testing: "type/manual"
-
-class
- TEST_JSON_SUITE
-
-inherit
- EQA_TEST_SET
- redefine
- on_prepare
- end
-
-feature {NONE} -- Events
-
- on_prepare
- --
- do
- create file_reader
- end
-
-feature -- Tests Pass
-
- test_json_pass1
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("pass1.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("pass1.json",parse_json.is_parsed = True)
- end
- end
-
- test_json_pass2
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("pass2.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("pass2.json",parse_json.is_parsed = True)
- end
- end
-
- test_json_pass3
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("pass3.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("pass3.json",parse_json.is_parsed = True)
- end
- end
-
-feature -- Tests Failures
- test_json_fail1
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("fail1.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("fail1.json",parse_json.is_parsed = False)
- end
- end
-
- test_json_fail2
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("fail2.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("fail2.json",parse_json.is_parsed = False)
- end
- end
-
- test_json_fail3
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("fail3.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("fail3.json",parse_json.is_parsed = False)
- end
- end
-
- test_json_fail4
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("fail4.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("fail4.json",parse_json.is_parsed = False)
- end
- end
-
- test_json_fail5
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("fail5.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("fail5.json",parse_json.is_parsed = False)
- end
- end
-
-
- test_json_fail6
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("fail6.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("fail6.json",parse_json.is_parsed = False )
- end
- end
-
- test_json_fail7
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("fail7.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("fail7.json",parse_json.is_parsed = False)
- end
- end
-
- test_json_fail8
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("fail8.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("fail8.json",parse_json.is_parsed = False )
- end
- end
-
-
- test_json_fail9
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("fail9.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("fail9.json",parse_json.is_parsed = False)
- end
- end
-
-
- test_json_fail10
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("fail10.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("fail10.json",parse_json.is_parsed = False)
- end
- end
-
- test_json_fail11
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("fail11.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("fail11.json",parse_json.is_parsed = False)
- end
- end
-
- test_json_fail12
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("fail12.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("fail12.json",parse_json.is_parsed = False)
- end
- end
-
- test_json_fail13
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("fail13.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("fail13.json",parse_json.is_parsed = False)
- end
- end
-
- test_json_fail14
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("fail14.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("fail14.json",parse_json.is_parsed = False)
- end
- end
-
- test_json_fail15
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("fail15.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("fail15.json",parse_json.is_parsed = False)
- end
- end
-
- test_json_fail16
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("fail16.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("fail16.json",parse_json.is_parsed = False)
- end
- end
-
- test_json_fail17
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("fail17.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("fail17.json",parse_json.is_parsed = False)
- end
- end
-
- test_json_fail18
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("fail18.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("fail18.json",parse_json.is_parsed = True)
- end
- end
-
- test_json_fail19
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("fail19.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("fail19.json",parse_json.is_parsed = False)
- end
- end
-
- test_json_fail20
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("fail20.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("fail20.json",parse_json.is_parsed = False)
- end
- end
-
- test_json_fail21
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("fail21.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("fail21.json",parse_json.is_parsed = False)
- end
- end
-
-
- test_json_fail22
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("fail22.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("fail22.json",parse_json.is_parsed = False)
- end
- end
-
- test_json_fail23
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("fail23.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("fail23.json",parse_json.is_parsed = False)
- end
- end
-
- test_json_fail24
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("fail24.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("fail24.json",parse_json.is_parsed = False)
- end
- end
-
- test_json_fail25
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("fail25.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("fail25.json",parse_json.is_parsed = False)
- end
- end
-
-
- test_json_fail26
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("fail26.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("fail26.json",parse_json.is_parsed = False)
- end
- end
-
-
- test_json_fail27
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("fail27.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("fail27.json",parse_json.is_parsed = False)
- end
- end
-
-
- test_json_fail28
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("fail28.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("fail28.json",parse_json.is_parsed = False)
- end
- end
-
-
- test_json_fail29
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("fail29.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("fail29.json",parse_json.is_parsed = False )
- end
- end
-
-
- test_json_fail30
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("fail30.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("fail30.json",parse_json.is_parsed = False)
- end
- end
-
- test_json_fail31
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("fail31.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("fail31.json",parse_json.is_parsed = False)
- end
- end
-
- test_json_fail32
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("fail32.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("fail32.json",parse_json.is_parsed = False)
- end
- end
-
- test_json_fail33
- --
- local
- parse_json: like new_json_parser
- do
- if attached json_file_from ("fail33.json") as json_file then
- parse_json := new_json_parser (json_file)
- json_value := parse_json.parse_json
- assert ("fail33.json",parse_json.is_parsed = False)
- end
- end
-
-feature -- JSON_FROM_FILE
-
- file_reader: JSON_FILE_READER
-
- json_value: detachable JSON_VALUE
-
- json_file_from (fn: STRING): detachable STRING
- do
- Result := file_reader.read_json_from (test_dir + fn)
- assert ("File contains json data", Result /= Void)
- end
-
- new_json_parser (a_string: STRING): JSON_PARSER
- do
- create Result.make_parser (a_string)
- end
-
- test_dir: STRING
- local
- i: INTEGER
- do
- Result := (create {EXECUTION_ENVIRONMENT}).current_working_directory
- Result.append_character ((create {OPERATING_ENVIRONMENT}).directory_separator)
- -- The should looks like
- -- ..json\test\autotest\test_suite\EIFGENs\test_suite\Testing\execution\TEST_JSON_SUITE.test_json_fail1\..\..\..\..\..\fail1.json
- from
- i := 5
- until
- i = 0
- loop
- Result.append_character ('.')
- Result.append_character ('.')
- Result.append_character ((create {OPERATING_ENVIRONMENT}).directory_separator)
- i := i - 1
- end
--- Result := "/home/jvelilla/work/project/Eiffel/ejson_dev/trunk/test/autotest/test_suite/"
- end
-
-invariant
- file_reader /= Void
-
-end
-
-
+note
+ description: "[
+ Eiffel tests that can be executed by testing tool.
+ ]"
+ author: "EiffelStudio test wizard"
+ date: "$Date$"
+ revision: "$Revision$"
+ testing: "type/manual"
+
+class
+ TEST_JSON_SUITE
+
+inherit
+ EQA_TEST_SET
+ redefine
+ on_prepare
+ end
+
+feature {NONE} -- Events
+
+ on_prepare
+ --
+ do
+ create file_reader
+ end
+
+feature -- Tests Pass
+
+ test_json_pass1
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("pass1.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("pass1.json",parse_json.is_parsed = True)
+ end
+ end
+
+ test_json_pass2
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("pass2.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("pass2.json",parse_json.is_parsed = True)
+ end
+ end
+
+ test_json_pass3
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("pass3.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("pass3.json",parse_json.is_parsed = True)
+ end
+ end
+
+feature -- Tests Failures
+ test_json_fail1
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("fail1.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("fail1.json",parse_json.is_parsed = False)
+ end
+ end
+
+ test_json_fail2
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("fail2.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("fail2.json",parse_json.is_parsed = False)
+ end
+ end
+
+ test_json_fail3
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("fail3.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("fail3.json",parse_json.is_parsed = False)
+ end
+ end
+
+ test_json_fail4
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("fail4.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("fail4.json",parse_json.is_parsed = False)
+ end
+ end
+
+ test_json_fail5
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("fail5.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("fail5.json",parse_json.is_parsed = False)
+ end
+ end
+
+
+ test_json_fail6
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("fail6.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("fail6.json",parse_json.is_parsed = False )
+ end
+ end
+
+ test_json_fail7
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("fail7.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("fail7.json",parse_json.is_parsed = False)
+ end
+ end
+
+ test_json_fail8
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("fail8.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("fail8.json",parse_json.is_parsed = False )
+ end
+ end
+
+
+ test_json_fail9
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("fail9.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("fail9.json",parse_json.is_parsed = False)
+ end
+ end
+
+
+ test_json_fail10
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("fail10.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("fail10.json",parse_json.is_parsed = False)
+ end
+ end
+
+ test_json_fail11
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("fail11.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("fail11.json",parse_json.is_parsed = False)
+ end
+ end
+
+ test_json_fail12
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("fail12.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("fail12.json",parse_json.is_parsed = False)
+ end
+ end
+
+ test_json_fail13
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("fail13.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("fail13.json",parse_json.is_parsed = False)
+ end
+ end
+
+ test_json_fail14
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("fail14.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("fail14.json",parse_json.is_parsed = False)
+ end
+ end
+
+ test_json_fail15
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("fail15.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("fail15.json",parse_json.is_parsed = False)
+ end
+ end
+
+ test_json_fail16
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("fail16.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("fail16.json",parse_json.is_parsed = False)
+ end
+ end
+
+ test_json_fail17
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("fail17.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("fail17.json",parse_json.is_parsed = False)
+ end
+ end
+
+ test_json_fail18
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("fail18.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("fail18.json",parse_json.is_parsed = True)
+ end
+ end
+
+ test_json_fail19
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("fail19.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("fail19.json",parse_json.is_parsed = False)
+ end
+ end
+
+ test_json_fail20
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("fail20.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("fail20.json",parse_json.is_parsed = False)
+ end
+ end
+
+ test_json_fail21
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("fail21.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("fail21.json",parse_json.is_parsed = False)
+ end
+ end
+
+
+ test_json_fail22
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("fail22.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("fail22.json",parse_json.is_parsed = False)
+ end
+ end
+
+ test_json_fail23
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("fail23.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("fail23.json",parse_json.is_parsed = False)
+ end
+ end
+
+ test_json_fail24
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("fail24.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("fail24.json",parse_json.is_parsed = False)
+ end
+ end
+
+ test_json_fail25
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("fail25.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("fail25.json",parse_json.is_parsed = False)
+ end
+ end
+
+
+ test_json_fail26
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("fail26.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("fail26.json",parse_json.is_parsed = False)
+ end
+ end
+
+
+ test_json_fail27
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("fail27.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("fail27.json",parse_json.is_parsed = False)
+ end
+ end
+
+
+ test_json_fail28
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("fail28.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("fail28.json",parse_json.is_parsed = False)
+ end
+ end
+
+
+ test_json_fail29
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("fail29.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("fail29.json",parse_json.is_parsed = False )
+ end
+ end
+
+
+ test_json_fail30
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("fail30.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("fail30.json",parse_json.is_parsed = False)
+ end
+ end
+
+ test_json_fail31
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("fail31.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("fail31.json",parse_json.is_parsed = False)
+ end
+ end
+
+ test_json_fail32
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("fail32.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("fail32.json",parse_json.is_parsed = False)
+ end
+ end
+
+ test_json_fail33
+ --
+ local
+ parse_json: like new_json_parser
+ do
+ if attached json_file_from ("fail33.json") as json_file then
+ parse_json := new_json_parser (json_file)
+ json_value := parse_json.parse_json
+ assert ("fail33.json",parse_json.is_parsed = False)
+ end
+ end
+
+feature -- JSON_FROM_FILE
+
+ file_reader: JSON_FILE_READER
+
+ json_value: detachable JSON_VALUE
+
+ json_file_from (fn: STRING): detachable STRING
+ do
+ Result := file_reader.read_json_from (test_dir + fn)
+ assert ("File contains json data", Result /= Void)
+ end
+
+ new_json_parser (a_string: STRING): JSON_PARSER
+ do
+ create Result.make_parser (a_string)
+ end
+
+ test_dir: STRING
+ local
+ i: INTEGER
+ do
+ Result := (create {EXECUTION_ENVIRONMENT}).current_working_directory
+ Result.append_character ((create {OPERATING_ENVIRONMENT}).directory_separator)
+ -- The should looks like
+ -- ..json\test\autotest\test_suite\EIFGENs\test_suite\Testing\execution\TEST_JSON_SUITE.test_json_fail1\..\..\..\..\..\fail1.json
+ from
+ i := 5
+ until
+ i = 0
+ loop
+ Result.append_character ('.')
+ Result.append_character ('.')
+ Result.append_character ((create {OPERATING_ENVIRONMENT}).directory_separator)
+ i := i - 1
+ end
+-- Result := "/home/jvelilla/work/project/Eiffel/ejson_dev/trunk/test/autotest/test_suite/"
+ end
+
+invariant
+ file_reader /= Void
+
+end
+
+
diff --git a/test/autotest/test_suite/test_suite-safe.ecf b/test/autotest/test_suite/test_suite-safe.ecf
index 00552058..541c8d9e 100644
--- a/test/autotest/test_suite/test_suite-safe.ecf
+++ b/test/autotest/test_suite/test_suite-safe.ecf
@@ -1,18 +1,18 @@
-
-
-
-
-
- /EIFGENs$
- /CVS$
- /.svn$
-
-
-
-
-
-
-
-
+
+
+
+
+
+ /EIFGENs$
+ /CVS$
+ /.svn$
+
+
+
+
+
+
+
+