Replaced git submodule by subtree merged in contrib/library/text/parser/json
This commit is contained in:
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -1,6 +1,3 @@
|
||||
[submodule "contrib/library/text/parser/json"]
|
||||
path = contrib/library/text/parser/json
|
||||
url = https://github.com/Eiffel-World/json.git
|
||||
[submodule "contrib/ise_library/cURL"]
|
||||
path = contrib/ise_library/cURL
|
||||
url = https://github.com/EiffelSoftware/mirror-Eiffel-cURL.git
|
||||
|
||||
Submodule contrib/library/text/parser/json deleted from c873d62efa
26
contrib/library/text/parser/json/History.txt
Normal file
26
contrib/library/text/parser/json/History.txt
Normal file
@@ -0,0 +1,26 @@
|
||||
History file for EJSON
|
||||
======================
|
||||
|
||||
team: ""
|
||||
date: "2011-07-06"
|
||||
revision: "0.3.0"
|
||||
|
||||
|
||||
+++++++++++++++++++++Important Changes since 0.2.0 version++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
*Updated skip_white_spaces, now check %U and %T codes
|
||||
|
||||
*Undo changes to is_a_valid_number, because it's doesn't follow the
|
||||
JSON spec. Tests : fail13.json, fail29.json and fail30.json are valid
|
||||
with this implementation, so we go back to the previous
|
||||
implementation.
|
||||
|
||||
*Added autotest test suite
|
||||
|
||||
*Added getest based test program
|
||||
|
||||
*Updated Eiffel configuration file, updated to the new clusters
|
||||
|
||||
*Added converters and factory classes
|
||||
|
||||
*Added new top level directories; library, test, build and example
|
||||
20
contrib/library/text/parser/json/License.txt
Normal file
20
contrib/library/text/parser/json/License.txt
Normal file
@@ -0,0 +1,20 @@
|
||||
Copyright (c) 2010 Javier Velilla and others, http://ejson.origo.ethz.ch
|
||||
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
97
contrib/library/text/parser/json/Readme.txt
Normal file
97
contrib/library/text/parser/json/Readme.txt
Normal file
@@ -0,0 +1,97 @@
|
||||
Readme file for eJSON
|
||||
=====================
|
||||
|
||||
team: "Javier Velilla,Jocelyn Fiat, Paul Cohen"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
1. Introduction
|
||||
---------------
|
||||
|
||||
eJSON stands for Eiffel JSON library and is a small Eiffel library for dealing
|
||||
with the JSON format. The objective of the library is to provide two basic
|
||||
features Eiffel2JSON and JSON2Eiffel.
|
||||
|
||||
2. Legal stuff
|
||||
--------------
|
||||
|
||||
eJSON is copyrighted by the author Javier Velilla and others. It is licensed
|
||||
under the MIT License. See the file license.txt in the same directory as this
|
||||
readme file.
|
||||
|
||||
3. Versioning scheme
|
||||
--------------------
|
||||
|
||||
eJSON version numbers has the form:
|
||||
|
||||
«major number».«minor number».«patch level»
|
||||
|
||||
eJSON will retain the major number 0 as long as it has beta status. A change in
|
||||
major number indicates that a release is not backward compatible. A change in
|
||||
minor number indicates that a release is backward compatible (within that major
|
||||
number) but that new useful features may have been added. A change in patch
|
||||
level simply indicates that the release contains bug fixes for the previous
|
||||
release. Note that as long as eJSON is in beta status (0.Y.Z) backward
|
||||
compatibility is not guranteed for changes in minor numbers!
|
||||
|
||||
4. Documentation
|
||||
---------------
|
||||
|
||||
Currently the only documentation on eJSON is available at:
|
||||
|
||||
http://ejson.origo.ethz.ch/wiki/user_guide
|
||||
|
||||
5. Requirements and installation
|
||||
--------------------------------
|
||||
|
||||
EJSON requires that you have:
|
||||
|
||||
1. Gobo 3.9 installed or later
|
||||
2. One of the following compiler combinations installed:
|
||||
* ISE Eiffel 6.5 or later.
|
||||
* gec [try to test]
|
||||
* tecomp [try to test]
|
||||
|
||||
eJSON probably works fine with other versions of the above compilers.
|
||||
There are no known platform dependencies (Windows, Linux).
|
||||
|
||||
To install eJSON simply extract the ejson-X.Y.Z.zip file to some appropriate
|
||||
place on your hard disk. There are no requirements on environment variables or
|
||||
registry variables.
|
||||
|
||||
To verify that everything works you should compile the example programs and/or
|
||||
the test program.
|
||||
|
||||
6. Contents of eJSON
|
||||
--------------------
|
||||
|
||||
All directory names below are relative to the root directory of your ejson
|
||||
installation.
|
||||
|
||||
Directory Description
|
||||
--------- -----------
|
||||
doc Contains the eJSON.pdf documentation file.
|
||||
examples Contains the two example programs.
|
||||
ejson Contains the actual eJSON library classes.
|
||||
test Contains a test program for eJSON.
|
||||
|
||||
7. Contacting the Team
|
||||
----------------------
|
||||
|
||||
Contact the team:
|
||||
|
||||
Javier Velilla «javier.hector@gmail.com»
|
||||
Paul Cohen «paco@seibostudios.se»
|
||||
Jocelyn Fiat «jfiat@eiffel.com»
|
||||
|
||||
8. Releases
|
||||
-----------
|
||||
|
||||
For more information on what was changed in each release look in the file
|
||||
history.txt.
|
||||
|
||||
Version Date Description
|
||||
------- ---- -----------
|
||||
0.3.0 2011-07-06 JSON Factory Converters
|
||||
0.2.0 2010-02-07 Adapted to EiffelStudio 6.4 or later, supports void-safety
|
||||
0.1.0 2010-02-07 First release, Adapted to SmartEiffel 1.2r7 and EiffelStudio 6.2 or previous
|
||||
@@ -0,0 +1,38 @@
|
||||
note
|
||||
description: "Objects that ..."
|
||||
author: ""
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
JSON_FILE_READER
|
||||
|
||||
feature -- Access
|
||||
|
||||
read_json_from (a_path: STRING): detachable STRING
|
||||
local
|
||||
l_file: PLAIN_TEXT_FILE
|
||||
template_content: STRING
|
||||
l_last_string: detachable STRING
|
||||
do
|
||||
create l_file.make (a_path)
|
||||
-- We perform several checks until we make a real attempt to open the file.
|
||||
if not l_file.exists then
|
||||
print ("error: '" + a_path + "' does not exist%N")
|
||||
else
|
||||
if not l_file.is_readable then
|
||||
print ("error: '" + a_path + "' is not readable.%N")
|
||||
else
|
||||
l_file.open_read
|
||||
create template_content.make_empty
|
||||
l_file.read_stream (l_file.count)
|
||||
l_last_string := l_file.last_string
|
||||
check l_last_string /= Void end -- implied by postcondition of `l_file.read_stream'
|
||||
template_content.append (l_last_string.string)
|
||||
Result := template_content
|
||||
l_file.close
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,59 @@
|
||||
note
|
||||
description:
|
||||
|
||||
"JSON Visitor"
|
||||
|
||||
pattern: "Visitor"
|
||||
author: "Javier Velilla"
|
||||
license:"MIT (see http://www.opensource.org/licenses/mit-license.php)"
|
||||
date: "2008/08/24"
|
||||
revision: "Revision 0.1"
|
||||
|
||||
deferred class
|
||||
JSON_VISITOR
|
||||
|
||||
feature -- Visitor Pattern
|
||||
|
||||
visit_json_array (a_json_array: JSON_ARRAY)
|
||||
-- Visit `a_json_array'.
|
||||
require
|
||||
a_json_array_not_void: a_json_array /= Void
|
||||
deferred
|
||||
end
|
||||
|
||||
visit_json_boolean (a_json_boolean: JSON_BOOLEAN)
|
||||
-- Visit `a_json_boolean'.
|
||||
require
|
||||
a_json_boolean_not_void: a_json_boolean /= Void
|
||||
deferred
|
||||
end
|
||||
|
||||
visit_json_null (a_json_null: JSON_NULL)
|
||||
-- Visit `a_json_null'.
|
||||
require
|
||||
a_json_null_not_void: a_json_null /= Void
|
||||
deferred
|
||||
end
|
||||
|
||||
visit_json_number (a_json_number: JSON_NUMBER)
|
||||
-- Visit `a_json_number'.
|
||||
require
|
||||
a_json_number_not_void: a_json_number /= Void
|
||||
deferred
|
||||
end
|
||||
|
||||
visit_json_object (a_json_object: JSON_OBJECT)
|
||||
-- Visit `a_json_object'.
|
||||
require
|
||||
a_json_object_not_void: a_json_object /= Void
|
||||
deferred
|
||||
end
|
||||
|
||||
visit_json_string (a_json_string: JSON_STRING)
|
||||
-- Visit `a_json_string'.
|
||||
require
|
||||
a_json_string_not_void: a_json_string /= Void
|
||||
deferred
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +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
|
||||
@@ -0,0 +1,81 @@
|
||||
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
|
||||
create js.make_json (c.key.out)
|
||||
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
|
||||
@@ -0,0 +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
|
||||
@@ -0,0 +1,32 @@
|
||||
note
|
||||
description: "[
|
||||
Shared factory class for creating JSON objects. Maps JSON
|
||||
objects to Gobo DS_HASH_TABLEs and JSON arrays to Gobo
|
||||
DS_LINKED_LISTs. Use non-conforming inheritance from this
|
||||
class to ensure that your classes share the same
|
||||
JSON_FACTORY instance.
|
||||
]"
|
||||
author: "Paul Cohen"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
file: "$HeadURL: $"
|
||||
|
||||
class SHARED_GOBO_EJSON
|
||||
|
||||
feature
|
||||
|
||||
json: EJSON
|
||||
-- A shared EJSON instance with default converters for
|
||||
-- DS_LINKED_LIST [ANY] and DS_HASH_TABLE [ANY, HASHABLE]
|
||||
local
|
||||
jllc: JSON_DS_LINKED_LIST_CONVERTER
|
||||
jhtc: JSON_DS_HASH_TABLE_CONVERTER
|
||||
once
|
||||
create Result
|
||||
create jllc.make
|
||||
Result.add_converter (jllc)
|
||||
create jhtc.make
|
||||
Result.add_converter (jhtc)
|
||||
end
|
||||
|
||||
end -- class SHARED_GOBO_EJSON
|
||||
28
contrib/library/text/parser/json/library/json-safe.ecf
Normal file
28
contrib/library/text/parser/json/library/json-safe.ecf
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="json" uuid="4E21C3BD-7951-4C6E-A673-431E762D7414" library_target="json">
|
||||
<target name="json">
|
||||
<root all_classes="true"/>
|
||||
<file_rule>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/CVS$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option trace="false" profile="false" debug="false" warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="standard" namespace="EJSON.Library">
|
||||
<assertions/>
|
||||
<warning name="export_class_missing" enabled="false"/>
|
||||
<warning name="old_verbatim_strings" enabled="false"/>
|
||||
<warning name="syntax" enabled="false"/>
|
||||
<warning name="vjrv" enabled="false"/>
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf" readonly="true"/>
|
||||
<cluster name="json" location=".\" recursive="true">
|
||||
<file_rule>
|
||||
<exclude>^/gobo$</exclude>
|
||||
<exclude>^/kernel$</exclude>
|
||||
<exclude>^/extras$</exclude>
|
||||
</file_rule>
|
||||
<cluster name="kernel" location=".\kernel\" recursive="true"/>
|
||||
<cluster name="extras" location=".\extras\" recursive="true"/>
|
||||
</cluster>
|
||||
</target>
|
||||
</system>
|
||||
28
contrib/library/text/parser/json/library/json.ecf
Normal file
28
contrib/library/text/parser/json/library/json.ecf
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="json" uuid="4E21C3BD-7951-4C6E-A673-431E762D7414" library_target="json">
|
||||
<target name="json">
|
||||
<root all_classes="true"/>
|
||||
<file_rule>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/CVS$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option trace="false" profile="false" debug="false" warning="true" full_class_checking="true" void_safety="none" syntax="standard" namespace="EJSON.Library">
|
||||
<assertions/>
|
||||
<warning name="export_class_missing" enabled="false"/>
|
||||
<warning name="old_verbatim_strings" enabled="false"/>
|
||||
<warning name="syntax" enabled="false"/>
|
||||
<warning name="vjrv" enabled="false"/>
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf" readonly="true"/>
|
||||
<cluster name="json" location=".\" recursive="true">
|
||||
<file_rule>
|
||||
<exclude>^/gobo$</exclude>
|
||||
<exclude>^/kernel$</exclude>
|
||||
<exclude>^/extras$</exclude>
|
||||
</file_rule>
|
||||
<cluster name="kernel" location=".\kernel\" recursive="true"/>
|
||||
<cluster name="extras" location=".\extras\" recursive="true"/>
|
||||
</cluster>
|
||||
</target>
|
||||
</system>
|
||||
1
contrib/library/text/parser/json/library/json.rc
Normal file
1
contrib/library/text/parser/json/library/json.rc
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="json_gobo" uuid="437195AB-8B3C-4238-8998-A932A1423449" library_target="json_gobo">
|
||||
<target name="json_gobo">
|
||||
<root all_classes="true"/>
|
||||
<file_rule>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/CVS$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option trace="false" profile="false" debug="false" warning="true" full_class_checking="true" void_safety="none" syntax="standard" namespace="EJSON.Library">
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf" readonly="true"/>
|
||||
<library name="json" location="json.ecf" readonly="true"/>
|
||||
<library name="gobo_structure" location="$ISE_LIBRARY\library\gobo\gobo_structure.ecf"/>
|
||||
<cluster name="json_gobo" location=".\gobo" recursive="true" />
|
||||
</target>
|
||||
</system>
|
||||
@@ -0,0 +1,36 @@
|
||||
note
|
||||
description: "A JSON converter"
|
||||
author: "Paul Cohen"
|
||||
date: "$Date: $"
|
||||
revision: "$Revision: $"
|
||||
file: "$HeadURL: $"
|
||||
|
||||
deferred class JSON_CONVERTER
|
||||
|
||||
inherit
|
||||
SHARED_EJSON
|
||||
|
||||
feature -- Access
|
||||
|
||||
object: ANY
|
||||
-- Eiffel object
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Conversion
|
||||
|
||||
from_json (j: attached like to_json): detachable like object
|
||||
-- Convert from JSON value.
|
||||
-- Returns Void if unable to convert
|
||||
deferred
|
||||
end
|
||||
|
||||
to_json (o: like object): detachable JSON_VALUE
|
||||
-- Convert to JSON value
|
||||
deferred
|
||||
end
|
||||
|
||||
invariant
|
||||
has_eiffel_object: object /= Void -- An empty object must be created at creation time!
|
||||
|
||||
end
|
||||
@@ -0,0 +1,88 @@
|
||||
note
|
||||
description: "A JSON converter for HASH_TABLE [ANY, HASHABLE]"
|
||||
author: "Paul Cohen"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
file: "$HeadURL: $"
|
||||
|
||||
class JSON_HASH_TABLE_CONVERTER
|
||||
|
||||
inherit
|
||||
JSON_CONVERTER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
do
|
||||
create object.make (0)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
object: HASH_TABLE [ANY, HASHABLE]
|
||||
|
||||
feature -- Conversion
|
||||
|
||||
from_json (j: attached like to_json): like object
|
||||
local
|
||||
keys: ARRAY [JSON_STRING]
|
||||
i: INTEGER
|
||||
h: detachable HASHABLE
|
||||
jv: detachable JSON_VALUE
|
||||
a: detachable 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
|
||||
jv := j.item (keys [i])
|
||||
if jv /= Void then
|
||||
a := json.object (jv, Void)
|
||||
if a /= Void then
|
||||
Result.put (a, h)
|
||||
else
|
||||
check a_attached: a /= Void end
|
||||
end
|
||||
else
|
||||
check j_has_item: False end
|
||||
end
|
||||
i := i + 1
|
||||
end
|
||||
end
|
||||
|
||||
to_json (o: like object): detachable JSON_OBJECT
|
||||
local
|
||||
c: HASH_TABLE_ITERATION_CURSOR [ANY, HASHABLE]
|
||||
js: JSON_STRING
|
||||
jv: detachable JSON_VALUE
|
||||
failed: BOOLEAN
|
||||
do
|
||||
create Result.make
|
||||
from
|
||||
c := o.new_cursor
|
||||
until
|
||||
c.after
|
||||
loop
|
||||
create js.make_json (c.key.out)
|
||||
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_HASH_TABLE_CONVERTER
|
||||
@@ -0,0 +1,63 @@
|
||||
note
|
||||
description: "A JSON converter for LINKED_LIST [ANY]"
|
||||
author: "Paul Cohen"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
file: "$HeadURL: $"
|
||||
|
||||
class JSON_LINKED_LIST_CONVERTER
|
||||
|
||||
inherit
|
||||
JSON_CONVERTER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
do
|
||||
create object.make
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
object: LINKED_LIST [detachable ANY]
|
||||
|
||||
feature -- Conversion
|
||||
|
||||
from_json (j: like to_json): detachable like object
|
||||
local
|
||||
i: INTEGER
|
||||
do
|
||||
create Result.make
|
||||
from
|
||||
i := 1
|
||||
until
|
||||
i > j.count
|
||||
loop
|
||||
Result.extend (json.object (j [i], Void))
|
||||
i := i + 1
|
||||
end
|
||||
end
|
||||
|
||||
to_json (o: like object): JSON_ARRAY
|
||||
local
|
||||
c: ITERATION_CURSOR [detachable ANY]
|
||||
do
|
||||
create Result.make_array
|
||||
from
|
||||
c := o.new_cursor
|
||||
until
|
||||
c.after
|
||||
loop
|
||||
if attached json.value (c.item) as v then
|
||||
Result.add (v)
|
||||
else
|
||||
check attached_value: False end
|
||||
end
|
||||
c.forth
|
||||
end
|
||||
end
|
||||
|
||||
end -- class JSON_LINKED_LIST_CONVERTER
|
||||
268
contrib/library/text/parser/json/library/kernel/ejson.e
Normal file
268
contrib/library/text/parser/json/library/kernel/ejson.e
Normal file
@@ -0,0 +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 (s32.as_string_8) -- FIXME: need correct convertion/encoding here ...
|
||||
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 := ": " + an_object.generator
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation (JSON parser)
|
||||
|
||||
json_parser: JSON_PARSER
|
||||
once
|
||||
create Result.make_parser ("")
|
||||
end
|
||||
|
||||
end -- class EJSON
|
||||
141
contrib/library/text/parser/json/library/kernel/json_array.e
Normal file
141
contrib/library/text/parser/json/library/kernel/json_array.e
Normal file
@@ -0,0 +1,141 @@
|
||||
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
|
||||
|
||||
DEBUG_OUTPUT
|
||||
|
||||
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 -- 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
|
||||
|
||||
add (value: JSON_VALUE)
|
||||
require
|
||||
value_not_null: value /= void
|
||||
do
|
||||
values.extend (value)
|
||||
ensure
|
||||
has_new_value: old values.count + 1 = values.count and
|
||||
values.has (value)
|
||||
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
|
||||
do
|
||||
Result := values
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
debug_output: STRING
|
||||
-- String that should be displayed in debugger to represent `Current'.
|
||||
do
|
||||
Result := count.out
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
values: ARRAYED_LIST [JSON_VALUE]
|
||||
-- Value container
|
||||
|
||||
invariant
|
||||
value_not_void: values /= Void
|
||||
|
||||
end
|
||||
@@ -0,0 +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
|
||||
47
contrib/library/text/parser/json/library/kernel/json_null.e
Normal file
47
contrib/library/text/parser/json/library/kernel/json_null.e
Normal file
@@ -0,0 +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
|
||||
@@ -0,0 +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
|
||||
160
contrib/library/text/parser/json/library/kernel/json_object.e
Normal file
160
contrib/library/text/parser/json/library/kernel/json_object.e
Normal file
@@ -0,0 +1,160 @@
|
||||
note
|
||||
|
||||
description: "[
|
||||
An JSON_OBJECT represent an object in JSON.
|
||||
An object is an unordered set of name/value pairs
|
||||
|
||||
Examples:
|
||||
|
||||
object
|
||||
{}
|
||||
{"key","value"}
|
||||
|
||||
]"
|
||||
author: "Javier Velilla"
|
||||
date: "2008/08/24"
|
||||
revision: "Revision 0.1"
|
||||
license:"MIT (see http://www.opensource.org/licenses/mit-license.php)"
|
||||
|
||||
class
|
||||
JSON_OBJECT
|
||||
|
||||
inherit
|
||||
JSON_VALUE
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
-- Initialize
|
||||
do
|
||||
create object.make (10)
|
||||
end
|
||||
|
||||
feature -- Change Element
|
||||
|
||||
put (value: detachable JSON_VALUE; key: JSON_STRING)
|
||||
-- Assuming there is no item of key `key',
|
||||
-- insert `value' with `key'.
|
||||
require
|
||||
key_not_present: not has_key (key)
|
||||
local
|
||||
l_value: detachable JSON_VALUE
|
||||
do
|
||||
l_value := value
|
||||
if l_value = Void then
|
||||
create {JSON_NULL} l_value
|
||||
end
|
||||
object.extend (l_value, key)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
has_key (key: JSON_STRING): BOOLEAN
|
||||
-- has the JSON_OBJECT contains a specific key 'key'.
|
||||
do
|
||||
Result := object.has (key)
|
||||
end
|
||||
|
||||
has_item (value: JSON_VALUE): BOOLEAN
|
||||
-- has the JSON_OBJECT contain a specfic item 'value'
|
||||
do
|
||||
Result := object.has_item (value)
|
||||
end
|
||||
|
||||
item (key: JSON_STRING): detachable JSON_VALUE
|
||||
-- the json_value associated with a key.
|
||||
do
|
||||
Result := object.item (key)
|
||||
end
|
||||
|
||||
current_keys: ARRAY [JSON_STRING]
|
||||
-- array containing actually used keys
|
||||
do
|
||||
Result := object.current_keys
|
||||
end
|
||||
|
||||
representation: STRING
|
||||
local
|
||||
t: HASH_TABLE [JSON_VALUE, JSON_STRING]
|
||||
do
|
||||
Result := "{"
|
||||
from
|
||||
t := map_representation
|
||||
t.start
|
||||
until
|
||||
t.after
|
||||
loop
|
||||
Result.append (t.key_for_iteration.representation)
|
||||
Result.append (":")
|
||||
Result.append (t.item_for_iteration.representation)
|
||||
t.forth
|
||||
if not t.after then
|
||||
Result.append_character (',')
|
||||
end
|
||||
end
|
||||
Result.append_character ('}')
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
is_empty: BOOLEAN
|
||||
-- Is empty object?
|
||||
do
|
||||
Result := object.is_empty
|
||||
end
|
||||
|
||||
feature -- Visitor pattern
|
||||
|
||||
accept (a_visitor: JSON_VISITOR)
|
||||
-- Accept `a_visitor'.
|
||||
-- (Call `visit_json_object' procedure on `a_visitor'.)
|
||||
do
|
||||
a_visitor.visit_json_object (Current)
|
||||
end
|
||||
|
||||
feature -- Conversion
|
||||
|
||||
map_representation: HASH_TABLE [JSON_VALUE, JSON_STRING]
|
||||
--A representation that maps keys to values
|
||||
do
|
||||
Result := object
|
||||
end
|
||||
|
||||
feature -- Report
|
||||
|
||||
hash_code: INTEGER
|
||||
-- Hash code value
|
||||
do
|
||||
from
|
||||
object.start
|
||||
Result := object.item_for_iteration.hash_code
|
||||
until
|
||||
object.off
|
||||
loop
|
||||
Result := ((Result \\ 8388593) |<< 8) + object.item_for_iteration.hash_code
|
||||
object.forth
|
||||
end
|
||||
-- Ensure it is a positive value.
|
||||
Result := Result.hash_code
|
||||
end
|
||||
|
||||
feature -- Status report
|
||||
|
||||
debug_output: STRING
|
||||
-- String that should be displayed in debugger to represent `Current'.
|
||||
do
|
||||
Result := object.count.out
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
object: HASH_TABLE [JSON_VALUE, JSON_STRING]
|
||||
-- Value container
|
||||
|
||||
invariant
|
||||
object_not_null: object /= Void
|
||||
|
||||
end
|
||||
329
contrib/library/text/parser/json/library/kernel/json_string.e
Normal file
329
contrib/library/text/parser/json/library/kernel/json_string.e
Normal file
@@ -0,0 +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
|
||||
43
contrib/library/text/parser/json/library/kernel/json_value.e
Normal file
43
contrib/library/text/parser/json/library/kernel/json_value.e
Normal file
@@ -0,0 +1,43 @@
|
||||
note
|
||||
description:"[
|
||||
JSON_VALUE represent a value in JSON.
|
||||
A value can be
|
||||
* a string in double quotes
|
||||
* a number
|
||||
* boolean value(true, false )
|
||||
* null
|
||||
* an object
|
||||
* an array
|
||||
]"
|
||||
author: "Javier Velilla"
|
||||
date: "2008/05/19"
|
||||
revision: "Revision 0.1"
|
||||
license:"MIT (see http://www.opensource.org/licenses/mit-license.php)"
|
||||
|
||||
|
||||
deferred class
|
||||
JSON_VALUE
|
||||
|
||||
inherit
|
||||
HASHABLE
|
||||
|
||||
DEBUG_OUTPUT
|
||||
|
||||
feature -- Access
|
||||
|
||||
representation: STRING
|
||||
-- UTF-8 encoded Unicode string representation of Current
|
||||
deferred
|
||||
end
|
||||
|
||||
feature -- Visitor pattern
|
||||
|
||||
accept (a_visitor: JSON_VISITOR)
|
||||
-- Accept `a_visitor'.
|
||||
-- (Call `visit_*' procedure on `a_visitor'.)
|
||||
require
|
||||
a_visitor_not_void: a_visitor /= Void
|
||||
deferred
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +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
|
||||
@@ -0,0 +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
|
||||
@@ -0,0 +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
|
||||
@@ -0,0 +1,32 @@
|
||||
note
|
||||
description: "[
|
||||
Shared factory class for creating JSON objects. Maps JSON
|
||||
objects to ELKS HASH_TABLEs and JSON arrays to ELKS
|
||||
LINKED_LISTs. Use non-conforming inheritance from this
|
||||
class to ensure that your classes share the same
|
||||
JSON_FACTORY instance.
|
||||
]"
|
||||
author: "Paul Cohen"
|
||||
date: "$Date: $"
|
||||
revision: "$Revision: $"
|
||||
file: "$HeadURL: $"
|
||||
|
||||
class SHARED_EJSON
|
||||
|
||||
feature
|
||||
|
||||
json: EJSON
|
||||
-- A shared EJSON instance with default converters for
|
||||
-- DS_LINKED_LIST [ANY] and DS_HASH_TABLE [ANY, HASHABLE]
|
||||
local
|
||||
jllc: JSON_LINKED_LIST_CONVERTER
|
||||
jhtc: JSON_HASH_TABLE_CONVERTER
|
||||
once
|
||||
create Result
|
||||
create jllc.make
|
||||
Result.add_converter (jllc)
|
||||
create jhtc.make
|
||||
Result.add_converter (jhtc)
|
||||
end
|
||||
|
||||
end -- class SHARED_EJSON
|
||||
@@ -0,0 +1,24 @@
|
||||
note
|
||||
description : "test_suite application root class"
|
||||
date : "$Date$"
|
||||
revision : "$Revision$"
|
||||
|
||||
class
|
||||
APPLICATION
|
||||
|
||||
inherit
|
||||
ARGUMENTS
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
-- Run application.
|
||||
do
|
||||
--| Add your code here
|
||||
print ("Hello Eiffel World!%N")
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,24 @@
|
||||
class AUTHOR
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_name: STRING_32)
|
||||
do
|
||||
set_name (a_name)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
name: STRING_32
|
||||
|
||||
feature -- Status setting
|
||||
|
||||
set_name (a_name: STRING_32)
|
||||
do
|
||||
name := a_name
|
||||
end
|
||||
|
||||
end -- class AUTHOR
|
||||
@@ -0,0 +1,40 @@
|
||||
class BOOK
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_title: STRING_32; an_author: AUTHOR; an_isbn: STRING_32)
|
||||
do
|
||||
set_title (a_title)
|
||||
set_author (an_author)
|
||||
set_isbn (an_isbn)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
title: STRING_32
|
||||
|
||||
isbn: STRING_32
|
||||
|
||||
author: AUTHOR
|
||||
|
||||
feature -- Status setting
|
||||
|
||||
set_title (a_title: STRING_32)
|
||||
do
|
||||
title := a_title
|
||||
end
|
||||
|
||||
set_author (an_author: AUTHOR)
|
||||
do
|
||||
author := an_author
|
||||
end
|
||||
|
||||
set_isbn (an_isbn: STRING_32)
|
||||
do
|
||||
isbn := an_isbn
|
||||
end
|
||||
|
||||
end -- class BOOK
|
||||
@@ -0,0 +1,80 @@
|
||||
class BOOK_COLLECTION
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_name: STRING_32)
|
||||
do
|
||||
set_name (a_name)
|
||||
create book_index.make (10)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
name: STRING_32
|
||||
|
||||
books: LIST [BOOK]
|
||||
do
|
||||
from
|
||||
create {LINKED_LIST [BOOK]} Result.make
|
||||
book_index.start
|
||||
until
|
||||
book_index.after
|
||||
loop
|
||||
Result.append (book_index.item_for_iteration)
|
||||
book_index.forth
|
||||
end
|
||||
end
|
||||
|
||||
books_by_author (an_author: STRING_32): detachable LIST [BOOK]
|
||||
do
|
||||
if book_index.has (an_author) then
|
||||
Result := book_index @ an_author
|
||||
else
|
||||
create {LINKED_LIST [BOOK]} Result.make
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Status setting
|
||||
|
||||
set_name (a_name: STRING_32)
|
||||
do
|
||||
name := a_name
|
||||
end
|
||||
|
||||
add_book (a_book: BOOK)
|
||||
local
|
||||
l: detachable LIST [BOOK]
|
||||
do
|
||||
if book_index.has (a_book.author.name) then
|
||||
l := book_index.at ( a_book.author.name )
|
||||
else
|
||||
create {LINKED_LIST [BOOK]} l.make
|
||||
book_index.put (l, a_book.author.name)
|
||||
end
|
||||
if attached l as la then
|
||||
la.force (a_book)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
add_books (book_list: like books)
|
||||
|
||||
do
|
||||
from
|
||||
book_list.start
|
||||
until
|
||||
book_list.after
|
||||
loop
|
||||
add_book (book_list.item)
|
||||
book_list.forth
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
book_index: HASH_TABLE [LIST [BOOK], STRING_32]
|
||||
|
||||
end -- class BOOK_COLLECTION
|
||||
@@ -0,0 +1 @@
|
||||
"A JSON payload should be an object or array, not a string."
|
||||
@@ -0,0 +1 @@
|
||||
{"Extra value after close": true} "misplaced quoted value"
|
||||
@@ -0,0 +1 @@
|
||||
{"Illegal expression": 1 + 2}
|
||||
@@ -0,0 +1 @@
|
||||
{"Illegal invocation": alert()}
|
||||
@@ -0,0 +1 @@
|
||||
{"Numbers cannot have leading zeroes": 013}
|
||||
@@ -0,0 +1 @@
|
||||
{"Numbers cannot be hex": 0x14}
|
||||
@@ -0,0 +1 @@
|
||||
["Illegal backslash escape: \x15"]
|
||||
@@ -0,0 +1 @@
|
||||
[\naked]
|
||||
@@ -0,0 +1 @@
|
||||
["Illegal backslash escape: \017"]
|
||||
@@ -0,0 +1 @@
|
||||
[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]
|
||||
@@ -0,0 +1 @@
|
||||
{"Missing colon" null}
|
||||
@@ -0,0 +1 @@
|
||||
["Unclosed array"
|
||||
@@ -0,0 +1 @@
|
||||
{"Double colon":: null}
|
||||
@@ -0,0 +1 @@
|
||||
{"Comma instead of colon", null}
|
||||
@@ -0,0 +1 @@
|
||||
["Colon instead of comma": false]
|
||||
@@ -0,0 +1 @@
|
||||
["Bad value", truth]
|
||||
@@ -0,0 +1 @@
|
||||
['single quote']
|
||||
@@ -0,0 +1 @@
|
||||
[" tab character in string "]
|
||||
@@ -0,0 +1 @@
|
||||
["tab\ character\ in\ string\ "]
|
||||
@@ -0,0 +1,2 @@
|
||||
["line
|
||||
break"]
|
||||
@@ -0,0 +1,2 @@
|
||||
["line\
|
||||
break"]
|
||||
@@ -0,0 +1 @@
|
||||
[0e]
|
||||
@@ -0,0 +1 @@
|
||||
{unquoted_key: "keys must be quoted"}
|
||||
@@ -0,0 +1 @@
|
||||
[0e+]
|
||||
@@ -0,0 +1 @@
|
||||
[0e+-1]
|
||||
@@ -0,0 +1 @@
|
||||
{"Comma instead if closing brace": true,
|
||||
@@ -0,0 +1 @@
|
||||
["mismatch"}
|
||||
@@ -0,0 +1 @@
|
||||
["extra comma",]
|
||||
@@ -0,0 +1 @@
|
||||
["double extra comma",,]
|
||||
@@ -0,0 +1 @@
|
||||
[ , "<-- missing value"]
|
||||
@@ -0,0 +1 @@
|
||||
["Comma after the close"],
|
||||
@@ -0,0 +1 @@
|
||||
["Extra close"]]
|
||||
@@ -0,0 +1 @@
|
||||
{"Extra comma": true,}
|
||||
@@ -0,0 +1,54 @@
|
||||
note
|
||||
description: "A JSON converter for AUTHOR"
|
||||
author: "Paul Cohen"
|
||||
date: "$Date: 2010-03-08 20:46:59 -0300 (Mon, 08 Mar 2010) $"
|
||||
revision: "$Revision: 82 $"
|
||||
file: "$HeadURL: https://svn.origo.ethz.ch/ejson/branches/POC-converters-factory/test/json_author_converter.e $"
|
||||
|
||||
class JSON_AUTHOR_CONVERTER
|
||||
|
||||
inherit
|
||||
JSON_CONVERTER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
local
|
||||
ucs: STRING_32
|
||||
do
|
||||
create ucs.make_from_string ("")
|
||||
create object.make (ucs)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
object: AUTHOR
|
||||
|
||||
feature -- Conversion
|
||||
|
||||
from_json (j: like to_json): detachable like object
|
||||
local
|
||||
ucs: detachable STRING_32
|
||||
do
|
||||
ucs ?= json.object (j.item (name_key), Void)
|
||||
check ucs /= Void end
|
||||
create Result.make (ucs)
|
||||
end
|
||||
|
||||
to_json (o: like object): JSON_OBJECT
|
||||
do
|
||||
create Result.make
|
||||
Result.put (json.value (o.name), name_key)
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
name_key: JSON_STRING
|
||||
once
|
||||
create Result.make_json ("name")
|
||||
end
|
||||
|
||||
end -- class JSON_AUTHOR_CONVERTER
|
||||
@@ -0,0 +1,79 @@
|
||||
note
|
||||
description: "A JSON converter for BOOK_COLLECTION"
|
||||
author: "Paul Cohen"
|
||||
date: "$Date: 2010-03-08 20:46:59 -0300 (Mon, 08 Mar 2010) $"
|
||||
revision: "$Revision: 82 $"
|
||||
file: "$HeadURL: https://svn.origo.ethz.ch/ejson/branches/POC-converters-factory/test/json_book_collection_converter.e $"
|
||||
|
||||
class JSON_BOOK_COLLECTION_CONVERTER
|
||||
|
||||
inherit
|
||||
JSON_CONVERTER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
local
|
||||
ucs: STRING_32
|
||||
do
|
||||
create ucs.make_from_string ("")
|
||||
create object.make (ucs)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
object: BOOK_COLLECTION
|
||||
|
||||
feature -- Conversion
|
||||
|
||||
from_json (j: like to_json): detachable like object
|
||||
local
|
||||
ucs: detachable STRING_32
|
||||
ll: LINKED_LIST [BOOK]
|
||||
b: detachable BOOK
|
||||
ja: detachable JSON_ARRAY
|
||||
i: INTEGER
|
||||
do
|
||||
ucs ?= json.object (j.item (name_key), Void)
|
||||
check ucs /= Void end
|
||||
create Result.make (ucs)
|
||||
ja ?= j.item (books_key)
|
||||
check ja /= Void end
|
||||
from
|
||||
i := 1
|
||||
create ll.make
|
||||
until
|
||||
i > ja.count
|
||||
loop
|
||||
b ?= json.object (ja [i], "BOOK")
|
||||
check b /= Void end
|
||||
ll.force (b)
|
||||
i := i + 1
|
||||
end
|
||||
check ll /= Void end
|
||||
Result.add_books (ll)
|
||||
end
|
||||
|
||||
to_json (o: like object): JSON_OBJECT
|
||||
do
|
||||
create Result.make
|
||||
Result.put (json.value (o.name), name_key)
|
||||
Result.put (json.value (o.books), books_key)
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
name_key: JSON_STRING
|
||||
once
|
||||
create Result.make_json ("name")
|
||||
end
|
||||
|
||||
books_key: JSON_STRING
|
||||
once
|
||||
create Result.make_json ("books")
|
||||
end
|
||||
|
||||
end -- class JSON_BOOK_COLLECTION_CONVERTER
|
||||
@@ -0,0 +1,73 @@
|
||||
note
|
||||
description: "A JSON converter for BOOK"
|
||||
author: "Paul Cohen"
|
||||
date: "$Date: 2010-03-08 20:46:59 -0300 (Mon, 08 Mar 2010) $"
|
||||
revision: "$Revision: 82 $"
|
||||
file: "$HeadURL: https://svn.origo.ethz.ch/ejson/branches/POC-converters-factory/test/json_book_converter.e $"
|
||||
|
||||
class JSON_BOOK_CONVERTER
|
||||
|
||||
inherit
|
||||
JSON_CONVERTER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
local
|
||||
ucs: STRING_32
|
||||
a: AUTHOR
|
||||
do
|
||||
create ucs.make_from_string ("")
|
||||
create a.make (ucs)
|
||||
create object.make (ucs, a, ucs)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
object: BOOK
|
||||
|
||||
feature -- Conversion
|
||||
|
||||
from_json (j: like to_json): detachable like object
|
||||
local
|
||||
ucs1, ucs2: detachable STRING_32
|
||||
a: detachable AUTHOR
|
||||
do
|
||||
ucs1 ?= json.object (j.item (title_key), Void)
|
||||
check ucs1 /= Void end
|
||||
ucs2 ?= json.object (j.item (isbn_key), Void)
|
||||
check ucs2 /= Void end
|
||||
a ?= json.object (j.item (author_key), "AUTHOR")
|
||||
check a /= Void end
|
||||
create Result.make (ucs1, a, ucs2)
|
||||
end
|
||||
|
||||
to_json (o: like object): JSON_OBJECT
|
||||
do
|
||||
create Result.make
|
||||
Result.put (json.value (o.title), title_key)
|
||||
Result.put (json.value (o.isbn), isbn_key)
|
||||
Result.put (json.value (o.author), author_key)
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
title_key: JSON_STRING
|
||||
once
|
||||
create Result.make_json ("title")
|
||||
end
|
||||
|
||||
isbn_key: JSON_STRING
|
||||
once
|
||||
create Result.make_json ("isbn")
|
||||
end
|
||||
|
||||
author_key: JSON_STRING
|
||||
once
|
||||
create Result.make_json ("author")
|
||||
end
|
||||
|
||||
end -- class JSON_BOOK_CONVERTER
|
||||
@@ -0,0 +1,11 @@
|
||||
{"menu": {
|
||||
"id": "file",
|
||||
"value": "File",
|
||||
"popup": {
|
||||
"menuitem": [
|
||||
{"value": "New", "onclick": "CreateNewDoc()"},
|
||||
{"value": "Open", "onclick": "OpenDoc()"},
|
||||
{"value": "Close", "onclick": "CloseDoc()"}
|
||||
]
|
||||
}
|
||||
}}
|
||||
@@ -0,0 +1,58 @@
|
||||
[
|
||||
"JSON Test Pattern pass1",
|
||||
{"object with 1 member":["array with 1 element"]},
|
||||
{},
|
||||
[],
|
||||
-42,
|
||||
true,
|
||||
false,
|
||||
null,
|
||||
{
|
||||
"integer": 1234567890,
|
||||
"real": -9876.543210,
|
||||
"e": 0.123456789e-12,
|
||||
"E": 1.234567890E+34,
|
||||
"": 23456789012E66,
|
||||
"zero": 0,
|
||||
"one": 1,
|
||||
"space": " ",
|
||||
"quote": "\"",
|
||||
"backslash": "\\",
|
||||
"controls": "\b\f\n\r\t",
|
||||
"slash": "/ & \/",
|
||||
"alpha": "abcdefghijklmnopqrstuvwyz",
|
||||
"ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ",
|
||||
"digit": "0123456789",
|
||||
"0123456789": "digit",
|
||||
"special": "`1~!@#$%^&*()_+-={':[,]}|;.</>?",
|
||||
"hex": "\u0123\u4567\u89AB\uCDEF\uabcd\uef4A",
|
||||
"true": true,
|
||||
"false": false,
|
||||
"null": null,
|
||||
"array":[ ],
|
||||
"object":{ },
|
||||
"address": "50 St. James Street",
|
||||
"url": "http://www.JSON.org/",
|
||||
"comment": "// /* <!-- --",
|
||||
"# -- --> */": " ",
|
||||
" s p a c e d " :[1,2 , 3
|
||||
|
||||
,
|
||||
|
||||
4 , 5 , 6 ,7 ],"compact":[1,2,3,4,5,6,7],
|
||||
"jsontext": "{\"object with 1 member\":[\"array with 1 element\"]}",
|
||||
"quotes": "" \u0022 %22 0x22 034 "",
|
||||
"\/\\\"\uCAFE\uBABE\uAB98\uFCDE\ubcda\uef4A\b\f\n\r\t`1~!@#$%^&*()_+-=[]{}|;:',./<>?"
|
||||
: "A key can be any string"
|
||||
},
|
||||
0.5 ,98.6
|
||||
,
|
||||
99.44
|
||||
,
|
||||
|
||||
1066,
|
||||
1e1,
|
||||
0.1e1,
|
||||
1e-1,
|
||||
1e00,2e+00,2e-00
|
||||
,"rosebud"]
|
||||
@@ -0,0 +1 @@
|
||||
[[[[[[[[[[[[[[[[[[["Not too deep"]]]]]]]]]]]]]]]]]]]
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"JSON Test Pattern pass3": {
|
||||
"The outermost value": "must be an object or array.",
|
||||
"In this test": "It is an object."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
class TEST_DS
|
||||
|
||||
inherit
|
||||
SHARED_EJSON
|
||||
rename default_create as shared_default_create end
|
||||
EQA_TEST_SET
|
||||
select default_create end
|
||||
|
||||
|
||||
feature -- Test
|
||||
|
||||
test_linked_list_converter
|
||||
local
|
||||
jc: JSON_LINKED_LIST_CONVERTER
|
||||
l: LINKED_LIST [STRING]
|
||||
l2: detachable LINKED_LIST [detachable ANY]
|
||||
s: STRING
|
||||
jv: detachable JSON_VALUE
|
||||
do
|
||||
create jc.make
|
||||
json.add_converter (jc)
|
||||
create l.make
|
||||
s := "foo"
|
||||
l.force (s)
|
||||
s := "bar"
|
||||
l.force (s)
|
||||
jv := json.value (l)
|
||||
assert ("jv /= Void", jv /= Void)
|
||||
if attached jv as l_jv then
|
||||
s := jv.representation
|
||||
l2 ?= json.object (jv, "LINKED_LIST")
|
||||
assert ("l2 /= Void", l2 /= Void)
|
||||
end
|
||||
end
|
||||
|
||||
test_hash_table_converter
|
||||
local
|
||||
tc: JSON_HASH_TABLE_CONVERTER
|
||||
t: HASH_TABLE [STRING, STRING]
|
||||
t2: detachable HASH_TABLE [ANY, HASHABLE]
|
||||
s: STRING
|
||||
ucs_key, ucs_value: detachable STRING_32
|
||||
jv: detachable JSON_VALUE
|
||||
do
|
||||
create tc.make
|
||||
json.add_converter (tc)
|
||||
create t.make (2)
|
||||
t.put ("foo", "1")
|
||||
t.put ("bar", "2")
|
||||
jv := json.value (t)
|
||||
assert ("jv /= Void", jv /= Void)
|
||||
if attached jv as l_jv then
|
||||
s := l_jv.representation
|
||||
t2 ?= json.object (l_jv, "HASH_TABLE")
|
||||
assert ("t2 /= Void", t2 /= Void)
|
||||
end
|
||||
create ucs_key.make_from_string ("1")
|
||||
if attached t2 as l_t2 then
|
||||
ucs_value ?= t2 @ ucs_key
|
||||
assert ("ucs_value /= Void", ucs_value /= Void)
|
||||
if attached ucs_value as l_ucs_value then
|
||||
assert ("ucs_value.string.is_equal (%"foo%")", l_ucs_value.string.is_equal ("foo"))
|
||||
end
|
||||
create ucs_key.make_from_string ("2")
|
||||
ucs_value ?= t2 @ ucs_key
|
||||
assert ("ucs_value /= Void", ucs_value /= Void)
|
||||
if attached ucs_value as l_ucs_value then
|
||||
assert ("ucs_value.string.is_equal (%"bar%")", l_ucs_value.string.is_equal ("bar"))
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end -- class TEST_DS
|
||||
@@ -0,0 +1,822 @@
|
||||
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_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
|
||||
@@ -0,0 +1,42 @@
|
||||
class TEST_JSON_CUSTOM_CLASSES
|
||||
|
||||
inherit
|
||||
SHARED_EJSON
|
||||
rename default_create as shared_default_create end
|
||||
EQA_TEST_SET
|
||||
select default_create end
|
||||
feature -- Test
|
||||
|
||||
test_custom_classes
|
||||
local
|
||||
bc: detachable BOOK_COLLECTION
|
||||
jbc: JSON_BOOK_CONVERTER
|
||||
jbcc: JSON_BOOK_COLLECTION_CONVERTER
|
||||
jac: JSON_AUTHOR_CONVERTER
|
||||
jo: detachable JSON_OBJECT
|
||||
parser: JSON_PARSER
|
||||
jrep: STRING
|
||||
do
|
||||
create jbc.make
|
||||
json.add_converter (jbc)
|
||||
create jbcc.make
|
||||
json.add_converter (jbcc)
|
||||
create jac.make
|
||||
json.add_converter (jac)
|
||||
jrep := "{%"name%":%"Test collection%",%"books%":[{%"title%":%"eJSON: The Definitive Guide%",%"isbn%":%"123123-413243%",%"author%":{%"name%":%"Foo Bar%"}}]}"
|
||||
create parser.make_parser (jrep)
|
||||
jo := Void
|
||||
jo ?= parser.parse
|
||||
assert ("jo /= Void", jo /= Void)
|
||||
bc := Void
|
||||
bc ?= json.object (jo, "BOOK_COLLECTION")
|
||||
assert ("bc /= Void", bc /= Void)
|
||||
jo ?= json.value (bc)
|
||||
assert ("jo /= Void", jo /= Void)
|
||||
if attached jo as l_jo then
|
||||
assert ("JSON representation is correct", l_jo.representation.same_string ("{%"name%":%"Test collection%",%"books%":[{%"title%":%"eJSON: The Definitive Guide%",%"isbn%":%"123123-413243%",%"author%":{%"name%":%"Foo Bar%"}}]}"))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end -- class TEST_JSON_CUSTOM_CLASS
|
||||
@@ -0,0 +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
|
||||
-- <Precursor>
|
||||
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
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="test_suite" uuid="EA141B17-6A21-4781-8B5F-E9939BAE968A">
|
||||
<target name="test_suite">
|
||||
<root cluster="test_suite" class="APPLICATION" feature="make"/>
|
||||
<file_rule>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/CVS$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" is_attached_by_default="true" void_safety="all" syntax="standard">
|
||||
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="json" location="..\..\..\library\json-safe.ecf"/>
|
||||
<library name="testing" location="$ISE_LIBRARY\library\testing\testing-safe.ecf"/>
|
||||
<cluster name="test_suite" location=".\" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-5-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-5-0 http://www.eiffel.com/developers/xml/configuration-1-5-0.xsd" name="test_suite" uuid="EA141B17-6A21-4781-8B5F-E9939BAE968A">
|
||||
<target name="test_suite">
|
||||
<root cluster="test_suite" class="APPLICATION" feature="make"/>
|
||||
<file_rule>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/CVS$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true">
|
||||
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||
</option>
|
||||
<precompile name="base_pre" location="$ISE_PRECOMP\base.ecf"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
|
||||
<library name="json" location="..\..\..\library\json.ecf"/>
|
||||
<library name="testing" location="$ISE_LIBRARY\library\testing\testing.ecf"/>
|
||||
<cluster name="test_suite" location=".\" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
24
contrib/library/text/parser/json/test/getest/author.e
Normal file
24
contrib/library/text/parser/json/test/getest/author.e
Normal file
@@ -0,0 +1,24 @@
|
||||
class AUTHOR
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_name: UC_STRING) is
|
||||
do
|
||||
set_name (a_name)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
name: UC_STRING
|
||||
|
||||
feature -- Status setting
|
||||
|
||||
set_name (a_name: UC_STRING) is
|
||||
do
|
||||
name := a_name
|
||||
end
|
||||
|
||||
end -- class AUTHOR
|
||||
40
contrib/library/text/parser/json/test/getest/book.e
Normal file
40
contrib/library/text/parser/json/test/getest/book.e
Normal file
@@ -0,0 +1,40 @@
|
||||
class BOOK
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_title: UC_STRING; an_author: AUTHOR; an_isbn: UC_STRING) is
|
||||
do
|
||||
set_title (a_title)
|
||||
set_author (an_author)
|
||||
set_isbn (an_isbn)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
title: UC_STRING
|
||||
|
||||
isbn: UC_STRING
|
||||
|
||||
author: AUTHOR
|
||||
|
||||
feature -- Status setting
|
||||
|
||||
set_title (a_title: UC_STRING) is
|
||||
do
|
||||
title := a_title
|
||||
end
|
||||
|
||||
set_author (an_author: AUTHOR) is
|
||||
do
|
||||
author := an_author
|
||||
end
|
||||
|
||||
set_isbn (an_isbn: UC_STRING) is
|
||||
do
|
||||
isbn := an_isbn
|
||||
end
|
||||
|
||||
end -- class BOOK
|
||||
@@ -0,0 +1,82 @@
|
||||
class BOOK_COLLECTION
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_name: UC_STRING) is
|
||||
do
|
||||
set_name (a_name)
|
||||
create book_index.make (10)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
name: UC_STRING
|
||||
|
||||
books: DS_LIST [BOOK] is
|
||||
local
|
||||
c: DS_HASH_TABLE_CURSOR [DS_LIST [BOOK], UC_STRING]
|
||||
do
|
||||
from
|
||||
create {DS_LINKED_LIST [BOOK]} Result.make
|
||||
c := book_index.new_cursor
|
||||
c.start
|
||||
until
|
||||
c.after
|
||||
loop
|
||||
Result.append_last (c.item)
|
||||
c.forth
|
||||
end
|
||||
end
|
||||
|
||||
books_by_author (an_author: UC_STRING): DS_LIST [BOOK] is
|
||||
do
|
||||
if book_index.has (an_author) then
|
||||
Result := book_index @ an_author
|
||||
else
|
||||
create {DS_LINKED_LIST [BOOK]} Result.make
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Status setting
|
||||
|
||||
set_name (a_name: UC_STRING) is
|
||||
do
|
||||
name := a_name
|
||||
end
|
||||
|
||||
add_book (a_book: BOOK) is
|
||||
local
|
||||
l: DS_LIST [BOOK]
|
||||
do
|
||||
if book_index.has (a_book.author.name) then
|
||||
l := book_index @ a_book.author.name
|
||||
else
|
||||
create {DS_LINKED_LIST [BOOK]} l.make
|
||||
book_index.put (l, a_book.author.name)
|
||||
end
|
||||
l.put_last (a_book)
|
||||
end
|
||||
|
||||
add_books (book_list: like books) is
|
||||
local
|
||||
c: DS_LIST_CURSOR [BOOK]
|
||||
do
|
||||
from
|
||||
c := book_list.new_cursor
|
||||
c.start
|
||||
until
|
||||
c.after
|
||||
loop
|
||||
add_book (c.item)
|
||||
c.forth
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
book_index: DS_HASH_TABLE [DS_LIST [BOOK], UC_STRING]
|
||||
|
||||
end -- class BOOK_COLLECTION
|
||||
11
contrib/library/text/parser/json/test/getest/ec_compile.bat
Normal file
11
contrib/library/text/parser/json/test/getest/ec_compile.bat
Normal file
@@ -0,0 +1,11 @@
|
||||
echo Compiling ejson_test (finalized)
|
||||
ecb -finalize -c_compile -config ejson_test.ecf -batch -clean > NUL 2>&1
|
||||
IF %ERRORLEVEL% EQU -1 goto ERROR
|
||||
copy EIFGENs\ejson_test\F_code\ejson_test.exe ejson_test.exe
|
||||
goto EOF
|
||||
|
||||
:ERROR
|
||||
echo Error occurred during ejson_test compilation
|
||||
goto EOF
|
||||
|
||||
:EOF
|
||||
5
contrib/library/text/parser/json/test/getest/ec_compile.sh
Executable file
5
contrib/library/text/parser/json/test/getest/ec_compile.sh
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "ec -finalize -c_compile -config ejson_test.ecf > /dev/null 2>&1"
|
||||
ec -finalize -c_compile -config ejson_test.ecf > /dev/null 2>&1
|
||||
cp EIFGENs/ejson_test/F_code/ejson_test .
|
||||
@@ -0,0 +1,17 @@
|
||||
-- Gobo test (getest) configuration file for eJSON
|
||||
|
||||
test
|
||||
ejson_test
|
||||
|
||||
default
|
||||
class ("TEST_[A-Z0-9_]*")
|
||||
feature ("test_[a-z0-9_]*")
|
||||
prefix ("X")
|
||||
testgen ("TESTGEN")
|
||||
compile ("ec_compile.bat")
|
||||
execute ("ejson_test.exe")
|
||||
|
||||
cluster
|
||||
test_dir: "."
|
||||
|
||||
end
|
||||
17
contrib/library/text/parser/json/test/getest/ejson_test.cfg
Normal file
17
contrib/library/text/parser/json/test/getest/ejson_test.cfg
Normal file
@@ -0,0 +1,17 @@
|
||||
-- Gobo test (getest) configuration file for eJSON
|
||||
|
||||
test
|
||||
ejson_test
|
||||
|
||||
default
|
||||
class ("TEST_[A-Z0-9_]*")
|
||||
feature ("test_[a-z0-9_]*")
|
||||
prefix ("X")
|
||||
testgen ("TESTGEN")
|
||||
compile ("./ec_compile.sh")
|
||||
execute ("./ejson_test")
|
||||
|
||||
cluster
|
||||
test_dir: "."
|
||||
|
||||
end
|
||||
21
contrib/library/text/parser/json/test/getest/ejson_test.ecf
Normal file
21
contrib/library/text/parser/json/test/getest/ejson_test.ecf
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-5-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-5-0 http://www.eiffel.com/developers/xml/configuration-1-5-0.xsd" name="ejson_test" uuid="9D4BC920-448B-4F84-9F95-5D47686EBC5E">
|
||||
<target name="ejson_test">
|
||||
<root class="EJSON_TEST" feature="make"/>
|
||||
<file_rule>
|
||||
<exclude>//.svn</exclude>
|
||||
<exclude>/cvs$</exclude>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
</file_rule>
|
||||
<option warning="true" void_safety="none" syntax="obsolete">
|
||||
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||
</option>
|
||||
<library name="base" location="$ISE_LIBRARY/library/base/base.ecf"/>
|
||||
<library name="json" location="../../library/json.ecf"/>
|
||||
<library name="json_gobo_extension" location="../../library/json_gobo_extension.ecf"/>
|
||||
<library name="gobo_kernel" location="$ISE_LIBRARY/library/gobo/gobo_kernel.ecf"/>
|
||||
<library name="gobo_structure" location="$ISE_LIBRARY/library/gobo/gobo_structure.ecf"/>
|
||||
<library name="gobo_test" location="$ISE_LIBRARY/library/gobo/gobo_test.ecf"/>
|
||||
<cluster name="tests" location="." recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
@@ -0,0 +1,56 @@
|
||||
indexing
|
||||
description: "A JSON converter for AUTHOR"
|
||||
author: "Paul Cohen"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
file: "$HeadURL: https://svn.origo.ethz.ch/ejson/branches/POC-converters-factory/test/json_author_converter.e $"
|
||||
|
||||
class JSON_AUTHOR_CONVERTER
|
||||
|
||||
inherit
|
||||
JSON_CONVERTER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make is
|
||||
local
|
||||
ucs: UC_STRING
|
||||
do
|
||||
create ucs.make_from_string ("")
|
||||
create object.make (ucs)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
value: JSON_OBJECT
|
||||
|
||||
object: AUTHOR
|
||||
|
||||
feature -- Conversion
|
||||
|
||||
from_json (j: like value): like object is
|
||||
local
|
||||
ucs: UC_STRING
|
||||
do
|
||||
ucs ?= json.object (j.item (name_key), Void)
|
||||
check ucs /= Void end
|
||||
create Result.make (ucs)
|
||||
end
|
||||
|
||||
to_json (o: like object): like value is
|
||||
do
|
||||
create Result.make
|
||||
Result.put (json.value (o.name), name_key)
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
name_key: JSON_STRING is
|
||||
once
|
||||
create Result.make_json ("name")
|
||||
end
|
||||
|
||||
end -- class JSON_AUTHOR_CONVERTER
|
||||
@@ -0,0 +1,81 @@
|
||||
indexing
|
||||
description: "A JSON converter for BOOK_COLLECTION"
|
||||
author: "Paul Cohen"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
file: "$HeadURL: https://svn.origo.ethz.ch/ejson/branches/POC-converters-factory/test/json_book_collection_converter.e $"
|
||||
|
||||
class JSON_BOOK_COLLECTION_CONVERTER
|
||||
|
||||
inherit
|
||||
JSON_CONVERTER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make is
|
||||
local
|
||||
ucs: UC_STRING
|
||||
do
|
||||
create ucs.make_from_string ("")
|
||||
create object.make (ucs)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
value: JSON_OBJECT
|
||||
|
||||
object: BOOK_COLLECTION
|
||||
|
||||
feature -- Conversion
|
||||
|
||||
from_json (j: like value): like object is
|
||||
local
|
||||
ucs: UC_STRING
|
||||
ll: DS_LINKED_LIST [BOOK]
|
||||
b: BOOK
|
||||
ja: JSON_ARRAY
|
||||
i: INTEGER
|
||||
do
|
||||
ucs ?= json.object (j.item (name_key), Void)
|
||||
check ucs /= Void end
|
||||
create Result.make (ucs)
|
||||
ja ?= j.item (books_key)
|
||||
check ja /= Void end
|
||||
from
|
||||
i := 1
|
||||
create ll.make
|
||||
until
|
||||
i > ja.count
|
||||
loop
|
||||
b ?= json.object (ja [i], "BOOK")
|
||||
check b /= Void end
|
||||
ll.put_last (b)
|
||||
i := i + 1
|
||||
end
|
||||
check ll /= Void end
|
||||
Result.add_books (ll)
|
||||
end
|
||||
|
||||
to_json (o: like object): like value is
|
||||
do
|
||||
create Result.make
|
||||
Result.put (json.value (o.name), name_key)
|
||||
Result.put (json.value (o.books), books_key)
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
name_key: JSON_STRING is
|
||||
once
|
||||
create Result.make_json ("name")
|
||||
end
|
||||
|
||||
books_key: JSON_STRING is
|
||||
once
|
||||
create Result.make_json ("books")
|
||||
end
|
||||
|
||||
end -- class JSON_BOOK_COLLECTION_CONVERTER
|
||||
@@ -0,0 +1,75 @@
|
||||
indexing
|
||||
description: "A JSON converter for BOOK"
|
||||
author: "Paul Cohen"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
file: "$HeadURL: https://svn.origo.ethz.ch/ejson/branches/POC-converters-factory/test/json_book_converter.e $"
|
||||
|
||||
class JSON_BOOK_CONVERTER
|
||||
|
||||
inherit
|
||||
JSON_CONVERTER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make is
|
||||
local
|
||||
ucs: UC_STRING
|
||||
a: AUTHOR
|
||||
do
|
||||
create ucs.make_from_string ("")
|
||||
create a.make (ucs)
|
||||
create object.make (ucs, a, ucs)
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
value: JSON_OBJECT
|
||||
|
||||
object: BOOK
|
||||
|
||||
feature -- Conversion
|
||||
|
||||
from_json (j: like value): like object is
|
||||
local
|
||||
ucs1, ucs2: UC_STRING
|
||||
a: AUTHOR
|
||||
do
|
||||
ucs1 ?= json.object (j.item (title_key), Void)
|
||||
check ucs1 /= Void end
|
||||
ucs2 ?= json.object (j.item (isbn_key), Void)
|
||||
check ucs2 /= Void end
|
||||
a ?= json.object (j.item (author_key), "AUTHOR")
|
||||
check a /= Void end
|
||||
create Result.make (ucs1, a, ucs2)
|
||||
end
|
||||
|
||||
to_json (o: like object): like value is
|
||||
do
|
||||
create Result.make
|
||||
Result.put (json.value (o.title), title_key)
|
||||
Result.put (json.value (o.isbn), isbn_key)
|
||||
Result.put (json.value (o.author), author_key)
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
title_key: JSON_STRING is
|
||||
once
|
||||
create Result.make_json ("title")
|
||||
end
|
||||
|
||||
isbn_key: JSON_STRING is
|
||||
once
|
||||
create Result.make_json ("isbn")
|
||||
end
|
||||
|
||||
author_key: JSON_STRING is
|
||||
once
|
||||
create Result.make_json ("author")
|
||||
end
|
||||
|
||||
end -- class JSON_BOOK_CONVERTER
|
||||
10
contrib/library/text/parser/json/test/getest/readme.txt
Normal file
10
contrib/library/text/parser/json/test/getest/readme.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
To compile and run the test program do as follows:
|
||||
|
||||
1. Make sure you have a compiled version of getest in your PATH.
|
||||
|
||||
2. In this dircetory, run the command:
|
||||
|
||||
$ getest --verbose --ise ejson_test.cfg
|
||||
|
||||
|
||||
Note: on Windows, you should use ejson_test-win.cfg
|
||||
71
contrib/library/text/parser/json/test/getest/test_ds.e
Normal file
71
contrib/library/text/parser/json/test/getest/test_ds.e
Normal file
@@ -0,0 +1,71 @@
|
||||
class TEST_DS
|
||||
|
||||
inherit
|
||||
SHARED_GOBO_EJSON
|
||||
|
||||
TS_TEST_CASE
|
||||
|
||||
create
|
||||
make_default
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make is
|
||||
-- Create test object.
|
||||
do
|
||||
end
|
||||
|
||||
feature -- Test
|
||||
|
||||
test_ds_linked_list_converter is
|
||||
local
|
||||
jc: JSON_DS_LINKED_LIST_CONVERTER
|
||||
l: DS_LINKED_LIST [STRING]
|
||||
l2: DS_LINKED_LIST [ANY]
|
||||
s: STRING
|
||||
jv: JSON_VALUE
|
||||
do
|
||||
create jc.make
|
||||
json.add_converter (jc)
|
||||
create l.make
|
||||
s := "foo"
|
||||
l.put_last (s)
|
||||
s := "bar"
|
||||
l.put_last (s)
|
||||
jv := json.value (l)
|
||||
assert ("jv /= Void", jv /= Void)
|
||||
s := jv.representation
|
||||
l2 ?= json.object (jv, "DS_LINKED_LIST")
|
||||
assert ("l2 /= Void", l2 /= Void)
|
||||
end
|
||||
|
||||
test_ds_hash_table_converter is
|
||||
local
|
||||
tc: JSON_DS_HASH_TABLE_CONVERTER
|
||||
t: DS_HASH_TABLE [STRING, STRING]
|
||||
t2: DS_HASH_TABLE [ANY, HASHABLE]
|
||||
s: STRING
|
||||
ucs_key, ucs_value: UC_STRING
|
||||
jv: JSON_VALUE
|
||||
do
|
||||
create tc.make
|
||||
json.add_converter (tc)
|
||||
create t.make (2)
|
||||
t.put ("foo", "1")
|
||||
t.put ("bar", "2")
|
||||
jv := json.value (t)
|
||||
assert ("jv /= Void", jv /= Void)
|
||||
s := jv.representation
|
||||
t2 ?= json.object (jv, "DS_HASH_TABLE")
|
||||
assert ("t2 /= Void", t2 /= Void)
|
||||
create ucs_key.make_from_string ("1")
|
||||
ucs_value ?= t2 @ ucs_key
|
||||
assert ("ucs_value /= Void", ucs_value /= Void)
|
||||
assert ("ucs_value.string.is_equal (%"foo%")", ucs_value.string.is_equal ("foo"))
|
||||
create ucs_key.make_from_string ("2")
|
||||
ucs_value ?= t2 @ ucs_key
|
||||
assert ("ucs_value /= Void", ucs_value /= Void)
|
||||
assert ("ucs_value.string.is_equal (%"bar%")", ucs_value.string.is_equal ("bar"))
|
||||
end
|
||||
|
||||
end -- class TEST_DS
|
||||
703
contrib/library/text/parser/json/test/getest/test_json_core.e
Normal file
703
contrib/library/text/parser/json/test/getest/test_json_core.e
Normal file
@@ -0,0 +1,703 @@
|
||||
class TEST_JSON_CORE
|
||||
|
||||
inherit
|
||||
TS_TEST_CASE
|
||||
SHARED_EJSON
|
||||
|
||||
create
|
||||
make_default
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make is
|
||||
-- Create test object.
|
||||
do
|
||||
end
|
||||
|
||||
feature -- Test
|
||||
|
||||
test_json_number_and_integer is
|
||||
local
|
||||
i: INTEGER
|
||||
i8: INTEGER_8
|
||||
jn: JSON_NUMBER
|
||||
jrep: STRING
|
||||
parser: JSON_PARSER
|
||||
do
|
||||
i := 42
|
||||
-- Eiffel value -> JSON value -> JSON representation
|
||||
create jn.make_integer (i)
|
||||
assert ("jn /= Void", jn /= Void)
|
||||
assert ("jn.representation.is_equal (%"42%")", jn.representation.is_equal ("42"))
|
||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||
jn := Void
|
||||
jn ?= json.value (i)
|
||||
assert ("jn /= Void", jn /= Void)
|
||||
assert ("jn.representation.is_equal (%"42%")", jn.representation.is_equal ("42"))
|
||||
-- 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)
|
||||
jn := Void
|
||||
jn ?= parser.parse
|
||||
assert ("jn /= Void", jn /= Void)
|
||||
i8 := 0
|
||||
i8 ?= json.object (jn, Void)
|
||||
assert ("i8 = 42", i8 = 42)
|
||||
end
|
||||
|
||||
test_json_number_and_integer_8 is
|
||||
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 /= Void", jn /= Void)
|
||||
assert ("jn.representation.is_equal (%"42%")", jn.representation.is_equal ("42"))
|
||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||
jn := Void
|
||||
jn ?= json.value (i8)
|
||||
assert ("jn /= Void", jn /= Void)
|
||||
assert ("jn.representation.is_equal (%"42%")", jn.representation.is_equal ("42"))
|
||||
-- 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)
|
||||
jn := Void
|
||||
jn ?= parser.parse
|
||||
assert ("jn /= Void", jn /= Void)
|
||||
i8 := 0
|
||||
i8 ?= json.object (jn, Void)
|
||||
assert ("i8 = 42", i8 = 42)
|
||||
end
|
||||
|
||||
test_json_number_and_integer_16 is
|
||||
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 /= Void", jn /= Void)
|
||||
assert ("jn.representation.is_equal (%"300%")", jn.representation.is_equal ("300"))
|
||||
-- Eiffel value -> JSON with factory
|
||||
jn := Void
|
||||
jn ?= json.value (i16)
|
||||
assert ("jn /= Void", jn /= Void)
|
||||
assert ("jn.representation.is_equal (%"300%")", jn.representation.is_equal ("300"))
|
||||
-- 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)
|
||||
jn := Void
|
||||
jn ?= parser.parse
|
||||
assert ("jn /= Void", jn /= Void)
|
||||
i16 := 0
|
||||
i16 ?= json.object (jn, Void)
|
||||
assert ("i16 = 300", i16 = 300)
|
||||
end
|
||||
|
||||
test_json_number_and_integer_32 is
|
||||
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 /= Void", jn /= Void)
|
||||
assert ("jn.representation.is_equal (%"100000%")", jn.representation.is_equal ("100000"))
|
||||
-- Eiffel value -> JSON representation -> JSON value with factory
|
||||
jn := Void
|
||||
jn ?= json.value (i32)
|
||||
assert ("jn /= Void", jn /= Void)
|
||||
assert ("jn.representation.is_equal (%"100000%")", jn.representation.is_equal ("100000"))
|
||||
-- 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)
|
||||
jn := Void
|
||||
jn ?= parser.parse
|
||||
assert ("jn /= Void", jn /= Void)
|
||||
i32 := 0
|
||||
i32 ?= json.object (jn, Void)
|
||||
assert ("i32 = 100000", i32 = 100000)
|
||||
end
|
||||
|
||||
test_json_number_and_integer_64 is
|
||||
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 /= Void", jn /= Void)
|
||||
assert ("jn.representation.is_equal (%"42949672960%")", jn.representation.is_equal ("42949672960"))
|
||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||
jn := Void
|
||||
jn ?= json.value (i64)
|
||||
assert ("jn /= Void", jn /= Void)
|
||||
assert ("jn.representation.is_equal (%"42949672960%")", jn.representation.is_equal ("42949672960"))
|
||||
-- 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)
|
||||
jn := Void
|
||||
jn ?= parser.parse
|
||||
assert ("jn /= Void", jn /= Void)
|
||||
i64 := 0
|
||||
i64 ?= json.object (jn, Void)
|
||||
assert ("i64 = 42949672960", i64 = 42949672960)
|
||||
end
|
||||
|
||||
test_json_number_and_natural_8 is
|
||||
local
|
||||
n8: NATURAL_8
|
||||
i16: INTEGER_16
|
||||
jn: JSON_NUMBER
|
||||
jrep: STRING
|
||||
parser: JSON_PARSER
|
||||
do
|
||||
n8 := 200
|
||||
-- Eiffel value -> JSON value -> JSON representation
|
||||
create jn.make_natural (n8)
|
||||
assert ("jn /= Void", jn /= Void)
|
||||
assert ("jn.representation.is_equal (%"200%")", jn.representation.is_equal ("200"))
|
||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||
jn := Void
|
||||
jn ?= json.value (n8)
|
||||
assert ("jn /= Void", jn /= Void)
|
||||
assert ("jn.representation.is_equal (%"200%")", jn.representation.is_equal ("200"))
|
||||
-- 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)
|
||||
jn := Void
|
||||
jn ?= parser.parse
|
||||
assert ("jn /= Void", jn /= Void)
|
||||
i16 := 0
|
||||
i16 ?= json.object (jn, Void)
|
||||
assert ("i16 = 200", i16 = 200)
|
||||
end
|
||||
|
||||
test_json_number_and_natural_16 is
|
||||
local
|
||||
n16: NATURAL_16
|
||||
i32: INTEGER_32
|
||||
jn: JSON_NUMBER
|
||||
jrep: STRING
|
||||
parser: JSON_PARSER
|
||||
do
|
||||
n16 := 32768
|
||||
-- Eiffel value -> JSON value -> JSON representation
|
||||
create jn.make_natural (n16)
|
||||
assert ("jn /= Void", jn /= Void)
|
||||
assert ("jn.representation.is_equal (%"32768%")", jn.representation.is_equal ("32768"))
|
||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||
jn := Void
|
||||
jn ?= json.value (n16)
|
||||
assert ("jn /= Void", jn /= Void)
|
||||
assert ("jn.representation.is_equal (%"32768%")", jn.representation.is_equal ("32768"))
|
||||
-- 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)
|
||||
jn := Void
|
||||
jn ?= parser.parse
|
||||
assert ("jn /= Void", jn /= Void)
|
||||
i32 := 0
|
||||
i32 ?= json.object (jn, Void)
|
||||
assert ("i32 = 32768", i32 = 32768)
|
||||
end
|
||||
|
||||
test_json_number_and_natural_32 is
|
||||
local
|
||||
n32: NATURAL_32
|
||||
i64: INTEGER_64
|
||||
jn: JSON_NUMBER
|
||||
jrep: STRING
|
||||
parser: JSON_PARSER
|
||||
do
|
||||
n32 := 2147483648
|
||||
-- Eiffel value -> JSON value -> JSON representation
|
||||
create jn.make_natural (n32)
|
||||
assert ("jn /= Void", jn /= Void)
|
||||
assert ("jn.representation.is_equal (%"2147483648%")", jn.representation.is_equal ("2147483648"))
|
||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||
jn := Void
|
||||
jn ?= json.value (n32)
|
||||
assert ("jn /= Void", jn /= Void)
|
||||
assert ("jn.representation.is_equal (%"2147483648%")", jn.representation.is_equal ("2147483648"))
|
||||
-- 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)
|
||||
jn := Void
|
||||
jn ?= parser.parse
|
||||
assert ("jn /= Void", jn /= Void)
|
||||
i64 := 0
|
||||
i64 ?= json.object (jn, Void)
|
||||
assert ("i64 = 2147483648", i64 = 2147483648)
|
||||
end
|
||||
|
||||
test_json_number_and_large_integers is
|
||||
local
|
||||
jrep: STRING
|
||||
jn: JSON_NUMBER
|
||||
n64: NATURAL_64
|
||||
parser: JSON_PARSER
|
||||
do
|
||||
n64 := 9223372036854775808
|
||||
-- Eiffel value -> JSON value -> JSON representation
|
||||
create jn.make_natural (n64)
|
||||
assert ("jn /= Void", jn /= Void)
|
||||
assert ("jn.representation.is_equal (%"9223372036854775808%")", jn.representation.is_equal ("9223372036854775808"))
|
||||
jn := Void
|
||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||
jn ?= json.value (n64)
|
||||
assert ("jn /= Void", jn /= Void)
|
||||
assert ("jn.representation.is_equal (%"9223372036854775808%")", jn.representation.is_equal ("9223372036854775808"))
|
||||
-- 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)
|
||||
jn := Void
|
||||
jn ?= parser.parse
|
||||
assert ("jn /= Void", jn /= Void)
|
||||
n64 := 0
|
||||
n64 ?= json.object (jn, Void)
|
||||
end
|
||||
|
||||
test_json_number_and_eiffel_real is
|
||||
local
|
||||
r: REAL
|
||||
r64: REAL_64
|
||||
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 /= Void", jn /= Void)
|
||||
assert ("jn.representation.is_equal (%"3.1400001049041748%")", jn.representation.is_equal ("3.1400001049041748"))
|
||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||
jn ?= json.value (r)
|
||||
assert ("jn /= Void", jn /= Void)
|
||||
assert ("jn.representation.is_equal (%"3.1400001049041748%")", jn.representation.is_equal ("3.1400001049041748"))
|
||||
-- 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)
|
||||
jn := Void
|
||||
jn ?= parser.parse
|
||||
assert ("jn /= Void", jn /= Void)
|
||||
r64 := 0
|
||||
r64 ?= json.object (jn, Void)
|
||||
assert ("r64 = 3.1400000000000001", r64 = 3.1400000000000001)
|
||||
end
|
||||
|
||||
test_json_number_and_eiffel_real_32 is
|
||||
local
|
||||
r32: REAL_32
|
||||
r64: REAL_64
|
||||
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 /= Void", jn /= Void)
|
||||
assert ("jn.representation.is_equal (%"3.1400001049041748%")", jn.representation.is_equal ("3.1400001049041748"))
|
||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||
jn ?= json.value (r32)
|
||||
assert ("jn /= Void", jn /= Void)
|
||||
assert ("jn.representation.is_equal (%"3.1400001049041748%")", jn.representation.is_equal ("3.1400001049041748"))
|
||||
-- JSON representation -> JSON value -> Eiffel value
|
||||
jrep := "3.1400001049041748"
|
||||
create parser.make_parser (jrep)
|
||||
jn ?= parser.parse
|
||||
assert ("jn /= Void", jn /= Void)
|
||||
r64 := 0
|
||||
r64 ?= json.object (jn, Void)
|
||||
assert ("r64 = 3.1400001049041748", r64 = 3.1400001049041748)
|
||||
end
|
||||
|
||||
test_json_number_and_eiffel_real_64 is
|
||||
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 /= Void", jn /= Void)
|
||||
assert ("jn.representation.is_equal (%"3.1415926535897931%")", jn.representation.is_equal ("3.1415926535897931"))
|
||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||
jn ?= json.value (r64)
|
||||
assert ("jn /= Void", jn /= Void)
|
||||
assert ("jn.representation.is_equal (%"3.1415926535897931%")", jn.representation.is_equal ("3.1415926535897931"))
|
||||
-- JSON representation -> JSON value -> Eiffel value
|
||||
jrep := "3.1415926535897931"
|
||||
create parser.make_parser (jrep)
|
||||
jn := Void
|
||||
jn ?= parser.parse
|
||||
assert ("jn /= Void", jn /= Void)
|
||||
r64 := 0
|
||||
r64 ?= json.object (jn, Void)
|
||||
assert ("r64 = 3.1415926535897931", r64 = 3.1415926535897931)
|
||||
end
|
||||
|
||||
test_json_boolean is
|
||||
local
|
||||
b: BOOLEAN
|
||||
jb: JSON_BOOLEAN
|
||||
jrep: STRING
|
||||
parser: JSON_PARSER
|
||||
do
|
||||
b := True
|
||||
-- Eiffel value -> JSON value -> JSON representation
|
||||
create jb.make_boolean (b)
|
||||
assert ("jb /= Void", jb /= Void)
|
||||
assert ("jb.representation.is_equal (%"true%")", jb.representation.is_equal ("true"))
|
||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||
jb ?= json.value (b)
|
||||
assert ("jb /= Void", jb /= Void)
|
||||
assert ("jb.representation.is_equal (%"true%")", jb.representation.is_equal ("true"))
|
||||
-- JSON representation -> JSON value -> Eiffel value
|
||||
jrep := "true"
|
||||
create parser.make_parser (jrep)
|
||||
jb := Void
|
||||
jb ?= parser.parse
|
||||
assert ("jb /= Void", jb /= Void)
|
||||
b := False
|
||||
b ?= json.object (jb, Void)
|
||||
assert ("b = True", b = True)
|
||||
|
||||
b := False
|
||||
-- Eiffel value -> JSON value -> JSON representation
|
||||
create jb.make_boolean (b)
|
||||
assert ("jb /= Void", jb /= Void)
|
||||
assert ("jb.representation.is_equal (%"false%")", jb.representation.is_equal ("false"))
|
||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||
jb ?= json.value (b)
|
||||
assert ("jb /= Void", jb /= Void)
|
||||
assert ("jb.representation.is_equal (%"false%")", jb.representation.is_equal ("false"))
|
||||
-- JSON representation -> JSON value -> Eiffel value
|
||||
jrep := "false"
|
||||
create parser.make_parser (jrep)
|
||||
jb := Void
|
||||
jb ?= parser.parse
|
||||
assert ("jb /= Void", jb /= Void)
|
||||
b := True
|
||||
b ?= json.object (jb, Void)
|
||||
assert ("b = False", b = False)
|
||||
end
|
||||
|
||||
test_json_null is
|
||||
local
|
||||
a: ANY
|
||||
dummy_object: STRING
|
||||
jn: 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)
|
||||
assert ("jn.representation.is_equal (%"null%")", jn.representation.is_equal ("null"))
|
||||
-- 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 is
|
||||
local
|
||||
c: CHARACTER
|
||||
js: JSON_STRING
|
||||
ucs: UC_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)
|
||||
assert ("js.representation.is_equal (%"%"a%"%")", js.representation.is_equal ("%"a%""))
|
||||
-- JSON representation -> JSON value -> Eiffel value
|
||||
jrep := "%"a%""
|
||||
create parser.make_parser (jrep)
|
||||
js := Void
|
||||
js ?= parser.parse
|
||||
assert ("js /= Void", js /= Void)
|
||||
ucs ?= json.object (js, Void)
|
||||
assert ("ucs.string.is_equal (%"a%")", ucs.string.is_equal ("a"))
|
||||
end
|
||||
|
||||
test_json_string_and_string is
|
||||
local
|
||||
s: STRING
|
||||
js: JSON_STRING
|
||||
ucs: UC_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)
|
||||
assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.is_equal ("%"foobar%""))
|
||||
-- JSON representation -> JSON value -> Eiffel value
|
||||
jrep := "%"foobar%""
|
||||
create parser.make_parser (jrep)
|
||||
js := Void
|
||||
js ?= parser.parse
|
||||
assert ("js /= Void", js /= Void)
|
||||
ucs ?= json.object (js, Void)
|
||||
assert ("ucs.string.is_equal (%"foobar%")", ucs.string.is_equal ("foobar"))
|
||||
end
|
||||
|
||||
test_json_string_and_uc_string is
|
||||
local
|
||||
js: JSON_STRING
|
||||
ucs: UC_STRING
|
||||
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)
|
||||
assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.is_equal ("%"foobar%""))
|
||||
-- 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)
|
||||
assert ("ucs.string.is_equal (%"foobar%")", ucs.string.is_equal ("foobar"))
|
||||
end
|
||||
|
||||
test_json_array is
|
||||
local
|
||||
ll: LINKED_LIST [INTEGER_8]
|
||||
ll2: LINKED_LIST [ANY]
|
||||
ja: JSON_ARRAY
|
||||
jn: JSON_NUMBER
|
||||
jrep: STRING
|
||||
parser: JSON_PARSER
|
||||
i, n: INTEGER
|
||||
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)
|
||||
assert ("ja.representation.is_equal (%"[0,1,1,2,3,5]%")", ja.representation.is_equal ("[0,1,1,2,3,5]"))
|
||||
-- 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
|
||||
assert ("ll2.is_equal (ll)", ll2.is_equal (ll))
|
||||
end
|
||||
|
||||
test_json_object is
|
||||
local
|
||||
t, t2: HASH_TABLE [ANY, UC_STRING]
|
||||
i: INTEGER
|
||||
ucs_key, ucs: UC_STRING
|
||||
a: ARRAY [INTEGER]
|
||||
jo: 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 DS_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 (%"{%"size%":42,%"contents%":[0,1,1,2,3,5],%"name%":%"foobar%"}%")", jo.representation.is_equal ("{%"size%":42,%"contents%":[0,1,1,2,3,5],%"name%":%"foobar%"}"))
|
||||
-- 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)
|
||||
assert ("jo.representation.is_equal (%"{%"size%":42,%"contents%":[0,1,1,2,3,5],%"name%":%"foobar%"}%")", jo.representation.is_equal ("{%"size%":42,%"contents%":[0,1,1,2,3,5],%"name%":%"foobar%"}"))
|
||||
-- JSON representation -> JSON value -> Eiffel value -> JSON value -> JSON representation
|
||||
jrep := "{%"size%":42,%"contents%":[0,1,1,2,3,5],%"name%":%"foobar%"}"
|
||||
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)
|
||||
assert ("jrep.is_equal (jo.representation)", jrep.is_equal (jo.representation))
|
||||
end
|
||||
|
||||
test_json_failed_json_conversion is
|
||||
-- Test converting an Eiffel object to JSON that is based on a class
|
||||
-- for which no JSON converter has been registered.
|
||||
local
|
||||
gv: KL_GOBO_VERSION
|
||||
jv: JSON_VALUE
|
||||
exception: BOOLEAN
|
||||
do
|
||||
if not exception then
|
||||
create gv
|
||||
jv := json.value (gv)
|
||||
else
|
||||
assert ("exceptions.is_developer_exception", exceptions.is_developer_exception)
|
||||
assert ("exceptions.is_developer_exception_of_name", exceptions.is_developer_exception_of_name ("eJSON exception: Failed to convert Eiffel object to a JSON_VALUE: KL_GOBO_VERSION"))
|
||||
end
|
||||
rescue
|
||||
exception := True
|
||||
retry
|
||||
end
|
||||
|
||||
test_json_failed_eiffel_conversion is
|
||||
-- Test converting from a JSON value to an Eiffel object based on a
|
||||
-- class for which no JSON converter has been registered.
|
||||
local
|
||||
gv: KL_GOBO_VERSION
|
||||
jo: JSON_OBJECT
|
||||
exception: BOOLEAN
|
||||
do
|
||||
if not exception then
|
||||
create jo.make
|
||||
gv ?= json.object (jo, "KL_GOBO_VERSION")
|
||||
else
|
||||
assert ("exceptions.is_developer_exception", exceptions.is_developer_exception)
|
||||
assert ("exceptions.is_developer_exception_of_name", exceptions.is_developer_exception_of_name ("eJSON exception: Failed to convert JSON_VALUE to an Eiffel object: JSON_OBJECT -> KL_GOBO_VERSION"))
|
||||
end
|
||||
rescue
|
||||
exception := True
|
||||
retry
|
||||
end
|
||||
|
||||
end -- class TEST_JSON_CORE
|
||||
@@ -0,0 +1,49 @@
|
||||
class TEST_JSON_CUSTOM_CLASSES
|
||||
|
||||
inherit
|
||||
SHARED_EJSON
|
||||
|
||||
TS_TEST_CASE
|
||||
|
||||
create
|
||||
make_default
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make is
|
||||
-- Create test object.
|
||||
do
|
||||
end
|
||||
|
||||
feature -- Test
|
||||
|
||||
test_custom_classes is
|
||||
local
|
||||
bc: BOOK_COLLECTION
|
||||
jbc: JSON_BOOK_CONVERTER
|
||||
jbcc: JSON_BOOK_COLLECTION_CONVERTER
|
||||
jac: JSON_AUTHOR_CONVERTER
|
||||
jo: JSON_OBJECT
|
||||
parser: JSON_PARSER
|
||||
jrep: STRING
|
||||
do
|
||||
create jbc.make
|
||||
json.add_converter (jbc)
|
||||
create jbcc.make
|
||||
json.add_converter (jbcc)
|
||||
create jac.make
|
||||
json.add_converter (jac)
|
||||
jrep := "{%"name%":%"Test collection%",%"books%":[{%"title%":%"eJSON: The Definitive Guide%",%"isbn%":%"123123-413243%",%"author%":{%"name%":%"Foo Bar%"}}]}"
|
||||
create parser.make_parser (jrep)
|
||||
jo := Void
|
||||
jo ?= parser.parse
|
||||
assert ("jo /= Void", jo /= Void)
|
||||
bc := Void
|
||||
bc ?= json.object (jo, "BOOK_COLLECTION")
|
||||
assert ("bc /= Void", bc /= Void)
|
||||
jo ?= json.value (bc)
|
||||
assert ("jo /= Void", jo /= Void)
|
||||
assert ("JSON representation is correct", jo.representation.is_equal ("{%"books%":[{%"title%":%"eJSON: The Definitive Guide%",%"isbn%":%"123123-413243%",%"author%":{%"name%":%"Foo Bar%"}}],%"name%":%"Test collection%"}"))
|
||||
end
|
||||
|
||||
end -- class TEST_JSON_CUSTOM_CLASS
|
||||
27
contrib/library/text/parser/json/test/run_autotest.bat
Normal file
27
contrib/library/text/parser/json/test/run_autotest.bat
Normal file
@@ -0,0 +1,27 @@
|
||||
@echo off
|
||||
setlocal
|
||||
set TMP_EC_SCRIPT_FILENAME=%~dp0.tmp_ec_scripting
|
||||
|
||||
cd %~dp0autotest\test_suite
|
||||
set TMP_EC_CMD=ec -config test_suite-safe.ecf -target test_suite -batch
|
||||
|
||||
echo # Fresh Compilation
|
||||
%TMP_EC_CMD% -batch -clean -freeze -c_compile -project_path . > %~dp0autotest.compile.log 2>&1
|
||||
|
||||
rem Build scripting for freeze + testing
|
||||
rem ------------------------------------
|
||||
rem Testing
|
||||
echo T > %TMP_EC_SCRIPT_FILENAME%
|
||||
rem Execute
|
||||
echo e >> %TMP_EC_SCRIPT_FILENAME%
|
||||
rem Quit
|
||||
echo Q >> %TMP_EC_SCRIPT_FILENAME%
|
||||
|
||||
echo # Execute test_suite
|
||||
type %TMP_EC_SCRIPT_FILENAME% | %TMP_EC_CMD% -loop 1> :NULL 2> %~dp0autotest.testing.log
|
||||
type %~dp0autotest.testing.log
|
||||
|
||||
cd %~dp0
|
||||
|
||||
del %TMP_EC_SCRIPT_FILENAME%
|
||||
endlocal
|
||||
Reference in New Issue
Block a user