Merge branch 'master' of https://github.com/eiffelhub/json
This commit is contained in:
@@ -7,3 +7,4 @@
|
|||||||
*.ecf text
|
*.ecf text
|
||||||
*.bat text
|
*.bat text
|
||||||
*.json text
|
*.json text
|
||||||
|
*.txt text
|
||||||
|
|||||||
2
contrib/library/text/parser/json/.gitignore
vendored
2
contrib/library/text/parser/json/.gitignore
vendored
@@ -1,2 +1,2 @@
|
|||||||
*.swp
|
*.swp
|
||||||
EIFGENs
|
EIFGENs/
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
History file for EJSON
|
History file for EJSON
|
||||||
======================
|
======================
|
||||||
|
|
||||||
team: ""
|
team: ""
|
||||||
date: "2011-07-06"
|
date: "2011-07-06"
|
||||||
revision: "0.3.0"
|
revision: "0.3.0"
|
||||||
|
|
||||||
|
WARNING: THIS FILE IS NOT UP TO DATE
|
||||||
|
|
||||||
|
|
||||||
+++++++++++++++++++++Important Changes since 0.2.0 version++++++++++++++++++++++++++++++++++++++++++++++
|
+++++++++++++++++++++Important Changes since 0.2.0 version++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
Copyright (c) 2010 Javier Velilla and others, http://ejson.origo.ethz.ch
|
Copyright (c) 2010-2014 Javier Velilla, Jocelyn Fiat and others,
|
||||||
|
https://github.com/eiffelhub/json .
|
||||||
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
|||||||
@@ -1,21 +1,26 @@
|
|||||||
Readme file for eJSON
|
Readme file for eJSON
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
team: "Javier Velilla,Jocelyn Fiat, Paul Cohen"
|
team: "Javier Velilla, Jocelyn Fiat"
|
||||||
date: "$Date$"
|
previous contributors: "Paul Cohen"
|
||||||
revision: "$Revision$"
|
date: "2014-nov-17"
|
||||||
|
|
||||||
1. Introduction
|
1. Introduction
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
eJSON stands for Eiffel JSON library and is a small Eiffel library for dealing
|
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
|
with the JSON format. This library provides a JSON parser and visitors,
|
||||||
features Eiffel2JSON and JSON2Eiffel.
|
including a pretty printer.
|
||||||
|
|
||||||
|
The converters part is now obsolete and not recommended (remember: the
|
||||||
|
objective of converters were to provide two basic features Eiffel2JSON and
|
||||||
|
JSON2Eiffel). There will be a new design for converters as a standalone
|
||||||
|
library on top of Current json library.
|
||||||
|
|
||||||
2. Legal stuff
|
2. Legal stuff
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
eJSON is copyrighted by the author Javier Velilla and others. It is licensed
|
eJSON is copyrighted by the author Javier Velilla, Jocelyn Fiat and others. It is licensed
|
||||||
under the MIT License. See the file license.txt in the same directory as this
|
under the MIT License. See the file license.txt in the same directory as this
|
||||||
readme file.
|
readme file.
|
||||||
|
|
||||||
@@ -46,11 +51,9 @@ Currently the only documentation on eJSON is available at:
|
|||||||
|
|
||||||
EJSON requires that you have:
|
EJSON requires that you have:
|
||||||
|
|
||||||
1. Gobo 3.9 installed or later
|
1. One of the following compiler combinations installed:
|
||||||
2. One of the following compiler combinations installed:
|
* ISE Eiffel 13.11 or later.
|
||||||
* ISE Eiffel 6.5 or later.
|
|
||||||
* gec [try to test]
|
* gec [try to test]
|
||||||
* tecomp [try to test]
|
|
||||||
|
|
||||||
eJSON probably works fine with other versions of the above compilers.
|
eJSON probably works fine with other versions of the above compilers.
|
||||||
There are no known platform dependencies (Windows, Linux).
|
There are no known platform dependencies (Windows, Linux).
|
||||||
@@ -58,6 +61,8 @@ There are no known platform dependencies (Windows, Linux).
|
|||||||
To install eJSON simply extract the ejson-X.Y.Z.zip file to some appropriate
|
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
|
place on your hard disk. There are no requirements on environment variables or
|
||||||
registry variables.
|
registry variables.
|
||||||
|
Note eJSON is also delivered within EiffelStudio release, under
|
||||||
|
$ISE_LIBRARY/contrib/library/text/parser/json
|
||||||
|
|
||||||
To verify that everything works you should compile the example programs and/or
|
To verify that everything works you should compile the example programs and/or
|
||||||
the test program.
|
the test program.
|
||||||
@@ -70,18 +75,18 @@ installation.
|
|||||||
|
|
||||||
Directory Description
|
Directory Description
|
||||||
--------- -----------
|
--------- -----------
|
||||||
doc Contains the eJSON.pdf documentation file.
|
doc Contains documentation file.
|
||||||
examples Contains the two example programs.
|
examples Contains example codes.
|
||||||
ejson Contains the actual eJSON library classes.
|
library Contains the actual eJSON library classes.
|
||||||
test Contains a test program for eJSON.
|
test Contains test suite for eJSON.
|
||||||
|
|
||||||
7. Contacting the Team
|
7. Contacting the Team
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
Contact the team:
|
Contact the team:
|
||||||
|
|
||||||
|
https://github.com/eiffelhub/json/issues
|
||||||
Javier Velilla «javier.hector@gmail.com»
|
Javier Velilla «javier.hector@gmail.com»
|
||||||
Paul Cohen «paco@seibostudios.se»
|
|
||||||
Jocelyn Fiat «jfiat@eiffel.com»
|
Jocelyn Fiat «jfiat@eiffel.com»
|
||||||
|
|
||||||
8. Releases
|
8. Releases
|
||||||
@@ -92,6 +97,14 @@ history.txt.
|
|||||||
|
|
||||||
Version Date Description
|
Version Date Description
|
||||||
------- ---- -----------
|
------- ---- -----------
|
||||||
|
0.6.0 2014-11-17 Fixed various issue with parsing string (such as \t and related),
|
||||||
|
Implemented escaping of slash '/' only in case of '</' to avoid
|
||||||
|
potential issue with javascript and </script>
|
||||||
|
Many feature renaming to match Eiffel style and naming convention,
|
||||||
|
kept previous feature as obsolete.
|
||||||
|
Restructured the library to make easy extraction of "converter"
|
||||||
|
classes if needed in the future.
|
||||||
|
Marked converters classes as obsolete.
|
||||||
0.5.0 2013-11-dd Added JSON_ITERATOR, simplified JSON_OBJECT
|
0.5.0 2013-11-dd Added JSON_ITERATOR, simplified JSON_OBJECT
|
||||||
0.4.0 2012-12-12 Updated documentation URI
|
0.4.0 2012-12-12 Updated documentation URI
|
||||||
0.3.0 2011-07-06 JSON Factory Converters
|
0.3.0 2011-07-06 JSON Factory Converters
|
||||||
|
|||||||
295
contrib/library/text/parser/json/doc/user_guide.mediawiki
Normal file
295
contrib/library/text/parser/json/doc/user_guide.mediawiki
Normal file
@@ -0,0 +1,295 @@
|
|||||||
|
== Preface ==
|
||||||
|
|
||||||
|
This document is a living document! As always read and try out the code to understand what's really going on.
|
||||||
|
|
||||||
|
=== About the project ===
|
||||||
|
|
||||||
|
The eJSON project was started by Javier Velilla in 2008. The aim was simply to
|
||||||
|
provide JSON support to Eiffel programmers. A couple of other people have been
|
||||||
|
involved to various extent since the start; Berend de Boer, Jocelyn Fiat and
|
||||||
|
Manu Stapf. In 2009 Paul Cohen joined the project as an active developer and
|
||||||
|
later Jocelyn Fiat.
|
||||||
|
|
||||||
|
The current active maintainers:
|
||||||
|
- Javier Velilla
|
||||||
|
- Jocelyn Fiat
|
||||||
|
|
||||||
|
The formal name of the project is “eJSON”.
|
||||||
|
|
||||||
|
For questions regarding eJSON please contact
|
||||||
|
- <javier.hector at gmail.com>
|
||||||
|
- <jfiat at eiffel.com>
|
||||||
|
- or directly on [https://github.com/eiffelhub/json/issues]
|
||||||
|
|
||||||
|
=== Current version and status ===
|
||||||
|
|
||||||
|
The latest release is 0.6.0. eJSON has been improved and cleaned.
|
||||||
|
The converters are not obsolete.
|
||||||
|
|
||||||
|
|
||||||
|
== Introduction ==
|
||||||
|
|
||||||
|
=== What is JSON? ===
|
||||||
|
|
||||||
|
JSON (JavaScript Object Notation) is a lightweight computer data interchange format. It is a text-based, human-readable format for representing simple data structures and associative arrays (called objects). See the [http://en.wikipedia.org/wiki/JSON Wikipedia article on JSON], [http://www.json.org www.json.org] and [http://www.json.com www.json.com] for more information.
|
||||||
|
|
||||||
|
The JSON format is specified in [http://www.ietf.org/rfc/rfc4627.txt IETF RFC 4627] by Douglas Crockford. The official [http://www.iana.org/assignments/media-types Internet MIME media type] for JSON is "application/json". The recommended file name extension for JSON files is ".json".
|
||||||
|
|
||||||
|
=== Advantages ===
|
||||||
|
|
||||||
|
1. Lightweight data-interchange format.
|
||||||
|
2. Easy for humans to read and write.
|
||||||
|
3. Enables easy integration with AJAX/JavaScript web applications. See the article [http://www.developer.com/lang/jscript/article.php/3596836 Speeding Up AJAX with JSON] for a good short discussion on this subject.
|
||||||
|
4. JSON data structures translate with ease into the native data structures universal to almost all programming languages used today.
|
||||||
|
|
||||||
|
=== Use in Eiffel applications ===
|
||||||
|
|
||||||
|
JSON can be used as a general serialization format for Eiffel objects. As such it could be used as a:
|
||||||
|
|
||||||
|
* Data representation format in REST-based web service applications written in Eiffel.
|
||||||
|
* Serialization format for Eiffel objects in persistence solutions.
|
||||||
|
* File format for configuration files in Eiffel systems.
|
||||||
|
|
||||||
|
=== Prerequisites ===
|
||||||
|
|
||||||
|
eJSON works today with EiffelStudio 13.11
|
||||||
|
There is an optional extension that requires the latest snapshot of the Gobo Eiffel libraries (a working snapshot is distributed with EiffelStudio). The depencencies on Gobo are on Gobo's unicode
|
||||||
|
and regex libraries and for some of the extra features in eJSON, on Gobos structure classes DS_HASH_TABLE and DS_LINKED_LIST.
|
||||||
|
|
||||||
|
eJSON is intended to work with all ECMA compliant Eiffel compilers.
|
||||||
|
|
||||||
|
=== Installation ===
|
||||||
|
|
||||||
|
You can either download a given release and install on your machine or you can get the latest snapshot of the code.
|
||||||
|
To download go to the [http://ejson.origo.ethz.ch/download download page].
|
||||||
|
To get the latest snapshot of the code do:
|
||||||
|
|
||||||
|
: $ git clone https://github.com/eiffelhub/json.git json
|
||||||
|
|
||||||
|
*[https://github.com/eiffelhub/json/releases download page]
|
||||||
|
*[https://github.com/eiffelhub/json github project]
|
||||||
|
|
||||||
|
Note that the latest json release is also delivered with EiffelStudio installation under <code>$ISE_LIBRARY/contrib/library/text/parser/json</code>.
|
||||||
|
|
||||||
|
|
||||||
|
=== Cluster and directory layout ===
|
||||||
|
|
||||||
|
json/
|
||||||
|
library/ (Root directory for eJSON library classes)
|
||||||
|
kernel/ (All classes in this cluster should eventually only depend on ECMA Eiffel and FreeELKS).
|
||||||
|
json_array.e
|
||||||
|
json_boolean.e
|
||||||
|
json_null.e
|
||||||
|
json_number.e
|
||||||
|
json_object.e
|
||||||
|
json_string.e
|
||||||
|
json_value.e
|
||||||
|
parser/
|
||||||
|
json_parser.e
|
||||||
|
json_parser_access.e
|
||||||
|
json_reader.e
|
||||||
|
json_tokens.e
|
||||||
|
utility/
|
||||||
|
file/
|
||||||
|
json_file_reader.e
|
||||||
|
visitor/
|
||||||
|
json_visitor.e
|
||||||
|
json_iterator.e
|
||||||
|
json_pretty_string_visitor.e
|
||||||
|
print_json_visitor.e
|
||||||
|
converters/ (JSON core converter classes !OBSOLETE!)
|
||||||
|
json_converter.e
|
||||||
|
json_hash_table_converter.e
|
||||||
|
json_list_converter.e
|
||||||
|
json_linked_list_converter.e
|
||||||
|
json_arrayed_list_converter.e
|
||||||
|
support/
|
||||||
|
ejson.e
|
||||||
|
shared_ejson.e
|
||||||
|
gobo_converters/ (JSON core converter classes support for GOBO !OBSOLETE!)
|
||||||
|
converters/
|
||||||
|
json_ds_hash_table_converter.e
|
||||||
|
json_ds_linked_list_converter.e
|
||||||
|
shared_gobo_ejson.e
|
||||||
|
test/ (Contains autotest suite)
|
||||||
|
autotest/ (AutoTest based unit test).
|
||||||
|
examples/ (Example code)
|
||||||
|
|
||||||
|
=== Future development ===
|
||||||
|
|
||||||
|
Here is a list of suggestions for future development of eJSON.
|
||||||
|
* Ongoing: Provide a JSON_FACTORY class for easy conversion between arbitrary JSON and Eiffel values.
|
||||||
|
* Ongoing: Provide a mechanism for users to add custom converters between JSON values and user space Eiffel classes.
|
||||||
|
* Ongoing: Implement a full test framework for eJSON.
|
||||||
|
* Suggestion: Investigate performance and improve it if neccessary.
|
||||||
|
* Suggestion: Support JSON references. See [http://www.json.com/2007/10/19/json-referencing-proposal-and-library JSON Referencing Proposal and Library] and [http://www.sitepen.com/blog/2008/06/17/json-referencing-in-dojo JSON referencing in Dojo] for more information.
|
||||||
|
* Suggestion: Support JSON path. See [http://goessner.net/articles/JsonPath JSONPath - XPath for JSON] for more information.
|
||||||
|
* Suggestion: Support JSON schema validation. See [http://json-schema.org JSON Schema Proposal] for more information.
|
||||||
|
* Suggestion: Support RDF JSON serialization. See [http://n2.talis.com/wiki/RDF_JSON_Specification RDF JSON Specification] for more information.
|
||||||
|
* Suggestion: Add support to JSON classes for conversion from Eiffel manifest values. So one can write things like:
|
||||||
|
|
||||||
|
== A simple example ==
|
||||||
|
|
||||||
|
There are two basic approaches to using eJSON; either you use the basic JSON_VALUE classes, converting to and from JSON values to corresponding Eiffel instances or you use the high level eJSON interface class SHARED_EJSON. Of course you can use a mix of both approaches if you find it appropriate!
|
||||||
|
|
||||||
|
Here is an example of how to create a JSON number value from an INTEGER and then obtain the JSON representation for that value.
|
||||||
|
|
||||||
|
simple_example is
|
||||||
|
local
|
||||||
|
i: INTEGER
|
||||||
|
jn: JSON_NUMBER
|
||||||
|
s: STRING
|
||||||
|
do
|
||||||
|
i := 42
|
||||||
|
create jn.make_integer (i)
|
||||||
|
s := jn.representation -- s.is_equal ("42")
|
||||||
|
end
|
||||||
|
|
||||||
|
== Mapping of JSON values to Eiffel values ==
|
||||||
|
|
||||||
|
=== JSON number ===
|
||||||
|
|
||||||
|
JSON numbers are represented by the class JSON_NUMBER. JSON number values can be converted to/from NATURAL_*, INTEGER_* and REAL_64 values. For floating point values REAL_* is used. The complete mapping is as follows:
|
||||||
|
|
||||||
|
JSON number -> Eiffel:
|
||||||
|
* -128 <= n <= +127 -> INTEGER_8
|
||||||
|
* n can't be represented by INTEGER_8 and -32768 <= n <= +32767 -> INTEGER_16
|
||||||
|
* n can't be represented by INTEGER_16 and -2147483648 <= n <= +2147483647 -> INTEGER_32
|
||||||
|
* n can't be represented by INTEGER_32 and -9223372036854775808 <= n <= +9223372036854775807 -> INTEGER_64
|
||||||
|
* n can't be represented by INTEGER_64 and 9223372036854775808 <= n <= 18446744073709551615 -> NATURAL_64
|
||||||
|
* n has fractional dot '.' -> REAL_64.
|
||||||
|
* n -> eJSON exception if number can't be represented by a INTEGER_64, NATURAL_64 or REAL_64.
|
||||||
|
|
||||||
|
Eiffel -> JSON number:
|
||||||
|
* NATURAL_8, NATURAL_16, NATURAL_32, NATURAL_64, NATURAL -> JSON number
|
||||||
|
* INTEGER_8, INTEGER_16, INTEGER_32, INTEGER_64, INTEGER -> JSON number
|
||||||
|
* REAL_32, REAL_64, REAL -> JSON number
|
||||||
|
|
||||||
|
You can use the following creation routines to create JSON_NUMBER instances:
|
||||||
|
|
||||||
|
* JSON_NUMBER.make_integer
|
||||||
|
* JSON_NUMBER.make_real
|
||||||
|
* JSON_NUMBER.make_natural
|
||||||
|
|
||||||
|
eiffel_to_json_number_representation is
|
||||||
|
local
|
||||||
|
i: INTEGER
|
||||||
|
r: REAL
|
||||||
|
jn: JSON_NUMBER
|
||||||
|
do
|
||||||
|
print ("JSON representation of Eiffel INTEGER: '")
|
||||||
|
i := 123
|
||||||
|
create jn.make_integer (i)
|
||||||
|
print (jn.representation)
|
||||||
|
print ("'%N")
|
||||||
|
print ("JSON representation of Eiffel REAL: '")
|
||||||
|
r := 12.3
|
||||||
|
create jn.make_real (r)
|
||||||
|
print (jn.representation)
|
||||||
|
print ("'%N")
|
||||||
|
end
|
||||||
|
|
||||||
|
The output of the above code will be:
|
||||||
|
|
||||||
|
JSON representation of Eiffel INTEGER: '123'
|
||||||
|
JSON representation of Eiffel REAL: '12.300000190734863'
|
||||||
|
|
||||||
|
=== JSON boolean ===
|
||||||
|
|
||||||
|
JSON boolean values are represented by the class JSON_BOOLEAN. The JSON boolean value "true" is converted to/from the BOOLEAN value "True" and the JSON boolean value "false is converted to/from the BOOLEAN value "False".
|
||||||
|
|
||||||
|
eiffel_to_json_boolean_representation is
|
||||||
|
local
|
||||||
|
b: BOOLEAN
|
||||||
|
jb: JSON_BOOLEAN
|
||||||
|
do
|
||||||
|
print ("JSON representation of Eiffel BOOLEAN: '")
|
||||||
|
b := True
|
||||||
|
create jb.make (b)
|
||||||
|
print (jb.representation)
|
||||||
|
print ("'%N")
|
||||||
|
print("JSON representation of Eiffel BOOLEAN: '")
|
||||||
|
b := False
|
||||||
|
create jb.make (b)
|
||||||
|
print (jb.representation)
|
||||||
|
print ("'%N")
|
||||||
|
end
|
||||||
|
|
||||||
|
The output of the above code will be:
|
||||||
|
|
||||||
|
JSON representation of Eiffel BOOLEAN: 'true'
|
||||||
|
JSON representation of Eiffel BOOLEAN: 'false'
|
||||||
|
|
||||||
|
=== JSON string ===
|
||||||
|
|
||||||
|
JSON strings are represented by the class JSON_STRING. JSON string values can be converted to/from STRING_32, STRING and CHARACTER values. The complete mapping is as follows:
|
||||||
|
|
||||||
|
JSON string -> Eiffel:
|
||||||
|
* All JSON strings -> STRING or STRING_32
|
||||||
|
|
||||||
|
Eiffel -> JSON string:
|
||||||
|
* STRING_32 -> JSON string
|
||||||
|
* STRING -> JSON string
|
||||||
|
* CHARACTER -> JSON string
|
||||||
|
|
||||||
|
eiffel_to_json_string_representation is
|
||||||
|
local
|
||||||
|
s: STRING
|
||||||
|
js: JSON_STRING
|
||||||
|
do
|
||||||
|
print ("JSON representation of Eiffel STRING: '")
|
||||||
|
s := "JSON rocks!"
|
||||||
|
create js.make_from_string (s)
|
||||||
|
print (js.representation)
|
||||||
|
print ("'%N")
|
||||||
|
end
|
||||||
|
|
||||||
|
The output of the above code will be:
|
||||||
|
|
||||||
|
JSON representation of Eiffel STRING: '"JSON rocks!"'
|
||||||
|
|
||||||
|
Note: JSON escape unicode characters, as well a other specific characters, to get the unescaped string value, use either 'unescaped_string_8' or 'unescaped_string_32'.
|
||||||
|
|
||||||
|
=== JSON null ===
|
||||||
|
|
||||||
|
The JSON null value is represented by the class JSON_NULL. The JSON null value can be converted to/from Void.
|
||||||
|
|
||||||
|
eiffel_to_json_null_representation is
|
||||||
|
local
|
||||||
|
a: ANY
|
||||||
|
jn: JSON_NULL
|
||||||
|
do
|
||||||
|
create jn
|
||||||
|
print ("JSON representation for JSON null value: '")
|
||||||
|
print (jn.representation)
|
||||||
|
print ("'%N")
|
||||||
|
a := Void
|
||||||
|
if attached {JSON_NULL} json.value (a) as l_jn then -- json from SHARED_EJSON!
|
||||||
|
print ("JSON representation of Eiffel Void reference: '")
|
||||||
|
print (l_jn.representation)
|
||||||
|
print ("'%N")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
The output of the above code will be:
|
||||||
|
|
||||||
|
JSON representation for JSON null value: 'null'
|
||||||
|
JSON representation of Eiffel Void reference: 'null'
|
||||||
|
|
||||||
|
=== JSON array ===
|
||||||
|
|
||||||
|
JSON array is represented by the class JSON_ARRAY.
|
||||||
|
|
||||||
|
=== JSON object ===
|
||||||
|
|
||||||
|
JSON object is represented by the class JSON_OBJECT.
|
||||||
|
|
||||||
|
|
||||||
|
== The eJSON visitor pattern ==
|
||||||
|
|
||||||
|
TBD. See examples.
|
||||||
|
|
||||||
|
== The eJSON file reader class ==
|
||||||
|
|
||||||
|
TBD.
|
||||||
|
|
||||||
83
contrib/library/text/parser/json/examples/basic/basic.e
Normal file
83
contrib/library/text/parser/json/examples/basic/basic.e
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
class
|
||||||
|
BASIC
|
||||||
|
|
||||||
|
create
|
||||||
|
make
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
make
|
||||||
|
-- Initialize `Current'.
|
||||||
|
local
|
||||||
|
parser: JSON_PARSER
|
||||||
|
printer: JSON_PRETTY_STRING_VISITOR
|
||||||
|
s: STRING_32
|
||||||
|
do
|
||||||
|
-- Create parser for content `json_content'
|
||||||
|
create parser.make_with_string (json_content)
|
||||||
|
-- Parse the content
|
||||||
|
parser.parse_content
|
||||||
|
if
|
||||||
|
parser.is_valid and then
|
||||||
|
attached parser.parsed_json_value as jv
|
||||||
|
then
|
||||||
|
-- Json content is valid, and well parser.
|
||||||
|
-- and the parsed json value is `jv'
|
||||||
|
|
||||||
|
-- Let's access the glossary/title value
|
||||||
|
if
|
||||||
|
attached {JSON_OBJECT} jv as j_object and then
|
||||||
|
attached {JSON_OBJECT} j_object.item ("glossary") as j_glossary and then
|
||||||
|
attached {JSON_STRING} j_glossary.item ("title") as j_title
|
||||||
|
then
|
||||||
|
print ("The glossary title is %"" + j_title.unescaped_string_8 + "%".%N")
|
||||||
|
else
|
||||||
|
print ("The glossary title was not found!%N")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Pretty print the parsed JSON
|
||||||
|
create s.make_empty
|
||||||
|
create printer.make (s)
|
||||||
|
jv.accept (printer)
|
||||||
|
print ("The JSON formatted using a pretty printer:%N")
|
||||||
|
print (s)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Status
|
||||||
|
|
||||||
|
feature -- Access
|
||||||
|
|
||||||
|
json_content: STRING = "[
|
||||||
|
{
|
||||||
|
"glossary": {
|
||||||
|
"title": "example glossary",
|
||||||
|
"GlossDiv": {
|
||||||
|
"title": "S",
|
||||||
|
"GlossList": {
|
||||||
|
"GlossEntry": {
|
||||||
|
"ID": "SGML",
|
||||||
|
"SortAs": "SGML",
|
||||||
|
"GlossTerm": "Standard Generalized Markup Language",
|
||||||
|
"Acronym": "SGML",
|
||||||
|
"Abbrev": "ISO 8879:1986",
|
||||||
|
"GlossDef": {
|
||||||
|
"para": "A meta-markup language, used to create markup languages such as DocBook.",
|
||||||
|
"GlossSeeAlso": ["GML", "XML"]
|
||||||
|
},
|
||||||
|
"GlossSee": "markup"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]"
|
||||||
|
|
||||||
|
feature -- Change
|
||||||
|
|
||||||
|
feature {NONE} -- Implementation
|
||||||
|
|
||||||
|
invariant
|
||||||
|
-- invariant_clause: True
|
||||||
|
|
||||||
|
end
|
||||||
10
contrib/library/text/parser/json/examples/basic/basic.ecf
Normal file
10
contrib/library/text/parser/json/examples/basic/basic.ecf
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||||
|
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="basic" uuid="5156B9EE-0436-42A3-BDA1-74710DF05A35">
|
||||||
|
<target name="basic">
|
||||||
|
<root class="BASIC" feature="make"/>
|
||||||
|
<setting name="console_application" value="true"/>
|
||||||
|
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||||
|
<library name="json" location="..\..\library\json-safe.ecf" readonly="false"/>
|
||||||
|
<cluster name="basic" location=".\"/>
|
||||||
|
</target>
|
||||||
|
</system>
|
||||||
@@ -5,9 +5,14 @@ note
|
|||||||
revision: "$Revision$"
|
revision: "$Revision$"
|
||||||
file: "$HeadURL: $"
|
file: "$HeadURL: $"
|
||||||
|
|
||||||
class JSON_ARRAYED_LIST_CONVERTER
|
class
|
||||||
|
JSON_ARRAYED_LIST_CONVERTER
|
||||||
|
|
||||||
|
obsolete
|
||||||
|
"This JSON converter design has issues [Sept/2014]."
|
||||||
|
|
||||||
inherit
|
inherit
|
||||||
|
|
||||||
JSON_LIST_CONVERTER
|
JSON_LIST_CONVERTER
|
||||||
redefine
|
redefine
|
||||||
object
|
object
|
||||||
@@ -27,4 +32,7 @@ feature {NONE} -- Factory
|
|||||||
create Result.make (nb)
|
create Result.make (nb)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
note
|
||||||
|
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
|
||||||
|
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
|
||||||
end -- class JSON_ARRAYED_LIST_CONVERTER
|
end -- class JSON_ARRAYED_LIST_CONVERTER
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
note
|
||||||
|
description: "A JSON converter"
|
||||||
|
author: "Paul Cohen"
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
file: "$HeadURL: $"
|
||||||
|
|
||||||
|
deferred class
|
||||||
|
JSON_CONVERTER
|
||||||
|
|
||||||
|
obsolete
|
||||||
|
"This JSON converter design has issues [Sept/2014]."
|
||||||
|
|
||||||
|
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!
|
||||||
|
|
||||||
|
note
|
||||||
|
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
|
||||||
|
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
|
||||||
|
end
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
note
|
||||||
|
description: "A JSON converter for HASH_TABLE [ANY, HASHABLE]"
|
||||||
|
author: "Paul Cohen"
|
||||||
|
date: "$Date: 2014-01-30 15:27:41 +0100 (jeu., 30 janv. 2014) $"
|
||||||
|
revision: "$Revision: 94128 $"
|
||||||
|
file: "$HeadURL: $"
|
||||||
|
|
||||||
|
class
|
||||||
|
JSON_HASH_TABLE_CONVERTER
|
||||||
|
|
||||||
|
obsolete
|
||||||
|
"This JSON converter design has issues [Sept/2014]."
|
||||||
|
|
||||||
|
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
|
||||||
|
do
|
||||||
|
create Result.make (j.count)
|
||||||
|
across
|
||||||
|
j as ic
|
||||||
|
loop
|
||||||
|
if attached json.object (ic.item, Void) as l_object then
|
||||||
|
if attached {HASHABLE} json.object (ic.key, Void) as h then
|
||||||
|
Result.put (l_object, h)
|
||||||
|
else
|
||||||
|
check
|
||||||
|
key_is_hashable: False
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
check
|
||||||
|
object_attached: False
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
to_json (o: like object): detachable JSON_OBJECT
|
||||||
|
local
|
||||||
|
js: JSON_STRING
|
||||||
|
failed: BOOLEAN
|
||||||
|
do
|
||||||
|
create Result.make
|
||||||
|
across
|
||||||
|
o as c
|
||||||
|
loop
|
||||||
|
if attached {JSON_STRING} json.value (c.key) as l_key then
|
||||||
|
js := l_key
|
||||||
|
else
|
||||||
|
if attached {READABLE_STRING_GENERAL} c.key as s_key then
|
||||||
|
create js.make_from_string_general (s_key)
|
||||||
|
else
|
||||||
|
create js.make_from_string (c.key.out)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if attached json.value (c.item) as jv then
|
||||||
|
Result.put (jv, js)
|
||||||
|
else
|
||||||
|
failed := True
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if failed then
|
||||||
|
Result := Void
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
note
|
||||||
|
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
|
||||||
|
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
|
||||||
|
end -- class JSON_HASH_TABLE_CONVERTER
|
||||||
@@ -5,9 +5,14 @@ note
|
|||||||
revision: "$Revision$"
|
revision: "$Revision$"
|
||||||
file: "$HeadURL: $"
|
file: "$HeadURL: $"
|
||||||
|
|
||||||
class JSON_LINKED_LIST_CONVERTER
|
class
|
||||||
|
JSON_LINKED_LIST_CONVERTER
|
||||||
|
|
||||||
|
obsolete
|
||||||
|
"This JSON converter design has issues [Sept/2014]."
|
||||||
|
|
||||||
inherit
|
inherit
|
||||||
|
|
||||||
JSON_LIST_CONVERTER
|
JSON_LIST_CONVERTER
|
||||||
redefine
|
redefine
|
||||||
object
|
object
|
||||||
@@ -27,4 +32,7 @@ feature {NONE} -- Factory
|
|||||||
create Result.make
|
create Result.make
|
||||||
end
|
end
|
||||||
|
|
||||||
|
note
|
||||||
|
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
|
||||||
|
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
|
||||||
end -- class JSON_LINKED_LIST_CONVERTER
|
end -- class JSON_LINKED_LIST_CONVERTER
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
note
|
||||||
|
description: "A JSON converter for LIST [ANY]"
|
||||||
|
author: "Paul Cohen"
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
file: "$HeadURL: $"
|
||||||
|
|
||||||
|
deferred class
|
||||||
|
JSON_LIST_CONVERTER
|
||||||
|
|
||||||
|
obsolete
|
||||||
|
"This JSON converter design has issues [Sept/2014]."
|
||||||
|
|
||||||
|
inherit
|
||||||
|
|
||||||
|
JSON_CONVERTER
|
||||||
|
|
||||||
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
make
|
||||||
|
do
|
||||||
|
object := new_object (0)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Access
|
||||||
|
|
||||||
|
object: LIST [detachable ANY]
|
||||||
|
|
||||||
|
feature {NONE} -- Factory
|
||||||
|
|
||||||
|
new_object (nb: INTEGER): like object
|
||||||
|
deferred
|
||||||
|
ensure
|
||||||
|
Result /= Void
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Conversion
|
||||||
|
|
||||||
|
from_json (j: attached like to_json): detachable like object
|
||||||
|
local
|
||||||
|
i: INTEGER
|
||||||
|
do
|
||||||
|
Result := new_object (j.count)
|
||||||
|
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): detachable JSON_ARRAY
|
||||||
|
local
|
||||||
|
c: ITERATION_CURSOR [detachable ANY]
|
||||||
|
failed: BOOLEAN
|
||||||
|
do
|
||||||
|
create Result.make (o.count)
|
||||||
|
from
|
||||||
|
c := o.new_cursor
|
||||||
|
until
|
||||||
|
c.after
|
||||||
|
loop
|
||||||
|
if attached json.value (c.item) as jv then
|
||||||
|
Result.add (jv)
|
||||||
|
else
|
||||||
|
failed := True
|
||||||
|
end
|
||||||
|
c.forth
|
||||||
|
end
|
||||||
|
if failed then
|
||||||
|
Result := Void
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
note
|
||||||
|
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
|
||||||
|
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
|
||||||
|
end -- class JSON_ARRAYED_LIST_CONVERTER
|
||||||
@@ -5,9 +5,14 @@ note
|
|||||||
revision: "$Revision$"
|
revision: "$Revision$"
|
||||||
file: "$HeadURL: $"
|
file: "$HeadURL: $"
|
||||||
|
|
||||||
class EJSON
|
class
|
||||||
|
EJSON
|
||||||
|
|
||||||
|
obsolete
|
||||||
|
"This JSON converter design has issues [Sept/2014]."
|
||||||
|
|
||||||
inherit
|
inherit
|
||||||
|
|
||||||
EXCEPTIONS
|
EXCEPTIONS
|
||||||
|
|
||||||
feature -- Access
|
feature -- Access
|
||||||
@@ -25,7 +30,7 @@ feature -- Access
|
|||||||
if an_object = Void then
|
if an_object = Void then
|
||||||
create {JSON_NULL} Result
|
create {JSON_NULL} Result
|
||||||
elseif attached {BOOLEAN} an_object as b then
|
elseif attached {BOOLEAN} an_object as b then
|
||||||
create {JSON_BOOLEAN} Result.make_boolean (b)
|
create {JSON_BOOLEAN} Result.make (b)
|
||||||
elseif attached {INTEGER_8} an_object as i8 then
|
elseif attached {INTEGER_8} an_object as i8 then
|
||||||
create {JSON_NUMBER} Result.make_integer (i8)
|
create {JSON_NUMBER} Result.make_integer (i8)
|
||||||
elseif attached {INTEGER_16} an_object as i16 then
|
elseif attached {INTEGER_16} an_object as i16 then
|
||||||
@@ -47,7 +52,7 @@ feature -- Access
|
|||||||
elseif attached {REAL_64} an_object as r64 then
|
elseif attached {REAL_64} an_object as r64 then
|
||||||
create {JSON_NUMBER} Result.make_real (r64)
|
create {JSON_NUMBER} Result.make_real (r64)
|
||||||
elseif attached {ARRAY [detachable ANY]} an_object as a then
|
elseif attached {ARRAY [detachable ANY]} an_object as a then
|
||||||
create ja.make_array
|
create ja.make (a.count)
|
||||||
from
|
from
|
||||||
i := a.lower
|
i := a.lower
|
||||||
until
|
until
|
||||||
@@ -56,22 +61,22 @@ feature -- Access
|
|||||||
if attached value (a @ i) as v then
|
if attached value (a @ i) as v then
|
||||||
ja.add (v)
|
ja.add (v)
|
||||||
else
|
else
|
||||||
check value_attached: False end
|
check
|
||||||
|
value_attached: False
|
||||||
|
end
|
||||||
end
|
end
|
||||||
i := i + 1
|
i := i + 1
|
||||||
end
|
end
|
||||||
Result := ja
|
Result := ja
|
||||||
elseif attached {CHARACTER_8} an_object as c8 then
|
elseif attached {CHARACTER_8} an_object as c8 then
|
||||||
create {JSON_STRING} Result.make_json (c8.out)
|
create {JSON_STRING} Result.make_from_string (c8.out)
|
||||||
elseif attached {CHARACTER_32} an_object as c32 then
|
elseif attached {CHARACTER_32} an_object as c32 then
|
||||||
create {JSON_STRING} Result.make_json (c32.out)
|
create {JSON_STRING} Result.make_from_string_32 (create {STRING_32}.make_filled (c32, 1))
|
||||||
|
|
||||||
elseif attached {STRING_8} an_object as s8 then
|
elseif attached {STRING_8} an_object as s8 then
|
||||||
create {JSON_STRING} Result.make_json (s8)
|
create {JSON_STRING} Result.make_from_string (s8)
|
||||||
elseif attached {STRING_32} an_object as s32 then
|
elseif attached {STRING_32} an_object as s32 then
|
||||||
create {JSON_STRING} Result.make_json_from_string_32 (s32)
|
create {JSON_STRING} Result.make_from_string_32 (s32)
|
||||||
end
|
end
|
||||||
|
|
||||||
if Result = Void then
|
if Result = Void then
|
||||||
-- Now check the converters
|
-- Now check the converters
|
||||||
if an_object /= Void and then attached converter_for (an_object) as jc then
|
if an_object /= Void and then attached converter_for (an_object) as jc then
|
||||||
@@ -160,12 +165,10 @@ feature -- Access
|
|||||||
-- "eJSON exception" if unable to convert value.
|
-- "eJSON exception" if unable to convert value.
|
||||||
require
|
require
|
||||||
json_not_void: json /= Void
|
json_not_void: json /= Void
|
||||||
local
|
|
||||||
jv: detachable JSON_VALUE
|
|
||||||
do
|
do
|
||||||
json_parser.set_representation (json)
|
json_parser.set_representation (json)
|
||||||
jv := json_parser.parse
|
json_parser.parse_content
|
||||||
if jv /= Void then
|
if json_parser.is_valid and then attached json_parser.parsed_json_value as jv then
|
||||||
Result := object (jv, base_class)
|
Result := object (jv, base_class)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -190,8 +193,8 @@ feature -- Access
|
|||||||
js_key, js_value: JSON_STRING
|
js_key, js_value: JSON_STRING
|
||||||
do
|
do
|
||||||
create Result.make
|
create Result.make
|
||||||
create js_key.make_json ("$ref")
|
create js_key.make_from_string ("$ref")
|
||||||
create js_value.make_json (s)
|
create js_value.make_from_string (s)
|
||||||
Result.put (js_value, js_key)
|
Result.put (js_value, js_key)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -205,7 +208,7 @@ feature -- Access
|
|||||||
local
|
local
|
||||||
c: ITERATION_CURSOR [STRING]
|
c: ITERATION_CURSOR [STRING]
|
||||||
do
|
do
|
||||||
create Result.make_array
|
create Result.make (l.count)
|
||||||
from
|
from
|
||||||
c := l.new_cursor
|
c := l.new_cursor
|
||||||
until
|
until
|
||||||
@@ -262,7 +265,10 @@ feature {NONE} -- Implementation (JSON parser)
|
|||||||
|
|
||||||
json_parser: JSON_PARSER
|
json_parser: JSON_PARSER
|
||||||
once
|
once
|
||||||
create Result.make_parser ("")
|
create Result.make_with_string ("{}")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
note
|
||||||
|
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
|
||||||
|
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
|
||||||
end -- class EJSON
|
end -- class EJSON
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
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: 89185 $"
|
||||||
|
file: "$HeadURL: $"
|
||||||
|
|
||||||
|
class
|
||||||
|
SHARED_EJSON
|
||||||
|
|
||||||
|
obsolete
|
||||||
|
"This JSON converter design has issues [Sept/2014]."
|
||||||
|
|
||||||
|
feature -- Access
|
||||||
|
|
||||||
|
json: EJSON
|
||||||
|
-- A shared EJSON instance with default converters for
|
||||||
|
--LINKED_LIST [ANY] and HASH_TABLE [ANY, HASHABLE]
|
||||||
|
local
|
||||||
|
jalc: JSON_ARRAYED_LIST_CONVERTER
|
||||||
|
jllc: JSON_LINKED_LIST_CONVERTER
|
||||||
|
jhtc: JSON_HASH_TABLE_CONVERTER
|
||||||
|
once
|
||||||
|
create Result
|
||||||
|
create jalc.make
|
||||||
|
Result.add_converter (jalc)
|
||||||
|
create jllc.make
|
||||||
|
Result.add_converter (jllc)
|
||||||
|
create jhtc.make
|
||||||
|
Result.add_converter (jhtc)
|
||||||
|
end
|
||||||
|
|
||||||
|
note
|
||||||
|
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
|
||||||
|
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
|
||||||
|
|
||||||
|
end -- class SHARED_EJSON
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
note
|
|
||||||
description: "Objects that ..."
|
|
||||||
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_with_name (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
|
|
||||||
@@ -9,20 +9,13 @@
|
|||||||
</file_rule>
|
</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">
|
<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/>
|
<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>
|
</option>
|
||||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf" readonly="true"/>
|
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf" readonly="true"/>
|
||||||
<cluster name="json" location=".\" recursive="true">
|
<cluster name="json" location=".\">
|
||||||
<file_rule>
|
<cluster name="json_kernel" location=".\kernel\" recursive="true"/>
|
||||||
<exclude>^/gobo$</exclude>
|
<cluster name="json_parser" location=".\parser\" recursive="true"/>
|
||||||
<exclude>^/kernel$</exclude>
|
<cluster name="json_utility" location=".\utility\" recursive="true"/>
|
||||||
<exclude>^/extras$</exclude>
|
|
||||||
</file_rule>
|
|
||||||
<cluster name="kernel" location=".\kernel\" recursive="true"/>
|
|
||||||
<cluster name="extras" location=".\extras\" recursive="true"/>
|
|
||||||
</cluster>
|
</cluster>
|
||||||
|
<cluster name="json_converter" location=".\converter\" recursive="true"/>
|
||||||
</target>
|
</target>
|
||||||
</system>
|
</system>
|
||||||
|
|||||||
@@ -9,20 +9,13 @@
|
|||||||
</file_rule>
|
</file_rule>
|
||||||
<option trace="false" profile="false" debug="false" warning="true" full_class_checking="true" void_safety="none" syntax="standard" namespace="EJSON.Library">
|
<option trace="false" profile="false" debug="false" warning="true" full_class_checking="true" void_safety="none" syntax="standard" namespace="EJSON.Library">
|
||||||
<assertions/>
|
<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>
|
</option>
|
||||||
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf" readonly="true"/>
|
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf" readonly="true"/>
|
||||||
<cluster name="json" location=".\" recursive="true">
|
<cluster name="json" location=".\" >
|
||||||
<file_rule>
|
<cluster name="json_kernel" location=".\kernel" recursive="true"/>
|
||||||
<exclude>^/gobo$</exclude>
|
<cluster name="json_parser" location=".\parser" recursive="true"/>
|
||||||
<exclude>^/kernel$</exclude>
|
<cluster name="json_utility" location=".\utility" recursive="true"/>
|
||||||
<exclude>^/extras$</exclude>
|
|
||||||
</file_rule>
|
|
||||||
<cluster name="kernel" location=".\kernel\" recursive="true"/>
|
|
||||||
<cluster name="extras" location=".\extras\" recursive="true"/>
|
|
||||||
</cluster>
|
</cluster>
|
||||||
|
<cluster name="json_converter" location=".\converter" recursive="true"/>
|
||||||
</target>
|
</target>
|
||||||
</system>
|
</system>
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
@@ -12,6 +12,6 @@
|
|||||||
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf" readonly="true"/>
|
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf" readonly="true"/>
|
||||||
<library name="json" location="json.ecf" readonly="true"/>
|
<library name="json" location="json.ecf" readonly="true"/>
|
||||||
<library name="gobo_structure" location="$ISE_LIBRARY\library\gobo\gobo_structure.ecf"/>
|
<library name="gobo_structure" location="$ISE_LIBRARY\library\gobo\gobo_structure.ecf"/>
|
||||||
<cluster name="json_gobo" location=".\gobo" recursive="true" />
|
<cluster name="json_gobo_converter" location=".\gobo_converter" recursive="true" />
|
||||||
</target>
|
</target>
|
||||||
</system>
|
</system>
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
note
|
|
||||||
description: "A JSON converter for HASH_TABLE [ANY, HASHABLE]"
|
|
||||||
author: "Paul Cohen"
|
|
||||||
date: "$Date: 2014-01-30 15:27:41 +0100 (jeu., 30 janv. 2014) $"
|
|
||||||
revision: "$Revision: 94128 $"
|
|
||||||
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
|
|
||||||
do
|
|
||||||
create Result.make (j.count)
|
|
||||||
across
|
|
||||||
j as ic
|
|
||||||
loop
|
|
||||||
if attached json.object (ic.item, Void) as l_object then
|
|
||||||
if attached {HASHABLE} json.object (ic.key, Void) as h then
|
|
||||||
Result.put (l_object, h)
|
|
||||||
else
|
|
||||||
check key_is_hashable: False end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
check object_attached: False end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
to_json (o: like object): detachable JSON_OBJECT
|
|
||||||
local
|
|
||||||
c: HASH_TABLE_ITERATION_CURSOR [ANY, HASHABLE]
|
|
||||||
js: JSON_STRING
|
|
||||||
failed: BOOLEAN
|
|
||||||
do
|
|
||||||
create Result.make
|
|
||||||
from
|
|
||||||
c := o.new_cursor
|
|
||||||
until
|
|
||||||
c.after
|
|
||||||
loop
|
|
||||||
if attached {JSON_STRING} json.value (c.key) as l_key then
|
|
||||||
js := l_key
|
|
||||||
else
|
|
||||||
create js.make_json (c.key.out)
|
|
||||||
end
|
|
||||||
if attached json.value (c.item) as jv 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
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
note
|
|
||||||
description: "A JSON converter for LIST [ANY]"
|
|
||||||
author: "Paul Cohen"
|
|
||||||
date: "$Date$"
|
|
||||||
revision: "$Revision$"
|
|
||||||
file: "$HeadURL: $"
|
|
||||||
|
|
||||||
deferred class JSON_LIST_CONVERTER
|
|
||||||
|
|
||||||
inherit
|
|
||||||
JSON_CONVERTER
|
|
||||||
|
|
||||||
feature {NONE} -- Initialization
|
|
||||||
|
|
||||||
make
|
|
||||||
do
|
|
||||||
object := new_object (0)
|
|
||||||
end
|
|
||||||
|
|
||||||
feature -- Access
|
|
||||||
|
|
||||||
object: LIST [detachable ANY]
|
|
||||||
|
|
||||||
feature {NONE} -- Factory
|
|
||||||
|
|
||||||
new_object (nb: INTEGER): like object
|
|
||||||
deferred
|
|
||||||
ensure
|
|
||||||
Result /= Void
|
|
||||||
end
|
|
||||||
|
|
||||||
feature -- Conversion
|
|
||||||
|
|
||||||
from_json (j: attached like to_json): detachable like object
|
|
||||||
local
|
|
||||||
i: INTEGER
|
|
||||||
do
|
|
||||||
Result := new_object (j.count)
|
|
||||||
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): detachable JSON_ARRAY
|
|
||||||
local
|
|
||||||
c: ITERATION_CURSOR [detachable ANY]
|
|
||||||
jv: detachable JSON_VALUE
|
|
||||||
failed: BOOLEAN
|
|
||||||
do
|
|
||||||
create Result.make_array
|
|
||||||
from
|
|
||||||
c := o.new_cursor
|
|
||||||
until
|
|
||||||
c.after
|
|
||||||
loop
|
|
||||||
jv := json.value (c.item)
|
|
||||||
if jv /= Void then
|
|
||||||
Result.add (jv)
|
|
||||||
else
|
|
||||||
failed := True
|
|
||||||
end
|
|
||||||
c.forth
|
|
||||||
end
|
|
||||||
if failed then
|
|
||||||
Result := Void
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end -- class JSON_ARRAYED_LIST_CONVERTER
|
|
||||||
@@ -7,15 +7,15 @@ note
|
|||||||
[]
|
[]
|
||||||
[elements]
|
[elements]
|
||||||
]"
|
]"
|
||||||
|
author: "$Author$"
|
||||||
author: "Javier Velilla"
|
date: "$date$"
|
||||||
date: "2008/08/24"
|
revision: "$Revision$"
|
||||||
revision: "Revision 0.1"
|
|
||||||
|
|
||||||
class
|
class
|
||||||
JSON_ARRAY
|
JSON_ARRAY
|
||||||
|
|
||||||
inherit
|
inherit
|
||||||
|
|
||||||
JSON_VALUE
|
JSON_VALUE
|
||||||
|
|
||||||
ITERABLE [JSON_VALUE]
|
ITERABLE [JSON_VALUE]
|
||||||
@@ -23,14 +23,29 @@ inherit
|
|||||||
DEBUG_OUTPUT
|
DEBUG_OUTPUT
|
||||||
|
|
||||||
create
|
create
|
||||||
|
make, make_empty,
|
||||||
make_array
|
make_array
|
||||||
|
|
||||||
feature {NONE} -- Initialization
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
make (nb: INTEGER)
|
||||||
|
-- Initialize JSON array with capacity of `nb' items.
|
||||||
|
do
|
||||||
|
create items.make (nb)
|
||||||
|
end
|
||||||
|
|
||||||
|
make_empty
|
||||||
|
-- Initialize empty JSON array.
|
||||||
|
do
|
||||||
|
make (0)
|
||||||
|
end
|
||||||
|
|
||||||
make_array
|
make_array
|
||||||
-- Initialize JSON Array
|
-- Initialize JSON Array
|
||||||
|
obsolete
|
||||||
|
"Use `make' Sept/2014"
|
||||||
do
|
do
|
||||||
create values.make (10)
|
make (10)
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Access
|
feature -- Access
|
||||||
@@ -40,24 +55,19 @@ feature -- Access
|
|||||||
require
|
require
|
||||||
is_valid_index: valid_index (i)
|
is_valid_index: valid_index (i)
|
||||||
do
|
do
|
||||||
Result := values.i_th (i)
|
Result := items.i_th (i)
|
||||||
end
|
end
|
||||||
|
|
||||||
representation: STRING
|
representation: STRING
|
||||||
local
|
|
||||||
i: INTEGER
|
|
||||||
do
|
do
|
||||||
Result := "["
|
Result := "["
|
||||||
from
|
across
|
||||||
i := 1
|
items as ic
|
||||||
until
|
|
||||||
i > count
|
|
||||||
loop
|
loop
|
||||||
Result.append (i_th (i).representation)
|
if Result.count > 1 then
|
||||||
i := i + 1
|
|
||||||
if i <= count then
|
|
||||||
Result.append_character (',')
|
Result.append_character (',')
|
||||||
end
|
end
|
||||||
|
Result.append (ic.item.representation)
|
||||||
end
|
end
|
||||||
Result.append_character (']')
|
Result.append_character (']')
|
||||||
end
|
end
|
||||||
@@ -76,7 +86,7 @@ feature -- Access
|
|||||||
new_cursor: ITERATION_CURSOR [JSON_VALUE]
|
new_cursor: ITERATION_CURSOR [JSON_VALUE]
|
||||||
-- Fresh cursor associated with current structure
|
-- Fresh cursor associated with current structure
|
||||||
do
|
do
|
||||||
Result := values.new_cursor
|
Result := items.new_cursor
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Mesurement
|
feature -- Mesurement
|
||||||
@@ -84,7 +94,7 @@ feature -- Mesurement
|
|||||||
count: INTEGER
|
count: INTEGER
|
||||||
-- Number of items.
|
-- Number of items.
|
||||||
do
|
do
|
||||||
Result := values.count
|
Result := items.count
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Status report
|
feature -- Status report
|
||||||
@@ -101,20 +111,18 @@ feature -- Change Element
|
|||||||
require
|
require
|
||||||
v_not_void: v /= Void
|
v_not_void: v /= Void
|
||||||
do
|
do
|
||||||
values.put_front (v)
|
items.put_front (v)
|
||||||
ensure
|
ensure
|
||||||
has_new_value: old values.count + 1 = values.count and
|
has_new_value: old items.count + 1 = items.count and items.first = v
|
||||||
values.first = v
|
|
||||||
end
|
end
|
||||||
|
|
||||||
add, extend (v: JSON_VALUE)
|
add, extend (v: JSON_VALUE)
|
||||||
require
|
require
|
||||||
v_not_void: v /= Void
|
v_not_void: v /= Void
|
||||||
do
|
do
|
||||||
values.extend (v)
|
items.extend (v)
|
||||||
ensure
|
ensure
|
||||||
has_new_value: old values.count + 1 = values.count and
|
has_new_value: old items.count + 1 = items.count and items.has (v)
|
||||||
values.has (v)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
prune_all (v: JSON_VALUE)
|
prune_all (v: JSON_VALUE)
|
||||||
@@ -122,41 +130,44 @@ feature -- Change Element
|
|||||||
require
|
require
|
||||||
v_not_void: v /= Void
|
v_not_void: v /= Void
|
||||||
do
|
do
|
||||||
values.prune_all (v)
|
items.prune_all (v)
|
||||||
ensure
|
ensure
|
||||||
not_has_new_value: not values.has (v)
|
not_has_new_value: not items.has (v)
|
||||||
end
|
end
|
||||||
|
|
||||||
wipe_out
|
wipe_out
|
||||||
-- Remove all items.
|
-- Remove all items.
|
||||||
do
|
do
|
||||||
values.wipe_out
|
items.wipe_out
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Report
|
feature -- Report
|
||||||
|
|
||||||
hash_code: INTEGER
|
hash_code: INTEGER
|
||||||
-- Hash code value
|
-- Hash code value
|
||||||
|
local
|
||||||
|
l_started: BOOLEAN
|
||||||
do
|
do
|
||||||
from
|
across
|
||||||
values.start
|
items as ic
|
||||||
Result := values.item.hash_code
|
|
||||||
until
|
|
||||||
values.off
|
|
||||||
loop
|
loop
|
||||||
Result:= ((Result \\ 8388593) |<< 8) + values.item.hash_code
|
if l_started then
|
||||||
values.forth
|
Result := ((Result \\ 8388593) |<< 8) + ic.item.hash_code
|
||||||
|
else
|
||||||
|
Result := ic.item.hash_code
|
||||||
|
l_started := True
|
||||||
end
|
end
|
||||||
Result := Result \\ values.count
|
end
|
||||||
|
Result := Result \\ items.count
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Conversion
|
feature -- Conversion
|
||||||
|
|
||||||
array_representation: ARRAYED_LIST [JSON_VALUE]
|
array_representation: ARRAYED_LIST [JSON_VALUE]
|
||||||
-- Representation as a sequences of values
|
-- Representation as a sequences of values.
|
||||||
-- be careful, modifying the return object may have impact on the original JSON_ARRAY object
|
-- be careful, modifying the return object may have impact on the original JSON_ARRAY object.
|
||||||
do
|
do
|
||||||
Result := values
|
Result := items
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Status report
|
feature -- Status report
|
||||||
@@ -169,10 +180,13 @@ feature -- Status report
|
|||||||
|
|
||||||
feature {NONE} -- Implementation
|
feature {NONE} -- Implementation
|
||||||
|
|
||||||
values: ARRAYED_LIST [JSON_VALUE]
|
items: ARRAYED_LIST [JSON_VALUE]
|
||||||
-- Value container
|
-- Value container
|
||||||
|
|
||||||
invariant
|
invariant
|
||||||
value_not_void: values /= Void
|
items_not_void: items /= Void
|
||||||
|
|
||||||
|
note
|
||||||
|
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
|
||||||
|
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,24 +1,47 @@
|
|||||||
note
|
note
|
||||||
description: "JSON Truth values"
|
description: "JSON Boolean values"
|
||||||
author: "Javier Velilla"
|
author: "$Author$"
|
||||||
date: "2008/08/24"
|
date: "$Date$"
|
||||||
revision: "Revision 0.1"
|
revision: "$Revision$"
|
||||||
|
|
||||||
class
|
class
|
||||||
JSON_BOOLEAN
|
JSON_BOOLEAN
|
||||||
|
|
||||||
inherit
|
inherit
|
||||||
|
|
||||||
JSON_VALUE
|
JSON_VALUE
|
||||||
|
|
||||||
create
|
create
|
||||||
|
make,
|
||||||
|
make_true, make_false,
|
||||||
make_boolean
|
make_boolean
|
||||||
|
|
||||||
feature {NONE} -- Initialization
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
make_boolean (an_item: BOOLEAN)
|
make (a_value: BOOLEAN)
|
||||||
--Initialize.
|
-- Initialize Current JSON boolean with `a_boolean'.
|
||||||
do
|
do
|
||||||
item := an_item
|
item := a_value
|
||||||
|
end
|
||||||
|
|
||||||
|
make_true
|
||||||
|
-- Initialize Current JSON boolean with True.
|
||||||
|
do
|
||||||
|
make (True)
|
||||||
|
end
|
||||||
|
|
||||||
|
make_false
|
||||||
|
-- Initialize Current JSON boolean with False.
|
||||||
|
do
|
||||||
|
make (False)
|
||||||
|
end
|
||||||
|
|
||||||
|
make_boolean (a_item: BOOLEAN)
|
||||||
|
-- Initialize.
|
||||||
|
obsolete
|
||||||
|
"Use `make' Sept/2014"
|
||||||
|
do
|
||||||
|
make (a_item)
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Access
|
feature -- Access
|
||||||
@@ -58,4 +81,7 @@ feature -- Status report
|
|||||||
Result := item.out
|
Result := item.out
|
||||||
end
|
end
|
||||||
|
|
||||||
|
note
|
||||||
|
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
|
||||||
|
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ class
|
|||||||
JSON_NULL
|
JSON_NULL
|
||||||
|
|
||||||
inherit
|
inherit
|
||||||
|
|
||||||
JSON_VALUE
|
JSON_VALUE
|
||||||
|
|
||||||
feature --Access
|
feature --Access
|
||||||
@@ -44,4 +45,7 @@ feature {NONE}-- Implementation
|
|||||||
|
|
||||||
null_value: STRING = "null"
|
null_value: STRING = "null"
|
||||||
|
|
||||||
|
note
|
||||||
|
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
|
||||||
|
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,24 +1,22 @@
|
|||||||
note
|
note
|
||||||
|
|
||||||
description: "JSON Numbers, octal and hexadecimal formats are not used."
|
description: "JSON Numbers, octal and hexadecimal formats are not used."
|
||||||
author: "Javier Velilla"
|
author: "$Author$"
|
||||||
date: "2008/08/24"
|
date: "$Date$"
|
||||||
revision: "Revision 0.1"
|
revision: "$Revision$"
|
||||||
license: "MIT (see http://www.opensource.org/licenses/mit-license.php)"
|
license: "MIT (see http://www.opensource.org/licenses/mit-license.php)"
|
||||||
|
|
||||||
class
|
class
|
||||||
JSON_NUMBER
|
JSON_NUMBER
|
||||||
|
|
||||||
inherit
|
inherit
|
||||||
|
|
||||||
JSON_VALUE
|
JSON_VALUE
|
||||||
redefine
|
redefine
|
||||||
is_equal
|
is_equal
|
||||||
end
|
end
|
||||||
|
|
||||||
create
|
create
|
||||||
make_integer,
|
make_integer, make_natural, make_real
|
||||||
make_natural,
|
|
||||||
make_real
|
|
||||||
|
|
||||||
feature {NONE} -- initialization
|
feature {NONE} -- initialization
|
||||||
|
|
||||||
@@ -26,21 +24,21 @@ feature {NONE} -- initialization
|
|||||||
-- Initialize an instance of JSON_NUMBER from the integer value of `an_argument'.
|
-- Initialize an instance of JSON_NUMBER from the integer value of `an_argument'.
|
||||||
do
|
do
|
||||||
item := an_argument.out
|
item := an_argument.out
|
||||||
numeric_type := INTEGER_TYPE
|
numeric_type := integer_type
|
||||||
end
|
end
|
||||||
|
|
||||||
make_natural (an_argument: NATURAL_64)
|
make_natural (an_argument: NATURAL_64)
|
||||||
-- Initialize an instance of JSON_NUMBER from the unsigned integer value of `an_argument'.
|
-- Initialize an instance of JSON_NUMBER from the unsigned integer value of `an_argument'.
|
||||||
do
|
do
|
||||||
item := an_argument.out
|
item := an_argument.out
|
||||||
numeric_type := NATURAL_TYPE
|
numeric_type := natural_type
|
||||||
end
|
end
|
||||||
|
|
||||||
make_real (an_argument: DOUBLE)
|
make_real (an_argument: REAL_64)
|
||||||
-- Initialize an instance of JSON_NUMBER from the floating point value of `an_argument'.
|
-- Initialize an instance of JSON_NUMBER from the floating point value of `an_argument'.
|
||||||
do
|
do
|
||||||
item := an_argument.out
|
item := an_argument.out
|
||||||
numeric_type := DOUBLE_TYPE
|
numeric_type := double_type
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Access
|
feature -- Access
|
||||||
@@ -48,6 +46,9 @@ feature -- Access
|
|||||||
item: STRING
|
item: STRING
|
||||||
-- Content
|
-- Content
|
||||||
|
|
||||||
|
numeric_type: INTEGER
|
||||||
|
-- Type of number (integer, natural or real).
|
||||||
|
|
||||||
hash_code: INTEGER
|
hash_code: INTEGER
|
||||||
--Hash code value
|
--Hash code value
|
||||||
do
|
do
|
||||||
@@ -59,6 +60,52 @@ feature -- Access
|
|||||||
Result := item
|
Result := item
|
||||||
end
|
end
|
||||||
|
|
||||||
|
feature -- Conversion
|
||||||
|
|
||||||
|
integer_64_item: INTEGER_64
|
||||||
|
-- Associated integer value.
|
||||||
|
require
|
||||||
|
is_integer: is_integer
|
||||||
|
do
|
||||||
|
Result := item.to_integer_64
|
||||||
|
end
|
||||||
|
|
||||||
|
natural_64_item: NATURAL_64
|
||||||
|
-- Associated natural value.
|
||||||
|
require
|
||||||
|
is_natural: is_natural
|
||||||
|
do
|
||||||
|
Result := item.to_natural_64
|
||||||
|
end
|
||||||
|
|
||||||
|
double_item, real_64_item: REAL_64
|
||||||
|
-- Associated real value.
|
||||||
|
require
|
||||||
|
is_real: is_real
|
||||||
|
do
|
||||||
|
Result := item.to_real_64
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Status report
|
||||||
|
|
||||||
|
is_integer: BOOLEAN
|
||||||
|
-- Is Current an integer number?
|
||||||
|
do
|
||||||
|
Result := numeric_type = integer_type
|
||||||
|
end
|
||||||
|
|
||||||
|
is_natural: BOOLEAN
|
||||||
|
-- Is Current a natural number?
|
||||||
|
do
|
||||||
|
Result := numeric_type = natural_type
|
||||||
|
end
|
||||||
|
|
||||||
|
is_double, is_real: BOOLEAN
|
||||||
|
-- Is Current a real number?
|
||||||
|
do
|
||||||
|
Result := numeric_type = real_type
|
||||||
|
end
|
||||||
|
|
||||||
feature -- Visitor pattern
|
feature -- Visitor pattern
|
||||||
|
|
||||||
accept (a_visitor: JSON_VISITOR)
|
accept (a_visitor: JSON_VISITOR)
|
||||||
@@ -87,13 +134,16 @@ feature -- Status report
|
|||||||
|
|
||||||
feature -- Implementation
|
feature -- Implementation
|
||||||
|
|
||||||
INTEGER_TYPE: INTEGER = 1
|
integer_type: INTEGER = 1
|
||||||
DOUBLE_TYPE: INTEGER = 2
|
|
||||||
NATURAL_TYPE: INTEGER = 3
|
|
||||||
|
|
||||||
numeric_type: INTEGER
|
double_type, real_type: INTEGER = 2
|
||||||
|
|
||||||
|
natural_type: INTEGER = 3
|
||||||
|
|
||||||
invariant
|
invariant
|
||||||
item_not_void: item /= Void
|
item_not_void: item /= Void
|
||||||
|
|
||||||
|
note
|
||||||
|
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
|
||||||
|
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,25 +1,24 @@
|
|||||||
note
|
note
|
||||||
|
|
||||||
description: "[
|
description: "[
|
||||||
An JSON_OBJECT represent an object in JSON.
|
An JSON_OBJECT represent an object in JSON.
|
||||||
An object is an unordered set of name/value pairs
|
An object is an unordered set of name/value pairs
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
object
|
object
|
||||||
{}
|
{}
|
||||||
|
{"key": value}
|
||||||
{"key": "value"}
|
{"key": "value"}
|
||||||
|
|
||||||
]"
|
]"
|
||||||
author: "Javier Velilla"
|
author: "$Author$"
|
||||||
date: "2008/08/24"
|
date: "$Date$"
|
||||||
revision: "Revision 0.1"
|
revision: "$Revision$"
|
||||||
license: "MIT (see http://www.opensource.org/licenses/mit-license.php)"
|
license: "MIT (see http://www.opensource.org/licenses/mit-license.php)"
|
||||||
|
|
||||||
class
|
class
|
||||||
JSON_OBJECT
|
JSON_OBJECT
|
||||||
|
|
||||||
inherit
|
inherit
|
||||||
|
|
||||||
JSON_VALUE
|
JSON_VALUE
|
||||||
|
|
||||||
TABLE_ITERABLE [JSON_VALUE, JSON_STRING]
|
TABLE_ITERABLE [JSON_VALUE, JSON_STRING]
|
||||||
@@ -27,214 +26,226 @@ inherit
|
|||||||
DEBUG_OUTPUT
|
DEBUG_OUTPUT
|
||||||
|
|
||||||
create
|
create
|
||||||
make
|
make_empty, make_with_capacity, make
|
||||||
|
|
||||||
feature {NONE} -- Initialization
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
make
|
make_with_capacity (nb: INTEGER)
|
||||||
-- Initialize
|
-- Initialize with a capacity of `nb' items.
|
||||||
do
|
do
|
||||||
create object.make (10)
|
create items.make (nb)
|
||||||
|
end
|
||||||
|
|
||||||
|
make_empty
|
||||||
|
-- Initialize as empty object.
|
||||||
|
do
|
||||||
|
make_with_capacity (0)
|
||||||
|
end
|
||||||
|
|
||||||
|
make
|
||||||
|
-- Initialize with default capacity.
|
||||||
|
do
|
||||||
|
make_with_capacity (3)
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Change Element
|
feature -- Change Element
|
||||||
|
|
||||||
put (value: detachable JSON_VALUE; key: JSON_STRING)
|
put (a_value: detachable JSON_VALUE; a_key: JSON_STRING)
|
||||||
-- Assuming there is no item of key `key',
|
-- Assuming there is no item of key `a_key',
|
||||||
-- insert `value' with `key'.
|
-- insert `a_value' with `a_key'.
|
||||||
require
|
require
|
||||||
key_not_present: not has_key (key)
|
a_key_not_present: not has_key (a_key)
|
||||||
local
|
|
||||||
l_value: like value
|
|
||||||
do
|
do
|
||||||
l_value := value
|
if a_value = Void then
|
||||||
if l_value = Void then
|
items.extend (create {JSON_NULL}, a_key)
|
||||||
create {JSON_NULL} l_value
|
else
|
||||||
|
items.extend (a_value, a_key)
|
||||||
end
|
end
|
||||||
object.extend (l_value, key)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
put_string (value: READABLE_STRING_GENERAL; key: JSON_STRING)
|
put_string (a_value: READABLE_STRING_GENERAL; a_key: JSON_STRING)
|
||||||
-- Assuming there is no item of key `key',
|
-- Assuming there is no item of key `a_key',
|
||||||
-- insert `value' with `key'.
|
-- insert `a_value' with `a_key'.
|
||||||
require
|
require
|
||||||
key_not_present: not has_key (key)
|
key_not_present: not has_key (a_key)
|
||||||
local
|
local
|
||||||
l_value: JSON_STRING
|
l_value: JSON_STRING
|
||||||
do
|
do
|
||||||
create l_value.make_json_from_string_32 (value.as_string_32)
|
if attached {READABLE_STRING_8} a_value as s then
|
||||||
put (l_value, key)
|
create l_value.make_from_string (s)
|
||||||
|
else
|
||||||
|
create l_value.make_from_string_32 (a_value.as_string_32)
|
||||||
|
end
|
||||||
|
put (l_value, a_key)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
put_integer (a_value: INTEGER_64; a_key: JSON_STRING)
|
||||||
put_integer (value: INTEGER_64; key: JSON_STRING)
|
-- Assuming there is no item of key `a_key',
|
||||||
-- Assuming there is no item of key `key',
|
-- insert `a_value' with `a_key'.
|
||||||
-- insert `value' with `key'.
|
|
||||||
require
|
require
|
||||||
key_not_present: not has_key (key)
|
key_not_present: not has_key (a_key)
|
||||||
local
|
local
|
||||||
l_value: JSON_NUMBER
|
l_value: JSON_NUMBER
|
||||||
do
|
do
|
||||||
create l_value.make_integer (value)
|
create l_value.make_integer (a_value)
|
||||||
put (l_value, key)
|
put (l_value, a_key)
|
||||||
end
|
end
|
||||||
|
|
||||||
put_natural (value: NATURAL_64; key: JSON_STRING)
|
put_natural (a_value: NATURAL_64; a_key: JSON_STRING)
|
||||||
-- Assuming there is no item of key `key',
|
-- Assuming there is no item of key `a_key',
|
||||||
-- insert `value' with `key'.
|
-- insert `a_value' with `a_key'.
|
||||||
require
|
require
|
||||||
key_not_present: not has_key (key)
|
key_not_present: not has_key (a_key)
|
||||||
local
|
local
|
||||||
l_value: JSON_NUMBER
|
l_value: JSON_NUMBER
|
||||||
do
|
do
|
||||||
create l_value.make_natural (value)
|
create l_value.make_natural (a_value)
|
||||||
put (l_value, key)
|
put (l_value, a_key)
|
||||||
end
|
end
|
||||||
|
|
||||||
put_real (value: DOUBLE; key: JSON_STRING)
|
put_real (a_value: DOUBLE; a_key: JSON_STRING)
|
||||||
-- Assuming there is no item of key `key',
|
-- Assuming there is no item of key `a_key',
|
||||||
-- insert `value' with `key'.
|
-- insert `a_value' with `a_key'.
|
||||||
require
|
require
|
||||||
key_not_present: not has_key (key)
|
key_not_present: not has_key (a_key)
|
||||||
local
|
local
|
||||||
l_value: JSON_NUMBER
|
l_value: JSON_NUMBER
|
||||||
do
|
do
|
||||||
create l_value.make_real (value)
|
create l_value.make_real (a_value)
|
||||||
put (l_value, key)
|
put (l_value, a_key)
|
||||||
end
|
end
|
||||||
|
|
||||||
put_boolean (value: BOOLEAN; key: JSON_STRING)
|
put_boolean (a_value: BOOLEAN; a_key: JSON_STRING)
|
||||||
-- Assuming there is no item of key `key',
|
-- Assuming there is no item of key `a_key',
|
||||||
-- insert `value' with `key'.
|
-- insert `a_value' with `a_key'.
|
||||||
require
|
require
|
||||||
key_not_present: not has_key (key)
|
key_not_present: not has_key (a_key)
|
||||||
local
|
local
|
||||||
l_value: JSON_BOOLEAN
|
l_value: JSON_BOOLEAN
|
||||||
do
|
do
|
||||||
create l_value.make_boolean (value)
|
create l_value.make (a_value)
|
||||||
put (l_value, key)
|
put (l_value, a_key)
|
||||||
end
|
end
|
||||||
|
|
||||||
replace (value: detachable JSON_VALUE; key: JSON_STRING)
|
replace (a_value: detachable JSON_VALUE; a_key: JSON_STRING)
|
||||||
-- Assuming there is no item of key `key',
|
-- Assuming there is no item of key `a_key',
|
||||||
-- insert `value' with `key'.
|
-- insert `a_value' with `a_key'.
|
||||||
local
|
|
||||||
l_value: like value
|
|
||||||
do
|
do
|
||||||
l_value := value
|
if a_value = Void then
|
||||||
if l_value = Void then
|
items.force (create {JSON_NULL}, a_key)
|
||||||
create {JSON_NULL} l_value
|
else
|
||||||
|
items.force (a_value, a_key)
|
||||||
end
|
end
|
||||||
object.force (l_value, key)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
replace_with_string (value: READABLE_STRING_GENERAL; key: JSON_STRING)
|
replace_with_string (a_value: READABLE_STRING_GENERAL; a_key: JSON_STRING)
|
||||||
-- Assuming there is no item of key `key',
|
-- Assuming there is no item of key `a_key',
|
||||||
-- insert `value' with `key'.
|
-- insert `a_value' with `a_key'.
|
||||||
local
|
local
|
||||||
l_value: JSON_STRING
|
l_value: JSON_STRING
|
||||||
do
|
do
|
||||||
create l_value.make_json_from_string_32 (value.as_string_32)
|
if attached {READABLE_STRING_8} a_value as s then
|
||||||
replace (l_value, key)
|
create l_value.make_from_string (s)
|
||||||
|
else
|
||||||
|
create l_value.make_from_string_32 (a_value.as_string_32)
|
||||||
|
end
|
||||||
|
replace (l_value, a_key)
|
||||||
end
|
end
|
||||||
|
|
||||||
replace_with_integer (value: INTEGER_64; key: JSON_STRING)
|
replace_with_integer (a_value: INTEGER_64; a_key: JSON_STRING)
|
||||||
-- Assuming there is no item of key `key',
|
-- Assuming there is no item of key `a_key',
|
||||||
-- insert `value' with `key'.
|
-- insert `a_value' with `a_key'.
|
||||||
local
|
local
|
||||||
l_value: JSON_NUMBER
|
l_value: JSON_NUMBER
|
||||||
do
|
do
|
||||||
create l_value.make_integer (value)
|
create l_value.make_integer (a_value)
|
||||||
replace (l_value, key)
|
replace (l_value, a_key)
|
||||||
end
|
end
|
||||||
|
|
||||||
replace_with_with_natural (value: NATURAL_64; key: JSON_STRING)
|
replace_with_with_natural (a_value: NATURAL_64; a_key: JSON_STRING)
|
||||||
-- Assuming there is no item of key `key',
|
-- Assuming there is no item of key `a_key',
|
||||||
-- insert `value' with `key'.
|
-- insert `a_value' with `a_key'.
|
||||||
local
|
local
|
||||||
l_value: JSON_NUMBER
|
l_value: JSON_NUMBER
|
||||||
do
|
do
|
||||||
create l_value.make_natural (value)
|
create l_value.make_natural (a_value)
|
||||||
replace (l_value, key)
|
replace (l_value, a_key)
|
||||||
end
|
end
|
||||||
|
|
||||||
replace_with_real (value: DOUBLE; key: JSON_STRING)
|
replace_with_real (a_value: DOUBLE; a_key: JSON_STRING)
|
||||||
-- Assuming there is no item of key `key',
|
-- Assuming there is no item of key `a_key',
|
||||||
-- insert `value' with `key'.
|
-- insert `a_value' with `a_key'.
|
||||||
local
|
local
|
||||||
l_value: JSON_NUMBER
|
l_value: JSON_NUMBER
|
||||||
do
|
do
|
||||||
create l_value.make_real (value)
|
create l_value.make_real (a_value)
|
||||||
replace (l_value, key)
|
replace (l_value, a_key)
|
||||||
end
|
end
|
||||||
|
|
||||||
replace_with_boolean (value: BOOLEAN; key: JSON_STRING)
|
replace_with_boolean (a_value: BOOLEAN; a_key: JSON_STRING)
|
||||||
-- Assuming there is no item of key `key',
|
-- Assuming there is no item of key `a_key',
|
||||||
-- insert `value' with `key'.
|
-- insert `a_value' with `a_key'.
|
||||||
local
|
local
|
||||||
l_value: JSON_BOOLEAN
|
l_value: JSON_BOOLEAN
|
||||||
do
|
do
|
||||||
create l_value.make_boolean (value)
|
create l_value.make (a_value)
|
||||||
replace (l_value, key)
|
replace (l_value, a_key)
|
||||||
end
|
end
|
||||||
|
|
||||||
remove (key: JSON_STRING)
|
remove (a_key: JSON_STRING)
|
||||||
-- Remove item indexed by `key' if any.
|
-- Remove item indexed by `a_key' if any.
|
||||||
do
|
do
|
||||||
object.remove (key)
|
items.remove (a_key)
|
||||||
end
|
end
|
||||||
|
|
||||||
wipe_out
|
wipe_out
|
||||||
-- Reset all items to default values; reset status.
|
-- Reset all items to default values; reset status.
|
||||||
do
|
do
|
||||||
object.wipe_out
|
items.wipe_out
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Status report
|
||||||
|
|
||||||
|
has_key (a_key: JSON_STRING): BOOLEAN
|
||||||
|
-- has the JSON_OBJECT contains a specific key `a_key'.
|
||||||
|
do
|
||||||
|
Result := items.has (a_key)
|
||||||
|
end
|
||||||
|
|
||||||
|
has_item (a_value: JSON_VALUE): BOOLEAN
|
||||||
|
-- has the JSON_OBJECT contain a specfic item `a_value'
|
||||||
|
do
|
||||||
|
Result := items.has_item (a_value)
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Access
|
feature -- Access
|
||||||
|
|
||||||
has_key (key: JSON_STRING): BOOLEAN
|
item (a_key: JSON_STRING): detachable JSON_VALUE
|
||||||
-- has the JSON_OBJECT contains a specific key 'key'.
|
-- the json_value associated with a key `a_key'.
|
||||||
do
|
do
|
||||||
Result := object.has (key)
|
Result := items.item (a_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
|
end
|
||||||
|
|
||||||
current_keys: ARRAY [JSON_STRING]
|
current_keys: ARRAY [JSON_STRING]
|
||||||
-- array containing actually used keys
|
-- Array containing actually used keys.
|
||||||
do
|
do
|
||||||
Result := object.current_keys
|
Result := items.current_keys
|
||||||
end
|
end
|
||||||
|
|
||||||
representation: STRING
|
representation: STRING
|
||||||
local
|
-- <Precursor>
|
||||||
t: HASH_TABLE [JSON_VALUE, JSON_STRING]
|
|
||||||
do
|
do
|
||||||
create Result.make (2)
|
create Result.make (2)
|
||||||
Result.append_character ('{')
|
Result.append_character ('{')
|
||||||
from
|
across
|
||||||
t := map_representation
|
items as ic
|
||||||
t.start
|
|
||||||
until
|
|
||||||
t.after
|
|
||||||
loop
|
loop
|
||||||
Result.append (t.key_for_iteration.representation)
|
if Result.count > 1 then
|
||||||
Result.append_character (':')
|
|
||||||
Result.append (t.item_for_iteration.representation)
|
|
||||||
t.forth
|
|
||||||
if not t.after then
|
|
||||||
Result.append_character (',')
|
Result.append_character (',')
|
||||||
end
|
end
|
||||||
|
Result.append (ic.key.representation)
|
||||||
|
Result.append_character (':')
|
||||||
|
Result.append (ic.item.representation)
|
||||||
end
|
end
|
||||||
Result.append_character ('}')
|
Result.append_character ('}')
|
||||||
end
|
end
|
||||||
@@ -242,9 +253,9 @@ feature -- Access
|
|||||||
feature -- Mesurement
|
feature -- Mesurement
|
||||||
|
|
||||||
count: INTEGER
|
count: INTEGER
|
||||||
-- Number of field
|
-- Number of field.
|
||||||
do
|
do
|
||||||
Result := object.count
|
Result := items.count
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Access
|
feature -- Access
|
||||||
@@ -252,7 +263,7 @@ feature -- Access
|
|||||||
new_cursor: TABLE_ITERATION_CURSOR [JSON_VALUE, JSON_STRING]
|
new_cursor: TABLE_ITERATION_CURSOR [JSON_VALUE, JSON_STRING]
|
||||||
-- Fresh cursor associated with current structure
|
-- Fresh cursor associated with current structure
|
||||||
do
|
do
|
||||||
Result := object.new_cursor
|
Result := items.new_cursor
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Status report
|
feature -- Status report
|
||||||
@@ -260,7 +271,7 @@ feature -- Status report
|
|||||||
is_empty: BOOLEAN
|
is_empty: BOOLEAN
|
||||||
-- Is empty object?
|
-- Is empty object?
|
||||||
do
|
do
|
||||||
Result := object.is_empty
|
Result := items.is_empty
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Visitor pattern
|
feature -- Visitor pattern
|
||||||
@@ -277,7 +288,7 @@ feature -- Conversion
|
|||||||
map_representation: HASH_TABLE [JSON_VALUE, JSON_STRING]
|
map_representation: HASH_TABLE [JSON_VALUE, JSON_STRING]
|
||||||
-- A representation that maps keys to values
|
-- A representation that maps keys to values
|
||||||
do
|
do
|
||||||
Result := object
|
Result := items
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Report
|
feature -- Report
|
||||||
@@ -286,13 +297,13 @@ feature -- Report
|
|||||||
-- Hash code value
|
-- Hash code value
|
||||||
do
|
do
|
||||||
from
|
from
|
||||||
object.start
|
items.start
|
||||||
Result := object.out.hash_code
|
Result := items.out.hash_code
|
||||||
until
|
until
|
||||||
object.off
|
items.off
|
||||||
loop
|
loop
|
||||||
Result := ((Result \\ 8388593) |<< 8) + object.item_for_iteration.hash_code
|
Result := ((Result \\ 8388593) |<< 8) + items.item_for_iteration.hash_code
|
||||||
object.forth
|
items.forth
|
||||||
end
|
end
|
||||||
-- Ensure it is a positive value.
|
-- Ensure it is a positive value.
|
||||||
Result := Result.hash_code
|
Result := Result.hash_code
|
||||||
@@ -308,10 +319,13 @@ feature -- Status report
|
|||||||
|
|
||||||
feature {NONE} -- Implementation
|
feature {NONE} -- Implementation
|
||||||
|
|
||||||
object: HASH_TABLE [JSON_VALUE, JSON_STRING]
|
items: HASH_TABLE [JSON_VALUE, JSON_STRING]
|
||||||
-- Value container
|
-- Value container
|
||||||
|
|
||||||
invariant
|
invariant
|
||||||
object_not_void: object /= Void
|
items_not_void: items /= Void
|
||||||
|
|
||||||
|
note
|
||||||
|
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
|
||||||
|
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,39 +1,92 @@
|
|||||||
note
|
note
|
||||||
|
|
||||||
description: "[
|
description: "[
|
||||||
A JSON_STRING represent a string in JSON.
|
A JSON_STRING represent a string in JSON.
|
||||||
A string is a collection of zero or more Unicodes characters, wrapped in double
|
A string is a collection of zero or more Unicodes characters, wrapped in double
|
||||||
quotes, using blackslash espaces.
|
quotes, using blackslash espaces.
|
||||||
]"
|
]"
|
||||||
|
author: "$Author$"
|
||||||
author: "Javier Velilla"
|
date: "$Date$"
|
||||||
date: "2008/08/24"
|
revision: "$Revision$"
|
||||||
revision: "Revision 0.1"
|
|
||||||
license: "MIT (see http://www.opensource.org/licenses/mit-license.php)"
|
license: "MIT (see http://www.opensource.org/licenses/mit-license.php)"
|
||||||
|
|
||||||
|
|
||||||
class
|
class
|
||||||
JSON_STRING
|
JSON_STRING
|
||||||
|
|
||||||
inherit
|
inherit
|
||||||
|
|
||||||
JSON_VALUE
|
JSON_VALUE
|
||||||
redefine
|
redefine
|
||||||
is_equal
|
is_equal
|
||||||
end
|
end
|
||||||
|
|
||||||
create
|
create
|
||||||
make_json,
|
make_from_string, make_from_string_32, make_from_string_general,
|
||||||
make_json_from_string_32,
|
make_from_escaped_json_string,
|
||||||
make_with_escaped_json
|
make_with_escaped_json, make_json, make_json_from_string_32
|
||||||
|
|
||||||
convert
|
convert
|
||||||
make_json ({READABLE_STRING_8, STRING_8, IMMUTABLE_STRING_8}),
|
make_from_string ({READABLE_STRING_8, STRING_8, IMMUTABLE_STRING_8}),
|
||||||
make_json_from_string_32 ({READABLE_STRING_32, STRING_32, IMMUTABLE_STRING_32})
|
make_from_string_32 ({READABLE_STRING_32, STRING_32, IMMUTABLE_STRING_32}),
|
||||||
|
make_from_string_general ({READABLE_STRING_GENERAL, STRING_GENERAL, IMMUTABLE_STRING_GENERAL})
|
||||||
|
|
||||||
feature {NONE} -- Initialization
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
|
make_from_string (s: READABLE_STRING_8)
|
||||||
|
-- Initialize from ascii string `s'.
|
||||||
|
require
|
||||||
|
s_not_void: s /= Void
|
||||||
|
do
|
||||||
|
make_from_escaped_json_string (escaped_json_string (s))
|
||||||
|
end
|
||||||
|
|
||||||
|
make_from_string_32 (s: READABLE_STRING_32)
|
||||||
|
-- Initialize from unicode string `s'.
|
||||||
|
require
|
||||||
|
s_not_void: s /= Void
|
||||||
|
do
|
||||||
|
make_from_escaped_json_string (escaped_json_string (s))
|
||||||
|
end
|
||||||
|
|
||||||
|
make_from_string_general (s: READABLE_STRING_GENERAL)
|
||||||
|
-- Initialize from string `s'.
|
||||||
|
require
|
||||||
|
s_not_void: s /= Void
|
||||||
|
do
|
||||||
|
if attached {READABLE_STRING_8} s as s8 then
|
||||||
|
make_from_string (s8)
|
||||||
|
else
|
||||||
|
make_from_string_32 (s.as_string_32)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
make_from_escaped_json_string (a_escaped_string: READABLE_STRING_8)
|
||||||
|
-- Initialize with `a_escaped_string' already JSON escaped.
|
||||||
|
require
|
||||||
|
a_escaped_string_not_void: a_escaped_string /= Void
|
||||||
|
do
|
||||||
|
item := a_escaped_string
|
||||||
|
end
|
||||||
|
|
||||||
|
make_with_escaped_json (a_escaped_string: READABLE_STRING_8)
|
||||||
|
-- Initialize with `a_escaped_string' already JSON escaped.
|
||||||
|
obsolete
|
||||||
|
"Use `make_from_escaped_json_string' Sept/2014"
|
||||||
|
require
|
||||||
|
a_escaped_string_not_void: a_escaped_string /= Void
|
||||||
|
do
|
||||||
|
make_from_escaped_json_string (a_escaped_string)
|
||||||
|
end
|
||||||
|
|
||||||
|
make_from_json_string (a_json: JSON_STRING)
|
||||||
|
-- Initialize with `a_json' string value.
|
||||||
|
do
|
||||||
|
make_from_escaped_json_string (a_json.item)
|
||||||
|
end
|
||||||
|
|
||||||
make_json (s: READABLE_STRING_8)
|
make_json (s: READABLE_STRING_8)
|
||||||
-- Initialize.
|
-- Initialize.
|
||||||
|
obsolete
|
||||||
|
"Use `make_from_string' Sept/2014"
|
||||||
require
|
require
|
||||||
item_not_void: s /= Void
|
item_not_void: s /= Void
|
||||||
do
|
do
|
||||||
@@ -42,18 +95,12 @@ feature {NONE} -- Initialization
|
|||||||
|
|
||||||
make_json_from_string_32 (s: READABLE_STRING_32)
|
make_json_from_string_32 (s: READABLE_STRING_32)
|
||||||
-- Initialize from STRING_32 `s'.
|
-- Initialize from STRING_32 `s'.
|
||||||
|
obsolete
|
||||||
|
"Use `make_from_string_32' Sept/2014"
|
||||||
require
|
require
|
||||||
item_not_void: s /= Void
|
item_not_void: s /= Void
|
||||||
do
|
do
|
||||||
make_with_escaped_json (escaped_json_string_32 (s))
|
make_with_escaped_json (escaped_json_string (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
|
end
|
||||||
|
|
||||||
feature -- Access
|
feature -- Access
|
||||||
@@ -64,7 +111,7 @@ feature -- Access
|
|||||||
feature -- Conversion
|
feature -- Conversion
|
||||||
|
|
||||||
unescaped_string_8: STRING_8
|
unescaped_string_8: STRING_8
|
||||||
-- Unescaped string from `item'.
|
-- Unescaped ascii string from `item'.
|
||||||
--| note: valid only if `item' does not encode any unicode character.
|
--| note: valid only if `item' does not encode any unicode character.
|
||||||
local
|
local
|
||||||
s: like item
|
s: like item
|
||||||
@@ -75,7 +122,7 @@ feature -- Conversion
|
|||||||
end
|
end
|
||||||
|
|
||||||
unescaped_string_32: STRING_32
|
unescaped_string_32: STRING_32
|
||||||
-- Unescaped string 32 from `item'
|
-- Unescaped uncode string from `item'
|
||||||
--| some encoders uses UTF-8 , and not the recommended pure json encoding
|
--| some encoders uses UTF-8 , and not the recommended pure json encoding
|
||||||
--| thus, let's support the UTF-8 encoding during decoding.
|
--| thus, let's support the UTF-8 encoding during decoding.
|
||||||
local
|
local
|
||||||
@@ -87,7 +134,7 @@ feature -- Conversion
|
|||||||
end
|
end
|
||||||
|
|
||||||
representation: STRING
|
representation: STRING
|
||||||
-- String representation of `item' with escaped entities if any
|
-- String representation of `item' with escaped entities if any.
|
||||||
do
|
do
|
||||||
create Result.make (item.count + 2)
|
create Result.make (item.count + 2)
|
||||||
Result.append_character ('%"')
|
Result.append_character ('%"')
|
||||||
@@ -105,16 +152,23 @@ feature -- Conversion
|
|||||||
do
|
do
|
||||||
s := item
|
s := item
|
||||||
n := s.count
|
n := s.count
|
||||||
from i := 1 until i > n loop
|
from
|
||||||
|
i := 1
|
||||||
|
until
|
||||||
|
i > n
|
||||||
|
loop
|
||||||
c := s [i]
|
c := s [i]
|
||||||
if c = '\' then
|
if c = '\' then
|
||||||
if i < n then
|
if i < n then
|
||||||
inspect s [i + 1]
|
inspect s [i + 1]
|
||||||
|
when '%"' then
|
||||||
|
a_output.append_character ('%"')
|
||||||
|
i := i + 2
|
||||||
when '\' then
|
when '\' then
|
||||||
a_output.append_character ('\')
|
a_output.append_character ('\')
|
||||||
i := i + 2
|
i := i + 2
|
||||||
when '%"' then
|
when '/' then
|
||||||
a_output.append_character ('%"')
|
a_output.append_character ('/')
|
||||||
i := i + 2
|
i := i + 2
|
||||||
when 'b' then
|
when 'b' then
|
||||||
a_output.append_character ('%B')
|
a_output.append_character ('%B')
|
||||||
@@ -132,15 +186,15 @@ feature -- Conversion
|
|||||||
a_output.append_character ('%T')
|
a_output.append_character ('%T')
|
||||||
i := i + 2
|
i := i + 2
|
||||||
when 'u' then
|
when 'u' then
|
||||||
--| Leave Unicode \uXXXX unescaped
|
--| Leave unicode \uXXXX unescaped
|
||||||
a_output.append_character ('\')
|
a_output.append_character (c) -- '\'
|
||||||
i := i + 1
|
i := i + 1
|
||||||
else
|
else
|
||||||
a_output.append_character ('\')
|
a_output.append_character (c) -- '\'
|
||||||
i := i + 1
|
i := i + 1
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
a_output.append_character ('\')
|
a_output.append_character (c) -- '\'
|
||||||
i := i + 1
|
i := i + 1
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@@ -163,16 +217,23 @@ feature -- Conversion
|
|||||||
do
|
do
|
||||||
s := item
|
s := item
|
||||||
n := s.count
|
n := s.count
|
||||||
from i := 1 until i > n loop
|
from
|
||||||
|
i := 1
|
||||||
|
until
|
||||||
|
i > n
|
||||||
|
loop
|
||||||
ch := s.item (i)
|
ch := s.item (i)
|
||||||
if ch = '\' then
|
if ch = '\' then
|
||||||
if i < n then
|
if i < n then
|
||||||
inspect s [i + 1]
|
inspect s [i + 1]
|
||||||
|
when '%"' then
|
||||||
|
a_output.append_character ('%"')
|
||||||
|
i := i + 2
|
||||||
when '\' then
|
when '\' then
|
||||||
a_output.append_character ('\')
|
a_output.append_character ('\')
|
||||||
i := i + 2
|
i := i + 2
|
||||||
when '%"' then
|
when '/' then
|
||||||
a_output.append_character ('%"')
|
a_output.append_character ('/')
|
||||||
i := i + 2
|
i := i + 2
|
||||||
when 'b' then
|
when 'b' then
|
||||||
a_output.append_character ('%B')
|
a_output.append_character ('%B')
|
||||||
@@ -196,48 +257,38 @@ feature -- Conversion
|
|||||||
end
|
end
|
||||||
i := i + 6 -- i+2+4
|
i := i + 6 -- i+2+4
|
||||||
else
|
else
|
||||||
a_output.append_character ('\')
|
a_output.append_character (ch) -- '\'
|
||||||
i := i + 1
|
i := i + 1
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
a_output.append_character ('\')
|
a_output.append_character (ch) -- '\'
|
||||||
i := i + 1
|
i := i + 1
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
c := ch.natural_32_code
|
c := ch.natural_32_code
|
||||||
if c <= 0x7F then
|
if c <= 0x7F then
|
||||||
-- 0xxxxxxx
|
-- 0xxxxxxx
|
||||||
check ch = c.to_character_32 end
|
check
|
||||||
|
ch = c.to_character_32
|
||||||
|
end
|
||||||
a_output.append_character (ch)
|
a_output.append_character (ch)
|
||||||
elseif c <= 0xDF then
|
elseif c <= 0xDF then
|
||||||
-- 110xxxxx 10xxxxxx
|
-- 110xxxxx 10xxxxxx
|
||||||
i := i + 1
|
i := i + 1
|
||||||
if i <= n then
|
if i <= n then
|
||||||
a_output.append_code (
|
a_output.append_code (((c & 0x1F) |<< 6) | (s.code (i) & 0x3F))
|
||||||
((c & 0x1F) |<< 6) |
|
|
||||||
(s.code (i) & 0x3F)
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
elseif c <= 0xEF then
|
elseif c <= 0xEF then
|
||||||
-- 1110xxxx 10xxxxxx 10xxxxxx
|
-- 1110xxxx 10xxxxxx 10xxxxxx
|
||||||
i := i + 2
|
i := i + 2
|
||||||
if i <= n then
|
if i <= n then
|
||||||
a_output.append_code (
|
a_output.append_code (((c & 0xF) |<< 12) | ((s.code (i - 1) & 0x3F) |<< 6) | (s.code (i) & 0x3F))
|
||||||
((c & 0xF) |<< 12) |
|
|
||||||
((s.code (i - 1) & 0x3F) |<< 6) |
|
|
||||||
(s.code (i) & 0x3F)
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
elseif c <= 0xF7 then
|
elseif c <= 0xF7 then
|
||||||
-- 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
-- 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||||
i := i + 3
|
i := i + 3
|
||||||
if i <= n then
|
if i <= n then
|
||||||
a_output.append_code (
|
a_output.append_code (((c & 0x7) |<< 18) | ((s.code (i - 2) & 0x3F) |<< 12) | ((s.code (i - 1) & 0x3F) |<< 6) | (s.code (i) & 0x3F))
|
||||||
((c & 0x7) |<< 18) |
|
|
||||||
((s.code (i - 2) & 0x3F) |<< 12) |
|
|
||||||
((s.code (i - 1) & 0x3F) |<< 6) |
|
|
||||||
(s.code (i) & 0x3F)
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
i := i + 1
|
i := i + 1
|
||||||
@@ -265,12 +316,48 @@ feature -- Comparison
|
|||||||
|
|
||||||
feature -- Change Element
|
feature -- Change Element
|
||||||
|
|
||||||
append (a_string: STRING)
|
append (a_escaped_string: READABLE_STRING_8)
|
||||||
-- Add a_string
|
-- Add JSON escaped string `a_escaped_string'
|
||||||
require
|
require
|
||||||
a_string_not_void: a_string /= Void
|
a_escaped_string_not_void: a_escaped_string /= Void
|
||||||
do
|
do
|
||||||
item.append_string (a_string)
|
item.append_string (a_escaped_string)
|
||||||
|
end
|
||||||
|
|
||||||
|
append_json_string (a_json_string: JSON_STRING)
|
||||||
|
-- Add JSON string `a_json_string'
|
||||||
|
require
|
||||||
|
a_json_string_not_void: a_json_string /= Void
|
||||||
|
do
|
||||||
|
append (a_json_string.item)
|
||||||
|
end
|
||||||
|
|
||||||
|
append_string (s: READABLE_STRING_8)
|
||||||
|
-- Add ascii string `s'
|
||||||
|
require
|
||||||
|
s_not_void: s /= Void
|
||||||
|
do
|
||||||
|
append (escaped_json_string (s))
|
||||||
|
end
|
||||||
|
|
||||||
|
append_string_32 (s: READABLE_STRING_32)
|
||||||
|
-- Add unicode string `s'
|
||||||
|
require
|
||||||
|
s_not_void: s /= Void
|
||||||
|
do
|
||||||
|
append (escaped_json_string (s))
|
||||||
|
end
|
||||||
|
|
||||||
|
append_string_general (s: READABLE_STRING_GENERAL)
|
||||||
|
-- Add unicode string `s'
|
||||||
|
require
|
||||||
|
s_not_void: s /= Void
|
||||||
|
do
|
||||||
|
if attached {READABLE_STRING_8} s as s8 then
|
||||||
|
append_string (s.as_string_8)
|
||||||
|
else
|
||||||
|
append_string_32 (s.as_string_32)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Status report
|
feature -- Status report
|
||||||
@@ -317,13 +404,11 @@ feature {NONE} -- Implementation
|
|||||||
char: CHARACTER
|
char: CHARACTER
|
||||||
do
|
do
|
||||||
nb := s.count
|
nb := s.count
|
||||||
|
|
||||||
if nb >= 2 and then s.item (2) = 'x' then
|
if nb >= 2 and then s.item (2) = 'x' then
|
||||||
i := 3
|
i := 3
|
||||||
else
|
else
|
||||||
i := 1
|
i := 1
|
||||||
end
|
end
|
||||||
|
|
||||||
from
|
from
|
||||||
until
|
until
|
||||||
i > nb
|
i > nb
|
||||||
@@ -339,35 +424,8 @@ feature {NONE} -- Implementation
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
escaped_json_string (s: READABLE_STRING_8): STRING_8
|
escaped_json_string (s: READABLE_STRING_GENERAL): STRING_8
|
||||||
-- JSON string with '"' and '\' characters escaped
|
-- JSON string with '"' and '\' characters and unicode 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 '%B' then Result.append_string ("\b")
|
|
||||||
when '%F' then Result.append_string ("\f")
|
|
||||||
when '%N' then Result.append_string ("\n")
|
|
||||||
when '%R' then Result.append_string ("\r")
|
|
||||||
when '%T' then Result.append_string ("\t")
|
|
||||||
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
|
require
|
||||||
s_not_void: s /= Void
|
s_not_void: s /= Void
|
||||||
local
|
local
|
||||||
@@ -378,18 +436,37 @@ feature {NONE} -- Implementation
|
|||||||
do
|
do
|
||||||
n := s.count
|
n := s.count
|
||||||
create Result.make (n + n // 10)
|
create Result.make (n + n // 10)
|
||||||
from i := 1 until i > n loop
|
from
|
||||||
|
i := 1
|
||||||
|
until
|
||||||
|
i > n
|
||||||
|
loop
|
||||||
uc := s.item (i)
|
uc := s.item (i)
|
||||||
if uc.is_character_8 then
|
if uc.is_character_8 then
|
||||||
c := uc.to_character_8
|
c := uc.to_character_8
|
||||||
inspect c
|
inspect c
|
||||||
when '%"' then Result.append_string ("\%"")
|
when '%"' then
|
||||||
when '\' then Result.append_string ("\\")
|
Result.append_string ("\%"")
|
||||||
when '%B' then Result.append_string ("\b")
|
when '\' then
|
||||||
when '%F' then Result.append_string ("\f")
|
Result.append_string ("\\")
|
||||||
when '%N' then Result.append_string ("\n")
|
when '/' then
|
||||||
when '%R' then Result.append_string ("\r")
|
-- To avoid issue with Javascript </script> ...
|
||||||
when '%T' then Result.append_string ("\t")
|
-- escape only </ to <\/
|
||||||
|
if s.valid_index (i - 1) and then s.item (i - 1) = '<' then
|
||||||
|
Result.append_string ("\/")
|
||||||
|
else
|
||||||
|
Result.append_string ("/")
|
||||||
|
end
|
||||||
|
when '%B' then
|
||||||
|
Result.append_string ("\b")
|
||||||
|
when '%F' then
|
||||||
|
Result.append_string ("\f")
|
||||||
|
when '%N' then
|
||||||
|
Result.append_string ("\n")
|
||||||
|
when '%R' then
|
||||||
|
Result.append_string ("\r")
|
||||||
|
when '%T' then
|
||||||
|
Result.append_string ("\t")
|
||||||
else
|
else
|
||||||
Result.extend (c)
|
Result.extend (c)
|
||||||
end
|
end
|
||||||
@@ -405,14 +482,15 @@ feature {NONE} -- Implementation
|
|||||||
j := j + 1
|
j := j + 1
|
||||||
end
|
end
|
||||||
h := h.substring (j, h.count)
|
h := h.substring (j, h.count)
|
||||||
|
|
||||||
from
|
from
|
||||||
until
|
until
|
||||||
h.count >= 4
|
h.count >= 4
|
||||||
loop
|
loop
|
||||||
h.prepend_integer (0)
|
h.prepend_integer (0)
|
||||||
end
|
end
|
||||||
check h.count = 4 end
|
check
|
||||||
|
hexastring_has_4_chars: h.count = 4
|
||||||
|
end
|
||||||
Result.append (h)
|
Result.append (h)
|
||||||
end
|
end
|
||||||
i := i + 1
|
i := i + 1
|
||||||
@@ -422,4 +500,7 @@ feature {NONE} -- Implementation
|
|||||||
invariant
|
invariant
|
||||||
item_not_void: item /= Void
|
item_not_void: item /= Void
|
||||||
|
|
||||||
|
note
|
||||||
|
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
|
||||||
|
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -14,11 +14,11 @@ note
|
|||||||
revision: "Revision 0.1"
|
revision: "Revision 0.1"
|
||||||
license: "MIT (see http://www.opensource.org/licenses/mit-license.php)"
|
license: "MIT (see http://www.opensource.org/licenses/mit-license.php)"
|
||||||
|
|
||||||
|
|
||||||
deferred class
|
deferred class
|
||||||
JSON_VALUE
|
JSON_VALUE
|
||||||
|
|
||||||
inherit
|
inherit
|
||||||
|
|
||||||
HASHABLE
|
HASHABLE
|
||||||
|
|
||||||
DEBUG_OUTPUT
|
DEBUG_OUTPUT
|
||||||
@@ -40,4 +40,7 @@ feature -- Visitor pattern
|
|||||||
deferred
|
deferred
|
||||||
end
|
end
|
||||||
|
|
||||||
|
note
|
||||||
|
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
|
||||||
|
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,513 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
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: 89185 $"
|
|
||||||
file: "$HeadURL: $"
|
|
||||||
|
|
||||||
class SHARED_EJSON
|
|
||||||
|
|
||||||
feature
|
|
||||||
|
|
||||||
json: EJSON
|
|
||||||
-- A shared EJSON instance with default converters for
|
|
||||||
--LINKED_LIST [ANY] and HASH_TABLE [ANY, HASHABLE]
|
|
||||||
local
|
|
||||||
jalc: JSON_ARRAYED_LIST_CONVERTER
|
|
||||||
jllc: JSON_LINKED_LIST_CONVERTER
|
|
||||||
jhtc: JSON_HASH_TABLE_CONVERTER
|
|
||||||
once
|
|
||||||
create Result
|
|
||||||
|
|
||||||
create jalc.make
|
|
||||||
Result.add_converter (jalc)
|
|
||||||
|
|
||||||
create jllc.make
|
|
||||||
Result.add_converter (jllc)
|
|
||||||
|
|
||||||
create jhtc.make
|
|
||||||
Result.add_converter (jhtc)
|
|
||||||
end
|
|
||||||
|
|
||||||
end -- class SHARED_EJSON
|
|
||||||
4
contrib/library/text/parser/json/library/license.lic
Normal file
4
contrib/library/text/parser/json/library/license.lic
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
${NOTE_KEYWORD}
|
||||||
|
copyright: "2010-${YEAR}, Javier Velilla and others https://github.com/eiffelhub/json."
|
||||||
|
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
|
||||||
|
|
||||||
679
contrib/library/text/parser/json/library/parser/json_parser.e
Normal file
679
contrib/library/text/parser/json/library/parser/json_parser.e
Normal file
@@ -0,0 +1,679 @@
|
|||||||
|
note
|
||||||
|
description: "Parse serialized JSON data"
|
||||||
|
author: "$Author$"
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
JSON_PARSER
|
||||||
|
|
||||||
|
inherit
|
||||||
|
JSON_READER
|
||||||
|
rename
|
||||||
|
make as make_reader,
|
||||||
|
reset as reset_reader
|
||||||
|
end
|
||||||
|
|
||||||
|
JSON_TOKENS
|
||||||
|
|
||||||
|
create
|
||||||
|
make_with_string,
|
||||||
|
make_parser
|
||||||
|
|
||||||
|
feature {NONE} -- Initialize
|
||||||
|
|
||||||
|
make_with_string (a_content: STRING)
|
||||||
|
-- Initialize parser with JSON content `a_content'.
|
||||||
|
require
|
||||||
|
a_content_not_empty: a_content /= Void and then not a_content.is_empty
|
||||||
|
do
|
||||||
|
create errors.make
|
||||||
|
make_reader (a_content)
|
||||||
|
reset
|
||||||
|
end
|
||||||
|
|
||||||
|
make_parser (a_json: STRING)
|
||||||
|
-- Initialize.
|
||||||
|
obsolete
|
||||||
|
"Use `make_with_string' [sept/2014]."
|
||||||
|
do
|
||||||
|
make_with_string (a_json)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Status report
|
||||||
|
|
||||||
|
is_parsed: BOOLEAN
|
||||||
|
-- Is parsed ?
|
||||||
|
|
||||||
|
is_valid: BOOLEAN
|
||||||
|
-- Is valid?
|
||||||
|
do
|
||||||
|
Result := not has_error
|
||||||
|
end
|
||||||
|
|
||||||
|
has_error: BOOLEAN
|
||||||
|
-- Has error?
|
||||||
|
|
||||||
|
errors: LINKED_LIST [STRING]
|
||||||
|
-- Current errors
|
||||||
|
|
||||||
|
errors_as_string: STRING
|
||||||
|
-- String representation of `errors'.
|
||||||
|
do
|
||||||
|
create Result.make_empty
|
||||||
|
across
|
||||||
|
errors as ic
|
||||||
|
loop
|
||||||
|
Result.append_string (ic.item)
|
||||||
|
Result.append_character ('%N')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
current_errors: STRING
|
||||||
|
-- Current errors as string
|
||||||
|
obsolete
|
||||||
|
"USe errors_as_string [sept/2014]"
|
||||||
|
do
|
||||||
|
Result := errors_as_string
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Access
|
||||||
|
|
||||||
|
parsed_json_value: detachable JSON_VALUE
|
||||||
|
-- Parsed json value if any.
|
||||||
|
require
|
||||||
|
is_parsed: is_parsed
|
||||||
|
attribute
|
||||||
|
ensure
|
||||||
|
attached_result_if_valid: is_valid implies Result /= Void
|
||||||
|
end
|
||||||
|
|
||||||
|
parsed_json_object: detachable JSON_OBJECT
|
||||||
|
-- parsed json value as a JSON_OBJECT if it is an object.
|
||||||
|
require
|
||||||
|
is_parsed: is_parsed
|
||||||
|
do
|
||||||
|
if attached {JSON_OBJECT} parsed_json_value as j_object then
|
||||||
|
Result := j_object
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
parsed_json_array: detachable JSON_ARRAY
|
||||||
|
-- parsed json value as a JSON_OBJECT if it is an array.
|
||||||
|
require
|
||||||
|
is_parsed: is_parsed
|
||||||
|
do
|
||||||
|
if attached {JSON_ARRAY} parsed_json_value as j_array then
|
||||||
|
Result := j_array
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Commands
|
||||||
|
|
||||||
|
reset
|
||||||
|
-- Reset parsing values.
|
||||||
|
do
|
||||||
|
parsed_json_value := Void
|
||||||
|
errors.wipe_out
|
||||||
|
has_error := False
|
||||||
|
is_parsed := False
|
||||||
|
end
|
||||||
|
|
||||||
|
parse_content
|
||||||
|
-- Parse JSON content `representation'.
|
||||||
|
-- start ::= object | array
|
||||||
|
do
|
||||||
|
reset
|
||||||
|
reset_reader
|
||||||
|
|
||||||
|
if is_valid_start_symbol then
|
||||||
|
parsed_json_value := next_json_value
|
||||||
|
if extra_elements then
|
||||||
|
report_error ("Remaining element outside the main json value!")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
report_error ("Syntax error unexpected token, expecting `{' or `['")
|
||||||
|
end
|
||||||
|
is_parsed := is_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
feature -- Element change
|
||||||
|
|
||||||
|
report_error (e: STRING)
|
||||||
|
-- Report error `e'
|
||||||
|
require
|
||||||
|
e_not_void: e /= Void
|
||||||
|
do
|
||||||
|
has_error := True
|
||||||
|
errors.force (e)
|
||||||
|
ensure
|
||||||
|
has_error: has_error
|
||||||
|
is_not_valid: not is_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
feature -- Obsolete commands
|
||||||
|
|
||||||
|
parse_json: detachable JSON_VALUE
|
||||||
|
-- Parse JSON data `representation'
|
||||||
|
-- start ::= object | array
|
||||||
|
obsolete
|
||||||
|
"Use `parse_content' and `parsed_json_value' [sept/2014]."
|
||||||
|
do
|
||||||
|
parse_content
|
||||||
|
if is_parsed then
|
||||||
|
Result := parsed_json_value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
parse_object: detachable JSON_OBJECT
|
||||||
|
-- Parse JSON data `representation'
|
||||||
|
-- start ::= object | array
|
||||||
|
obsolete
|
||||||
|
"Use `parse_content' and `parsed_json_value' [nov/2014]."
|
||||||
|
do
|
||||||
|
parse_content
|
||||||
|
if is_parsed and then attached {JSON_OBJECT} parsed_json_value as jo then
|
||||||
|
Result := jo
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
parse: detachable JSON_VALUE
|
||||||
|
-- Next JSON value from current position on `representation'.
|
||||||
|
obsolete
|
||||||
|
"Use restricted `next_parsed_json_value' [sept/2014]."
|
||||||
|
do
|
||||||
|
Result := next_parsed_json_value
|
||||||
|
is_parsed := is_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
feature {JSON_PARSER_ACCESS} -- Obsolete commands: restricted area
|
||||||
|
|
||||||
|
next_parsed_json_value: detachable JSON_VALUE
|
||||||
|
-- Return next json value from current position.
|
||||||
|
--| this does not call `reset_reader'.
|
||||||
|
do
|
||||||
|
reset
|
||||||
|
Result := next_json_value
|
||||||
|
end
|
||||||
|
|
||||||
|
feature {NONE} -- Implementation: parsing
|
||||||
|
|
||||||
|
next_json_value: detachable JSON_VALUE
|
||||||
|
-- Next JSON value from current position on `representation'.
|
||||||
|
local
|
||||||
|
c: CHARACTER
|
||||||
|
do
|
||||||
|
if not has_error then
|
||||||
|
skip_white_spaces
|
||||||
|
c := actual
|
||||||
|
inspect c
|
||||||
|
when token_object_open then
|
||||||
|
Result := next_json_object
|
||||||
|
when token_double_quote then
|
||||||
|
Result := parse_string
|
||||||
|
when token_array_open then
|
||||||
|
Result := parse_array
|
||||||
|
else
|
||||||
|
if c.is_digit or c = token_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_true
|
||||||
|
next
|
||||||
|
next
|
||||||
|
next
|
||||||
|
elseif is_false then
|
||||||
|
Result := create {JSON_BOOLEAN}.make_false
|
||||||
|
next
|
||||||
|
next
|
||||||
|
next
|
||||||
|
next
|
||||||
|
else
|
||||||
|
report_error ("JSON is not well formed in parse")
|
||||||
|
Result := Void
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
ensure
|
||||||
|
is_parsed_implies_result_not_void: not has_error implies Result /= Void
|
||||||
|
end
|
||||||
|
|
||||||
|
next_json_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 = token_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 = token_colon then --| token_colon = ':'
|
||||||
|
next
|
||||||
|
skip_white_spaces
|
||||||
|
else
|
||||||
|
report_error ("%N Input string is a not well formed JSON, expected: : found: " + actual.out)
|
||||||
|
has_more := False
|
||||||
|
end
|
||||||
|
l_value := next_json_value
|
||||||
|
if not has_error and then (l_value /= Void and l_json_string /= Void) then
|
||||||
|
Result.put (l_value, l_json_string)
|
||||||
|
next
|
||||||
|
skip_white_spaces
|
||||||
|
if actual = token_object_close then
|
||||||
|
has_more := False
|
||||||
|
elseif actual /= token_comma then
|
||||||
|
has_more := 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 = token_double_quote then
|
||||||
|
from
|
||||||
|
has_more := True
|
||||||
|
until
|
||||||
|
not has_more
|
||||||
|
loop
|
||||||
|
next
|
||||||
|
c := actual
|
||||||
|
if c = token_double_quote then
|
||||||
|
has_more := False
|
||||||
|
elseif c = '%H' then -- '%H' = '\' = reverse solidus
|
||||||
|
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
|
||||||
|
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
|
||||||
|
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
|
||||||
|
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_from_escaped_json_string (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_empty
|
||||||
|
-- check if is an empty array []
|
||||||
|
next
|
||||||
|
skip_white_spaces
|
||||||
|
if actual = token_array_close then
|
||||||
|
-- is an empty array
|
||||||
|
else
|
||||||
|
previous
|
||||||
|
from
|
||||||
|
flag := True
|
||||||
|
until
|
||||||
|
not flag
|
||||||
|
loop
|
||||||
|
next
|
||||||
|
skip_white_spaces
|
||||||
|
l_value := next_json_value
|
||||||
|
if not has_error and then l_value /= Void then
|
||||||
|
Result.add (l_value)
|
||||||
|
next
|
||||||
|
skip_white_spaces
|
||||||
|
c := actual
|
||||||
|
if c = token_array_close then
|
||||||
|
flag := False
|
||||||
|
elseif c /= token_comma then
|
||||||
|
flag := 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 = token_comma 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
|
||||||
|
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 = token_minus then
|
||||||
|
s.extend (c)
|
||||||
|
i := i + 1
|
||||||
|
if i > n then
|
||||||
|
Result := False
|
||||||
|
else
|
||||||
|
c := a_number [i]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
--| "0|[1-9]\d*
|
||||||
|
if Result and c.is_digit then
|
||||||
|
if c = '0' then
|
||||||
|
--| "0"
|
||||||
|
s.extend (c)
|
||||||
|
i := i + 1
|
||||||
|
if i <= n then
|
||||||
|
c := a_number [i]
|
||||||
|
end
|
||||||
|
else
|
||||||
|
--| "[1-9]"
|
||||||
|
s.extend (c)
|
||||||
|
|
||||||
|
--| "\d*"
|
||||||
|
i := i + 1
|
||||||
|
if i <= n then
|
||||||
|
c := a_number [i]
|
||||||
|
from
|
||||||
|
until
|
||||||
|
i > n or not c.is_digit
|
||||||
|
loop
|
||||||
|
s.extend (c)
|
||||||
|
i := i + 1
|
||||||
|
if i <= n then
|
||||||
|
c := a_number [i]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if i > n then
|
||||||
|
-- Exit
|
||||||
|
else
|
||||||
|
if Result then
|
||||||
|
--| "(\.\d+)?"
|
||||||
|
if c = token_dot 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
|
||||||
|
if i <= n then
|
||||||
|
c := a_number [i]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
Result := False --| expecting digit
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if Result then --| "(?:[eE][+-]?\d+)?\b"
|
||||||
|
if is_exp_token (c) then
|
||||||
|
--| "[eE][+-]?\d+"
|
||||||
|
s.extend (c)
|
||||||
|
i := i + 1
|
||||||
|
c := a_number [i]
|
||||||
|
if c = token_plus or c = token_minus then
|
||||||
|
s.extend (c)
|
||||||
|
i := i + 1
|
||||||
|
if i <= n then
|
||||||
|
c := a_number [i]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if c.is_digit then
|
||||||
|
from
|
||||||
|
until
|
||||||
|
i > n or not c.is_digit
|
||||||
|
loop
|
||||||
|
s.extend (c)
|
||||||
|
i := i + 1
|
||||||
|
if i <= n then
|
||||||
|
c := a_number [i]
|
||||||
|
end
|
||||||
|
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
|
||||||
|
if i <= n then
|
||||||
|
c := a_number [i]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
Result := i > n and then s.same_string (a_number)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
is_valid_unicode (a_unicode: STRING): BOOLEAN
|
||||||
|
-- is 'a_unicode' a valid unicode based on the 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] = token_object_open or s [1] = token_array_open
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
feature {NONE} -- Constants
|
||||||
|
|
||||||
|
false_id: STRING = "false"
|
||||||
|
|
||||||
|
true_id: STRING = "true"
|
||||||
|
|
||||||
|
null_id: STRING = "null"
|
||||||
|
|
||||||
|
note
|
||||||
|
copyright: "2010-2015, Javier Velilla and others https://github.com/eiffelhub/json."
|
||||||
|
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
|
||||||
|
end
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
note
|
||||||
|
description: "Inherit to access restricted feature from {JSON_PARSER}."
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
deferred class
|
||||||
|
JSON_PARSER_ACCESS
|
||||||
|
|
||||||
|
note
|
||||||
|
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
|
||||||
|
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
|
||||||
|
end
|
||||||
@@ -20,13 +20,19 @@ feature {NONE} -- Initialization
|
|||||||
|
|
||||||
feature -- Commands
|
feature -- Commands
|
||||||
|
|
||||||
|
reset
|
||||||
|
-- Reset reader
|
||||||
|
do
|
||||||
|
index := 1
|
||||||
|
end
|
||||||
|
|
||||||
set_representation (a_json: STRING)
|
set_representation (a_json: STRING)
|
||||||
-- Set `representation'.
|
-- Set `representation'.
|
||||||
do
|
do
|
||||||
a_json.left_adjust
|
a_json.left_adjust
|
||||||
a_json.right_adjust
|
a_json.right_adjust
|
||||||
representation := a_json
|
representation := a_json
|
||||||
index := 1
|
reset
|
||||||
end
|
end
|
||||||
|
|
||||||
read: CHARACTER
|
read: CHARACTER
|
||||||
@@ -115,4 +121,7 @@ feature {NONE} -- Implementation
|
|||||||
invariant
|
invariant
|
||||||
representation_not_void: representation /= Void
|
representation_not_void: representation /= Void
|
||||||
|
|
||||||
|
note
|
||||||
|
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
|
||||||
|
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
|
||||||
end
|
end
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
note
|
||||||
|
description: "Token used by the JSON_PARSER"
|
||||||
|
author: "$Author$"
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
JSON_TOKENS
|
||||||
|
|
||||||
|
feature -- Access
|
||||||
|
|
||||||
|
token_object_open: CHARACTER = '{'
|
||||||
|
token_object_close: CHARACTER = '}'
|
||||||
|
|
||||||
|
token_array_open: CHARACTER = '['
|
||||||
|
token_array_close: CHARACTER = ']'
|
||||||
|
|
||||||
|
token_double_quote: CHARACTER = '"'
|
||||||
|
token_plus: CHARACTER = '+'
|
||||||
|
token_minus: CHARACTER = '-'
|
||||||
|
token_dot: CHARACTER = '.'
|
||||||
|
token_exp: CHARACTER = 'e'
|
||||||
|
token_comma: CHARACTER = ','
|
||||||
|
token_colon: CHARACTER = ':'
|
||||||
|
|
||||||
|
feature -- Status report
|
||||||
|
|
||||||
|
is_open_token (c: CHARACTER): BOOLEAN
|
||||||
|
-- Characters which open a type
|
||||||
|
do
|
||||||
|
inspect c
|
||||||
|
when token_object_open, token_array_open, token_double_quote, token_plus, token_minus, token_dot then
|
||||||
|
Result := True
|
||||||
|
else
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
is_close_token (c: CHARACTER): BOOLEAN
|
||||||
|
-- Characters which close a type
|
||||||
|
do
|
||||||
|
inspect c
|
||||||
|
when token_object_close, token_array_close, token_double_quote 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 '"', '%H' , '/', '%B', '%F', '%N', '%R', '%T' then -- '%H' = '\' = reverse solidus
|
||||||
|
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
|
||||||
|
|
||||||
|
is_exp_token (c: CHARACTER): BOOLEAN
|
||||||
|
-- Is number exposant token?
|
||||||
|
do
|
||||||
|
Result := c = token_exp or else c.as_lower = token_exp
|
||||||
|
end
|
||||||
|
|
||||||
|
note
|
||||||
|
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
|
||||||
|
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
|
||||||
|
end
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
note
|
||||||
|
description: "Objects that ..."
|
||||||
|
author: ""
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
JSON_FILE_READER
|
||||||
|
|
||||||
|
feature -- Access
|
||||||
|
|
||||||
|
read_json_from (a_path: READABLE_STRING_GENERAL): detachable STRING
|
||||||
|
local
|
||||||
|
l_file: PLAIN_TEXT_FILE
|
||||||
|
l_last_string: detachable STRING
|
||||||
|
l_file_count: INTEGER
|
||||||
|
l_fetch_done: BOOLEAN
|
||||||
|
do
|
||||||
|
create l_file.make_with_name (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.out + "' does not exist%N") -- FIXME: unicode may be truncated
|
||||||
|
else
|
||||||
|
if not l_file.is_readable then
|
||||||
|
print ("error: '" + a_path.out + "' is not readable.%N") -- FIXME: unicode may be truncated
|
||||||
|
else
|
||||||
|
l_file_count := l_file.count
|
||||||
|
l_file.open_read
|
||||||
|
from
|
||||||
|
create Result.make (l_file_count)
|
||||||
|
until
|
||||||
|
l_fetch_done
|
||||||
|
loop
|
||||||
|
l_file.read_stream (1_024)
|
||||||
|
l_last_string := l_file.last_string
|
||||||
|
l_fetch_done := l_file.exhausted or l_file.end_of_file or l_last_string.count < 1_024
|
||||||
|
if not l_last_string.is_empty then
|
||||||
|
Result.append (l_last_string)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
l_file.close
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
note
|
||||||
|
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
|
||||||
|
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
|
||||||
|
end
|
||||||
@@ -1,8 +1,5 @@
|
|||||||
note
|
note
|
||||||
description:
|
description: "JSON Iterator"
|
||||||
|
|
||||||
"JSON Iterator"
|
|
||||||
|
|
||||||
pattern: "Iterator visitor"
|
pattern: "Iterator visitor"
|
||||||
author: "Jocelyn Fiat"
|
author: "Jocelyn Fiat"
|
||||||
license: "MIT (see http://www.opensource.org/licenses/mit-license.php)"
|
license: "MIT (see http://www.opensource.org/licenses/mit-license.php)"
|
||||||
@@ -13,6 +10,7 @@ deferred class
|
|||||||
JSON_ITERATOR
|
JSON_ITERATOR
|
||||||
|
|
||||||
inherit
|
inherit
|
||||||
|
|
||||||
JSON_VISITOR
|
JSON_VISITOR
|
||||||
|
|
||||||
feature -- Visitor Pattern
|
feature -- Visitor Pattern
|
||||||
@@ -57,4 +55,7 @@ feature -- Visitor Pattern
|
|||||||
do
|
do
|
||||||
end
|
end
|
||||||
|
|
||||||
|
note
|
||||||
|
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
|
||||||
|
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
|
||||||
end
|
end
|
||||||
@@ -6,6 +6,7 @@ class
|
|||||||
JSON_PRETTY_STRING_VISITOR
|
JSON_PRETTY_STRING_VISITOR
|
||||||
|
|
||||||
inherit
|
inherit
|
||||||
|
|
||||||
JSON_VISITOR
|
JSON_VISITOR
|
||||||
|
|
||||||
create
|
create
|
||||||
@@ -26,21 +27,58 @@ feature -- Initialization
|
|||||||
output := a_output
|
output := a_output
|
||||||
create indentation.make_empty
|
create indentation.make_empty
|
||||||
indentation_step := "%T"
|
indentation_step := "%T"
|
||||||
|
|
||||||
object_count_inlining := a_object_count_inlining
|
object_count_inlining := a_object_count_inlining
|
||||||
array_count_inlining := a_array_count_inlining
|
array_count_inlining := a_array_count_inlining
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Access
|
feature -- Access
|
||||||
|
|
||||||
output: STRING_32
|
output: STRING_GENERAL
|
||||||
-- JSON representation
|
-- JSON representation
|
||||||
|
|
||||||
indentation: like output
|
feature -- Settings
|
||||||
|
|
||||||
indentation_step: like indentation
|
indentation_step: STRING
|
||||||
|
-- Text used for indentation.
|
||||||
|
--| by default a tabulation "%T"
|
||||||
|
|
||||||
line_number: INTEGER
|
object_count_inlining: INTEGER
|
||||||
|
-- Inline where object item count is under `object_count_inlining'.
|
||||||
|
--| ex 3:
|
||||||
|
--| { "a", "b", "c" }
|
||||||
|
--| ex 2:
|
||||||
|
--| {
|
||||||
|
--| "a",
|
||||||
|
--| "b",
|
||||||
|
--| "c"
|
||||||
|
--| }
|
||||||
|
|
||||||
|
array_count_inlining: INTEGER
|
||||||
|
-- Inline where array item count is under `object_count_inlining'.
|
||||||
|
|
||||||
|
feature -- Element change
|
||||||
|
|
||||||
|
set_indentation_step (a_step: STRING)
|
||||||
|
-- Set `indentation_step' to `a_step'.
|
||||||
|
do
|
||||||
|
indentation_step := a_step
|
||||||
|
end
|
||||||
|
|
||||||
|
set_object_count_inlining (a_nb: INTEGER)
|
||||||
|
-- Set `object_count_inlining' to `a_nb'.
|
||||||
|
do
|
||||||
|
object_count_inlining := a_nb
|
||||||
|
end
|
||||||
|
|
||||||
|
set_array_count_inlining (a_nb: INTEGER)
|
||||||
|
-- Set `array_count_inlining' to `a_nb'.
|
||||||
|
do
|
||||||
|
array_count_inlining := a_nb
|
||||||
|
end
|
||||||
|
|
||||||
|
feature {NONE} -- Implementation
|
||||||
|
|
||||||
|
indentation: STRING
|
||||||
|
|
||||||
indent
|
indent
|
||||||
do
|
do
|
||||||
@@ -59,8 +97,7 @@ feature -- Access
|
|||||||
line_number := line_number + 1
|
line_number := line_number + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
object_count_inlining: INTEGER
|
line_number: INTEGER
|
||||||
array_count_inlining: INTEGER
|
|
||||||
|
|
||||||
feature -- Visitor Pattern
|
feature -- Visitor Pattern
|
||||||
|
|
||||||
@@ -71,10 +108,14 @@ feature -- Visitor Pattern
|
|||||||
l_json_array: ARRAYED_LIST [JSON_VALUE]
|
l_json_array: ARRAYED_LIST [JSON_VALUE]
|
||||||
l_line: like line_number
|
l_line: like line_number
|
||||||
l_multiple_lines: BOOLEAN
|
l_multiple_lines: BOOLEAN
|
||||||
|
l_output: like output
|
||||||
do
|
do
|
||||||
|
l_output := output
|
||||||
l_json_array := a_json_array.array_representation
|
l_json_array := a_json_array.array_representation
|
||||||
l_multiple_lines := l_json_array.count >= array_count_inlining or across l_json_array as p some attached {JSON_OBJECT} p.item or attached {JSON_ARRAY} p.item end
|
l_multiple_lines := l_json_array.count >= array_count_inlining
|
||||||
output.append ("[")
|
or across l_json_array as p some attached {JSON_OBJECT} p.item or attached {JSON_ARRAY} p.item end
|
||||||
|
l_output.append_code (91) -- '[' : 91
|
||||||
|
|
||||||
l_line := line_number
|
l_line := line_number
|
||||||
indent
|
indent
|
||||||
from
|
from
|
||||||
@@ -82,27 +123,21 @@ feature -- Visitor Pattern
|
|||||||
until
|
until
|
||||||
l_json_array.off
|
l_json_array.off
|
||||||
loop
|
loop
|
||||||
if
|
if line_number > l_line or l_multiple_lines then
|
||||||
line_number > l_line or
|
|
||||||
l_multiple_lines
|
|
||||||
then
|
|
||||||
new_line
|
new_line
|
||||||
end
|
end
|
||||||
value := l_json_array.item
|
value := l_json_array.item
|
||||||
value.accept (Current)
|
value.accept (Current)
|
||||||
l_json_array.forth
|
l_json_array.forth
|
||||||
if not l_json_array.after then
|
if not l_json_array.after then
|
||||||
output.append (", ")
|
l_output.append (", ")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
exdent
|
exdent
|
||||||
if
|
if line_number > l_line or l_json_array.count >= array_count_inlining then
|
||||||
line_number > l_line or
|
|
||||||
l_json_array.count >= array_count_inlining
|
|
||||||
then
|
|
||||||
new_line
|
new_line
|
||||||
end
|
end
|
||||||
output.append ("]")
|
l_output.append_code (93) -- ']' : 93
|
||||||
end
|
end
|
||||||
|
|
||||||
visit_json_boolean (a_json_boolean: JSON_BOOLEAN)
|
visit_json_boolean (a_json_boolean: JSON_BOOLEAN)
|
||||||
@@ -129,10 +164,12 @@ feature -- Visitor Pattern
|
|||||||
l_pairs: HASH_TABLE [JSON_VALUE, JSON_STRING]
|
l_pairs: HASH_TABLE [JSON_VALUE, JSON_STRING]
|
||||||
l_line: like line_number
|
l_line: like line_number
|
||||||
l_multiple_lines: BOOLEAN
|
l_multiple_lines: BOOLEAN
|
||||||
|
l_output: like output
|
||||||
do
|
do
|
||||||
|
l_output := output
|
||||||
l_pairs := a_json_object.map_representation
|
l_pairs := a_json_object.map_representation
|
||||||
l_multiple_lines := l_pairs.count >= object_count_inlining or across l_pairs as p some attached {JSON_OBJECT} p.item or attached {JSON_ARRAY} p.item end
|
l_multiple_lines := l_pairs.count >= object_count_inlining or across l_pairs as p some attached {JSON_OBJECT} p.item or attached {JSON_ARRAY} p.item end
|
||||||
output.append ("{")
|
l_output.append_code (123) -- '{' : 123
|
||||||
l_line := line_number
|
l_line := line_number
|
||||||
indent
|
indent
|
||||||
from
|
from
|
||||||
@@ -140,36 +177,36 @@ feature -- Visitor Pattern
|
|||||||
until
|
until
|
||||||
l_pairs.off
|
l_pairs.off
|
||||||
loop
|
loop
|
||||||
if
|
if line_number > l_line or l_multiple_lines then
|
||||||
line_number > l_line or
|
|
||||||
l_multiple_lines
|
|
||||||
then
|
|
||||||
new_line
|
new_line
|
||||||
end
|
end
|
||||||
l_pairs.key_for_iteration.accept (Current)
|
l_pairs.key_for_iteration.accept (Current)
|
||||||
output.append (": ")
|
l_output.append (": ")
|
||||||
l_pairs.item_for_iteration.accept (Current)
|
l_pairs.item_for_iteration.accept (Current)
|
||||||
l_pairs.forth
|
l_pairs.forth
|
||||||
if not l_pairs.after then
|
if not l_pairs.after then
|
||||||
output.append (", ")
|
l_output.append (", ")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
exdent
|
exdent
|
||||||
if
|
if line_number > l_line or l_pairs.count >= object_count_inlining then
|
||||||
line_number > l_line or
|
|
||||||
l_pairs.count >= object_count_inlining
|
|
||||||
then
|
|
||||||
new_line
|
new_line
|
||||||
end
|
end
|
||||||
output.append ("}")
|
l_output.append_code (125) -- '}' : 125
|
||||||
end
|
end
|
||||||
|
|
||||||
visit_json_string (a_json_string: JSON_STRING)
|
visit_json_string (a_json_string: JSON_STRING)
|
||||||
-- Visit `a_json_string'.
|
-- Visit `a_json_string'.
|
||||||
|
local
|
||||||
|
l_output: like output
|
||||||
do
|
do
|
||||||
output.append ("%"")
|
l_output := output
|
||||||
output.append (a_json_string.item)
|
l_output.append_code (34) -- '%"' : 34
|
||||||
output.append ("%"")
|
l_output.append (a_json_string.item)
|
||||||
|
l_output.append_code (34) -- '%"' : 34
|
||||||
end
|
end
|
||||||
|
|
||||||
|
note
|
||||||
|
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
|
||||||
|
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
|
||||||
end
|
end
|
||||||
@@ -1,8 +1,5 @@
|
|||||||
note
|
note
|
||||||
description:
|
description: "JSON Visitor"
|
||||||
|
|
||||||
"JSON Visitor"
|
|
||||||
|
|
||||||
pattern: "Visitor"
|
pattern: "Visitor"
|
||||||
author: "Javier Velilla"
|
author: "Javier Velilla"
|
||||||
license: "MIT (see http://www.opensource.org/licenses/mit-license.php)"
|
license: "MIT (see http://www.opensource.org/licenses/mit-license.php)"
|
||||||
@@ -56,4 +53,7 @@ feature -- Visitor Pattern
|
|||||||
deferred
|
deferred
|
||||||
end
|
end
|
||||||
|
|
||||||
|
note
|
||||||
|
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
|
||||||
|
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
|
||||||
end
|
end
|
||||||
@@ -8,9 +8,11 @@ class
|
|||||||
PRINT_JSON_VISITOR
|
PRINT_JSON_VISITOR
|
||||||
|
|
||||||
inherit
|
inherit
|
||||||
|
|
||||||
JSON_VISITOR
|
JSON_VISITOR
|
||||||
|
|
||||||
create make
|
create
|
||||||
|
make
|
||||||
|
|
||||||
feature -- Initialization
|
feature -- Initialization
|
||||||
|
|
||||||
@@ -99,4 +101,7 @@ feature -- Visitor Pattern
|
|||||||
to_json.append ("%"")
|
to_json.append ("%"")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
note
|
||||||
|
copyright: "2010-2014, Javier Velilla and others https://github.com/eiffelhub/json."
|
||||||
|
license: "https://github.com/eiffelhub/json/blob/master/License.txt"
|
||||||
end
|
end
|
||||||
16
contrib/library/text/parser/json/package.iron
Normal file
16
contrib/library/text/parser/json/package.iron
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package json
|
||||||
|
|
||||||
|
project
|
||||||
|
json_safe = "library/json-safe.ecf"
|
||||||
|
json = "library/json.ecf"
|
||||||
|
json_gobo_extension = "library/json_gobo_extension.ecf"
|
||||||
|
|
||||||
|
note
|
||||||
|
title: Eiffel JSON
|
||||||
|
description: Eiffel JSON parser and visitors
|
||||||
|
tags: json,parser,text
|
||||||
|
license: MIT
|
||||||
|
copyright: Copyright (c) 2010-2014 Javier Velilla, Jocelyn Fiat and others,
|
||||||
|
link[github]: "project" https://github.com/eiffelhub/json
|
||||||
|
|
||||||
|
end
|
||||||
@@ -7,6 +7,7 @@ class
|
|||||||
APPLICATION
|
APPLICATION
|
||||||
|
|
||||||
inherit
|
inherit
|
||||||
|
|
||||||
ARGUMENTS
|
ARGUMENTS
|
||||||
|
|
||||||
create
|
create
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
class AUTHOR
|
class
|
||||||
|
AUTHOR
|
||||||
|
|
||||||
create
|
create
|
||||||
make
|
make
|
||||||
@@ -6,19 +7,26 @@ create
|
|||||||
feature {NONE} -- Initialization
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
make (a_name: STRING_32)
|
make (a_name: STRING_32)
|
||||||
|
-- Create an author with `a_name' as `name'.
|
||||||
do
|
do
|
||||||
set_name (a_name)
|
set_name (a_name)
|
||||||
|
ensure
|
||||||
|
name_set: name = a_name
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Access
|
feature -- Access
|
||||||
|
|
||||||
name: STRING_32
|
name: STRING_32
|
||||||
|
-- Author name
|
||||||
|
|
||||||
feature -- Status setting
|
feature -- Change
|
||||||
|
|
||||||
set_name (a_name: STRING_32)
|
set_name (a_name: STRING_32)
|
||||||
|
-- Set `name' with `a_name'.
|
||||||
do
|
do
|
||||||
name := a_name
|
name := a_name
|
||||||
|
ensure
|
||||||
|
name_set: name = a_name
|
||||||
end
|
end
|
||||||
|
|
||||||
end -- class AUTHOR
|
end -- class AUTHOR
|
||||||
|
|||||||
@@ -1,40 +1,59 @@
|
|||||||
class BOOK
|
class
|
||||||
|
BOOK
|
||||||
|
|
||||||
create
|
create
|
||||||
make
|
make
|
||||||
|
|
||||||
feature {NONE} -- Initialization
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
make (a_title: STRING_32; an_author: AUTHOR; an_isbn: STRING_32)
|
make (a_title: STRING_32; a_author: AUTHOR; a_isbn: STRING_32)
|
||||||
|
-- Create a book with `a_title' as `title',
|
||||||
|
-- `a_author' as `author', and `a_isbn' as `isbn'.
|
||||||
do
|
do
|
||||||
set_title (a_title)
|
set_title (a_title)
|
||||||
set_author (an_author)
|
set_author (a_author)
|
||||||
set_isbn (an_isbn)
|
set_isbn (a_isbn)
|
||||||
|
ensure
|
||||||
|
title_set: title = a_title
|
||||||
|
author_set: author = a_author
|
||||||
|
isbn_set: isbn = a_isbn
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Access
|
feature -- Access
|
||||||
|
|
||||||
title: STRING_32
|
title: STRING_32
|
||||||
|
-- Main title.
|
||||||
|
|
||||||
isbn: STRING_32
|
isbn: STRING_32
|
||||||
|
-- ISBN.
|
||||||
|
|
||||||
author: AUTHOR
|
author: AUTHOR
|
||||||
|
-- Author.
|
||||||
|
|
||||||
feature -- Status setting
|
feature -- Change
|
||||||
|
|
||||||
set_title (a_title: STRING_32)
|
set_title (a_title: STRING_32)
|
||||||
|
-- Set `title' with `a_title'.
|
||||||
do
|
do
|
||||||
title := a_title
|
title := a_title
|
||||||
|
ensure
|
||||||
|
title_set: title = a_title
|
||||||
end
|
end
|
||||||
|
|
||||||
set_author (an_author: AUTHOR)
|
set_author (a_author: AUTHOR)
|
||||||
|
-- Set `author' with `a_author'.
|
||||||
do
|
do
|
||||||
author := an_author
|
author := a_author
|
||||||
|
ensure
|
||||||
|
author_set: author = a_author
|
||||||
end
|
end
|
||||||
|
|
||||||
set_isbn (an_isbn: STRING_32)
|
set_isbn (a_isbn: STRING_32)
|
||||||
|
-- Set `isbn' with `a_isbn'.
|
||||||
do
|
do
|
||||||
isbn := an_isbn
|
isbn := a_isbn
|
||||||
|
ensure
|
||||||
|
isbn_set: isbn = a_isbn
|
||||||
end
|
end
|
||||||
|
|
||||||
end -- class BOOK
|
end -- class BOOK
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
class BOOK_COLLECTION
|
class
|
||||||
|
BOOK_COLLECTION
|
||||||
|
|
||||||
create
|
create
|
||||||
make
|
make
|
||||||
@@ -6,75 +7,76 @@ create
|
|||||||
feature {NONE} -- Initialization
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
make (a_name: STRING_32)
|
make (a_name: STRING_32)
|
||||||
|
-- Create a book collection with `a_name' as `name'.
|
||||||
do
|
do
|
||||||
set_name (a_name)
|
set_name (a_name)
|
||||||
create book_index.make (10)
|
create book_index.make (10)
|
||||||
|
ensure
|
||||||
|
name_set: name = a_name
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Access
|
feature -- Access
|
||||||
|
|
||||||
name: STRING_32
|
name: STRING_32
|
||||||
|
-- Name.
|
||||||
|
|
||||||
books: LIST [BOOK]
|
books: LIST [BOOK]
|
||||||
|
-- collection of book.
|
||||||
do
|
do
|
||||||
from
|
|
||||||
create {LINKED_LIST [BOOK]} Result.make
|
create {LINKED_LIST [BOOK]} Result.make
|
||||||
book_index.start
|
across
|
||||||
until
|
book_index as it
|
||||||
book_index.after
|
|
||||||
loop
|
loop
|
||||||
Result.append (book_index.item_for_iteration)
|
Result.append (it.item)
|
||||||
book_index.forth
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
books_by_author (an_author: STRING_32): detachable LIST [BOOK]
|
books_by_author (a_author: STRING_32): LIST [BOOK]
|
||||||
|
-- Books wrote by `a_author' in this collection.
|
||||||
do
|
do
|
||||||
if book_index.has (an_author) then
|
if attached book_index [a_author] as l_result then
|
||||||
Result := book_index @ an_author
|
Result := l_result
|
||||||
else
|
else
|
||||||
create {LINKED_LIST [BOOK]} Result.make
|
create {LINKED_LIST [BOOK]} Result.make
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Status setting
|
feature -- Change
|
||||||
|
|
||||||
set_name (a_name: STRING_32)
|
set_name (a_name: STRING_32)
|
||||||
|
-- Set `name' with `a_name'.
|
||||||
do
|
do
|
||||||
name := a_name
|
name := a_name
|
||||||
|
ensure
|
||||||
|
name_set: name = a_name
|
||||||
end
|
end
|
||||||
|
|
||||||
add_book (a_book: BOOK)
|
add_book (a_book: BOOK)
|
||||||
|
-- Extend collection with `a_book'.
|
||||||
local
|
local
|
||||||
l: detachable LIST [BOOK]
|
l: detachable LIST [BOOK]
|
||||||
do
|
do
|
||||||
if book_index.has (a_book.author.name) then
|
|
||||||
l := book_index.at (a_book.author.name)
|
l := book_index.at (a_book.author.name)
|
||||||
else
|
if l = Void then
|
||||||
create {LINKED_LIST [BOOK]} l.make
|
create {LINKED_LIST [BOOK]} l.make
|
||||||
book_index.put (l, a_book.author.name)
|
book_index.put (l, a_book.author.name)
|
||||||
end
|
end
|
||||||
if attached l as la then
|
l.force (a_book)
|
||||||
la.force (a_book)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
add_books (book_list: like books)
|
add_books (book_list: like books)
|
||||||
|
-- Append collection with `book_list'.
|
||||||
do
|
do
|
||||||
from
|
across
|
||||||
book_list.start
|
book_list as it
|
||||||
until
|
|
||||||
book_list.after
|
|
||||||
loop
|
loop
|
||||||
add_book (book_list.item)
|
add_book (it.item)
|
||||||
book_list.forth
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
feature {NONE} -- Implementation
|
feature {NONE} -- Implementation
|
||||||
|
|
||||||
book_index: HASH_TABLE [LIST [BOOK], STRING_32]
|
book_index: HASH_TABLE [LIST [BOOK], STRING_32]
|
||||||
|
-- Association of author name and its books.
|
||||||
|
|
||||||
end -- class BOOK_COLLECTION
|
end -- class BOOK_COLLECTION
|
||||||
|
|||||||
@@ -4,9 +4,11 @@ note
|
|||||||
date: "$Date$"
|
date: "$Date$"
|
||||||
revision: "$Revision$"
|
revision: "$Revision$"
|
||||||
|
|
||||||
class JSON_AUTHOR_CONVERTER
|
class
|
||||||
|
JSON_AUTHOR_CONVERTER
|
||||||
|
|
||||||
inherit
|
inherit
|
||||||
|
|
||||||
JSON_CONVERTER
|
JSON_CONVERTER
|
||||||
|
|
||||||
create
|
create
|
||||||
@@ -29,12 +31,10 @@ feature -- Access
|
|||||||
feature -- Conversion
|
feature -- Conversion
|
||||||
|
|
||||||
from_json (j: like to_json): detachable like object
|
from_json (j: like to_json): detachable like object
|
||||||
local
|
|
||||||
ucs: detachable STRING_32
|
|
||||||
do
|
do
|
||||||
ucs ?= json.object (j.item (name_key), Void)
|
if attached {STRING_32} json.object (j.item (name_key), Void) as l_name then
|
||||||
check ucs /= Void end
|
create Result.make (l_name)
|
||||||
create Result.make (ucs)
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
to_json (o: like object): JSON_OBJECT
|
to_json (o: like object): JSON_OBJECT
|
||||||
@@ -46,8 +46,9 @@ feature -- Conversion
|
|||||||
feature {NONE} -- Implementation
|
feature {NONE} -- Implementation
|
||||||
|
|
||||||
name_key: JSON_STRING
|
name_key: JSON_STRING
|
||||||
|
-- Author's name label.
|
||||||
once
|
once
|
||||||
create Result.make_json ("name")
|
create Result.make_from_string ("name")
|
||||||
end
|
end
|
||||||
|
|
||||||
end -- class JSON_AUTHOR_CONVERTER
|
end -- class JSON_AUTHOR_CONVERTER
|
||||||
|
|||||||
@@ -4,9 +4,11 @@ note
|
|||||||
date: "$Date$"
|
date: "$Date$"
|
||||||
revision: "$Revision$"
|
revision: "$Revision$"
|
||||||
|
|
||||||
class JSON_BOOK_COLLECTION_CONVERTER
|
class
|
||||||
|
JSON_BOOK_COLLECTION_CONVERTER
|
||||||
|
|
||||||
inherit
|
inherit
|
||||||
|
|
||||||
JSON_CONVERTER
|
JSON_CONVERTER
|
||||||
|
|
||||||
create
|
create
|
||||||
@@ -30,35 +32,35 @@ feature -- Conversion
|
|||||||
|
|
||||||
from_json (j: like to_json): detachable like object
|
from_json (j: like to_json): detachable like object
|
||||||
local
|
local
|
||||||
ucs: detachable STRING_32
|
l_books: LINKED_LIST [BOOK]
|
||||||
ll: LINKED_LIST [BOOK]
|
|
||||||
b: detachable BOOK
|
|
||||||
ja: detachable JSON_ARRAY
|
|
||||||
i: INTEGER
|
|
||||||
do
|
do
|
||||||
ucs ?= json.object (j.item (name_key), Void)
|
if
|
||||||
check ucs /= Void end
|
attached {STRING_32} json.object (j.item (name_key), Void) as l_name and
|
||||||
create Result.make (ucs)
|
attached {JSON_ARRAY} j.item (books_key) as l_json_array
|
||||||
ja ?= j.item (books_key)
|
then
|
||||||
check ja /= Void end
|
create Result.make (l_name)
|
||||||
from
|
create l_books.make
|
||||||
i := 1
|
across
|
||||||
create ll.make
|
l_json_array as it
|
||||||
until
|
until
|
||||||
i > ja.count
|
Result = Void
|
||||||
loop
|
loop
|
||||||
b ?= json.object (ja [i], "BOOK")
|
if attached {BOOK} json.object (it.item, "BOOK") as l_book then
|
||||||
check b /= Void end
|
l_books.extend (l_book)
|
||||||
ll.force (b)
|
else
|
||||||
i := i + 1
|
Result := Void
|
||||||
|
-- Failed
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if Result /= Void then
|
||||||
|
Result.add_books (l_books)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
check ll /= Void end
|
|
||||||
Result.add_books (ll)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
to_json (o: like object): JSON_OBJECT
|
to_json (o: like object): JSON_OBJECT
|
||||||
do
|
do
|
||||||
create Result.make
|
create Result.make_with_capacity (2)
|
||||||
Result.put (json.value (o.name), name_key)
|
Result.put (json.value (o.name), name_key)
|
||||||
Result.put (json.value (o.books), books_key)
|
Result.put (json.value (o.books), books_key)
|
||||||
end
|
end
|
||||||
@@ -66,13 +68,15 @@ feature -- Conversion
|
|||||||
feature {NONE} -- Implementation
|
feature {NONE} -- Implementation
|
||||||
|
|
||||||
name_key: JSON_STRING
|
name_key: JSON_STRING
|
||||||
|
-- Collection's name label.
|
||||||
once
|
once
|
||||||
create Result.make_json ("name")
|
create Result.make_from_string ("name")
|
||||||
end
|
end
|
||||||
|
|
||||||
books_key: JSON_STRING
|
books_key: JSON_STRING
|
||||||
|
-- Book list label.
|
||||||
once
|
once
|
||||||
create Result.make_json ("books")
|
create Result.make_from_string ("books")
|
||||||
end
|
end
|
||||||
|
|
||||||
end -- class JSON_BOOK_COLLECTION_CONVERTER
|
end -- class JSON_BOOK_COLLECTION_CONVERTER
|
||||||
|
|||||||
@@ -4,9 +4,11 @@ note
|
|||||||
date: "$Date$"
|
date: "$Date$"
|
||||||
revision: "$Revision$"
|
revision: "$Revision$"
|
||||||
|
|
||||||
class JSON_BOOK_CONVERTER
|
class
|
||||||
|
JSON_BOOK_CONVERTER
|
||||||
|
|
||||||
inherit
|
inherit
|
||||||
|
|
||||||
JSON_CONVERTER
|
JSON_CONVERTER
|
||||||
|
|
||||||
create
|
create
|
||||||
@@ -31,22 +33,19 @@ feature -- Access
|
|||||||
feature -- Conversion
|
feature -- Conversion
|
||||||
|
|
||||||
from_json (j: like to_json): detachable like object
|
from_json (j: like to_json): detachable like object
|
||||||
local
|
|
||||||
ucs1, ucs2: detachable STRING_32
|
|
||||||
a: detachable AUTHOR
|
|
||||||
do
|
do
|
||||||
ucs1 ?= json.object (j.item (title_key), Void)
|
if
|
||||||
check ucs1 /= Void end
|
attached {STRING_32} json.object (j.item (title_key), Void) as l_title and
|
||||||
ucs2 ?= json.object (j.item (isbn_key), Void)
|
attached {STRING_32} json.object (j.item (isbn_key), Void) as l_isbn and
|
||||||
check ucs2 /= Void end
|
attached {AUTHOR} json.object (j.item (author_key), "AUTHOR") as l_author
|
||||||
a ?= json.object (j.item (author_key), "AUTHOR")
|
then
|
||||||
check a /= Void end
|
create Result.make (l_title, l_author, l_isbn)
|
||||||
create Result.make (ucs1, a, ucs2)
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
to_json (o: like object): JSON_OBJECT
|
to_json (o: like object): JSON_OBJECT
|
||||||
do
|
do
|
||||||
create Result.make
|
create Result.make_with_capacity (3)
|
||||||
Result.put (json.value (o.title), title_key)
|
Result.put (json.value (o.title), title_key)
|
||||||
Result.put (json.value (o.isbn), isbn_key)
|
Result.put (json.value (o.isbn), isbn_key)
|
||||||
Result.put (json.value (o.author), author_key)
|
Result.put (json.value (o.author), author_key)
|
||||||
@@ -55,18 +54,21 @@ feature -- Conversion
|
|||||||
feature {NONE} -- Implementation
|
feature {NONE} -- Implementation
|
||||||
|
|
||||||
title_key: JSON_STRING
|
title_key: JSON_STRING
|
||||||
|
-- Book's title label.
|
||||||
once
|
once
|
||||||
create Result.make_json ("title")
|
create Result.make_from_string ("title")
|
||||||
end
|
end
|
||||||
|
|
||||||
isbn_key: JSON_STRING
|
isbn_key: JSON_STRING
|
||||||
|
-- Book ISBN label.
|
||||||
once
|
once
|
||||||
create Result.make_json ("isbn")
|
create Result.make_from_string ("isbn")
|
||||||
end
|
end
|
||||||
|
|
||||||
author_key: JSON_STRING
|
author_key: JSON_STRING
|
||||||
|
-- Author label.
|
||||||
once
|
once
|
||||||
create Result.make_json ("author")
|
create Result.make_from_string ("author")
|
||||||
end
|
end
|
||||||
|
|
||||||
end -- class JSON_BOOK_CONVERTER
|
end -- class JSON_BOOK_CONVERTER
|
||||||
|
|||||||
@@ -1,73 +1,71 @@
|
|||||||
class TEST_DS
|
note
|
||||||
|
description: "Linked list and hash table converters test."
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
TEST_DS
|
||||||
|
|
||||||
inherit
|
inherit
|
||||||
SHARED_EJSON
|
|
||||||
rename default_create as shared_default_create end
|
|
||||||
EQA_TEST_SET
|
|
||||||
select default_create end
|
|
||||||
|
|
||||||
|
SHARED_EJSON
|
||||||
|
undefine
|
||||||
|
default_create
|
||||||
|
end
|
||||||
|
|
||||||
|
EQA_TEST_SET
|
||||||
|
|
||||||
feature -- Test
|
feature -- Test
|
||||||
|
|
||||||
test_linked_list_converter
|
test_linked_list_converter
|
||||||
|
-- Convert a linked list to a json value and
|
||||||
|
-- convert this one to a linked list.
|
||||||
local
|
local
|
||||||
jc: JSON_LINKED_LIST_CONVERTER
|
|
||||||
l: LINKED_LIST [STRING]
|
l: LINKED_LIST [STRING]
|
||||||
l2: detachable LINKED_LIST [detachable ANY]
|
|
||||||
s: STRING
|
s: STRING
|
||||||
jv: detachable JSON_VALUE
|
|
||||||
do
|
do
|
||||||
create jc.make
|
|
||||||
json.add_converter (jc)
|
|
||||||
create l.make
|
create l.make
|
||||||
s := "foo"
|
l.force ("foo")
|
||||||
l.force (s)
|
l.force ("bar")
|
||||||
s := "bar"
|
if attached json.value (l) as l_value then
|
||||||
l.force (s)
|
s := l_value.representation
|
||||||
jv := json.value (l)
|
assert ("JSON array converted to LINKED_LIST", attached {LINKED_LIST [detachable ANY]} json.object (l_value, "LINKED_LIST"))
|
||||||
assert ("jv /= Void", jv /= Void)
|
else
|
||||||
if attached jv as l_jv then
|
assert ("LINKED_LIST converted to a JSON value", False)
|
||||||
s := jv.representation
|
|
||||||
l2 ?= json.object (jv, "LINKED_LIST")
|
|
||||||
assert ("l2 /= Void", l2 /= Void)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test_hash_table_converter
|
test_hash_table_converter
|
||||||
|
-- Convert a hash table to a json value and
|
||||||
|
-- convert this one to a hash table.
|
||||||
local
|
local
|
||||||
tc: JSON_HASH_TABLE_CONVERTER
|
|
||||||
t: HASH_TABLE [STRING, STRING]
|
t: HASH_TABLE [STRING, STRING]
|
||||||
t2: detachable HASH_TABLE [ANY, HASHABLE]
|
|
||||||
s: STRING
|
s: STRING
|
||||||
ucs_key, ucs_value: detachable STRING_32
|
l_ucs_key: detachable STRING_32
|
||||||
jv: detachable JSON_VALUE
|
|
||||||
do
|
do
|
||||||
create tc.make
|
|
||||||
json.add_converter (tc)
|
|
||||||
create t.make (2)
|
create t.make (2)
|
||||||
t.put ("foo", "1")
|
t.put ("foo", "1")
|
||||||
t.put ("bar", "2")
|
t.put ("bar", "2")
|
||||||
jv := json.value (t)
|
if attached json.value (t) as l_value then
|
||||||
assert ("jv /= Void", jv /= Void)
|
s := l_value.representation
|
||||||
if attached jv as l_jv then
|
if attached {HASH_TABLE [ANY, HASHABLE]} json.object (l_value, "HASH_TABLE") as t2 then
|
||||||
s := l_jv.representation
|
create l_ucs_key.make_from_string ("1")
|
||||||
t2 ?= json.object (l_jv, "HASH_TABLE")
|
if attached {STRING_32} t2 [l_ucs_key] as l_ucs_value then
|
||||||
assert ("t2 /= Void", t2 /= Void)
|
assert ("ucs_value.string.is_equal (%"foo%")", l_ucs_value.same_string_general ("foo"))
|
||||||
|
else
|
||||||
|
assert ("ucs_value /= Void", False)
|
||||||
end
|
end
|
||||||
create ucs_key.make_from_string ("1")
|
create l_ucs_key.make_from_string ("2")
|
||||||
if attached t2 as l_t2 then
|
if attached {STRING_32} t2 [l_ucs_key] as l_ucs_value then
|
||||||
ucs_value ?= t2 @ ucs_key
|
assert ("ucs_value.string.is_equal (%"bar%")", l_ucs_value.same_string_general ("bar"))
|
||||||
assert ("ucs_value /= Void", ucs_value /= Void)
|
else
|
||||||
if attached ucs_value as l_ucs_value then
|
assert ("ucs_value /= Void", False)
|
||||||
assert ("ucs_value.string.is_equal (%"foo%")", l_ucs_value.string.is_equal ("foo"))
|
|
||||||
end
|
end
|
||||||
create ucs_key.make_from_string ("2")
|
else
|
||||||
ucs_value ?= t2 @ ucs_key
|
assert ("JSON object converted to HASH_TABLE", False);
|
||||||
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
|
||||||
|
else
|
||||||
|
assert ("HASH_TABLE converted to a JSON value", False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,19 @@
|
|||||||
class TEST_JSON_CORE
|
class
|
||||||
|
TEST_JSON_CORE
|
||||||
|
|
||||||
inherit
|
inherit
|
||||||
|
|
||||||
SHARED_EJSON
|
SHARED_EJSON
|
||||||
rename default_create as shared_default_create end
|
undefine
|
||||||
|
default_create
|
||||||
|
end
|
||||||
|
|
||||||
EQA_TEST_SET
|
EQA_TEST_SET
|
||||||
select default_create end
|
|
||||||
|
JSON_PARSER_ACCESS
|
||||||
|
undefine
|
||||||
|
default_create
|
||||||
|
end
|
||||||
|
|
||||||
feature -- Test
|
feature -- Test
|
||||||
|
|
||||||
@@ -31,15 +40,15 @@ feature -- Test
|
|||||||
-- that can represent the value of the JSON number, in this case
|
-- that can represent the value of the JSON number, in this case
|
||||||
-- we know it is INTEGER_8 since the value is 42
|
-- we know it is INTEGER_8 since the value is 42
|
||||||
jrep := "42"
|
jrep := "42"
|
||||||
create parser.make_parser (jrep)
|
create parser.make_with_string (jrep)
|
||||||
if attached {JSON_NUMBER} parser.parse as l_jn then
|
if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then
|
||||||
if attached {INTEGER_8} json.object (jn, Void) as l_i8 then
|
if attached {INTEGER_8} json.object (jn, Void) as l_i8 then
|
||||||
assert ("l_i8 = 42", l_i8 = 42)
|
assert ("l_i8 = 42", l_i8 = 42)
|
||||||
else
|
else
|
||||||
assert ("json.object (jn, Void) is a INTEGER_8", False)
|
assert ("json.object (jn, Void) is a INTEGER_8", False)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
assert ("parser.parse is a JSON_NUMBER", False)
|
assert ("parser.next_parsed_json_value is a JSON_NUMBER", False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -66,15 +75,15 @@ feature -- Test
|
|||||||
-- that can represent the value of the JSON number, in this case
|
-- that can represent the value of the JSON number, in this case
|
||||||
-- we know it is INTEGER_8 since the value is 42
|
-- we know it is INTEGER_8 since the value is 42
|
||||||
jrep := "42"
|
jrep := "42"
|
||||||
create parser.make_parser (jrep)
|
create parser.make_with_string (jrep)
|
||||||
if attached {JSON_NUMBER} parser.parse as l_jn then
|
if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then
|
||||||
if attached {INTEGER_8} json.object (jn, Void) as l_i8 then
|
if attached {INTEGER_8} json.object (jn, Void) as l_i8 then
|
||||||
assert ("l_i8 = 42", l_i8 = 42)
|
assert ("l_i8 = 42", l_i8 = 42)
|
||||||
else
|
else
|
||||||
assert ("json.object (jn, Void) is a INTEGER_8", False)
|
assert ("json.object (jn, Void) is a INTEGER_8", False)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
assert ("parser.parse is a JSON_NUMBER", False)
|
assert ("parser.next_parsed_json_value is a JSON_NUMBER", False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -101,15 +110,15 @@ feature -- Test
|
|||||||
-- that can represent the value of the JSON number, in this case
|
-- that can represent the value of the JSON number, in this case
|
||||||
-- we know it is INTEGER_16 since the value is 300
|
-- we know it is INTEGER_16 since the value is 300
|
||||||
jrep := "300"
|
jrep := "300"
|
||||||
create parser.make_parser (jrep)
|
create parser.make_with_string (jrep)
|
||||||
if attached {JSON_NUMBER} parser.parse as l_jn then
|
if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then
|
||||||
if attached {INTEGER_16} json.object (jn, Void) as l_i16 then
|
if attached {INTEGER_16} json.object (jn, Void) as l_i16 then
|
||||||
assert ("l_i16 = 300", l_i16 = 300)
|
assert ("l_i16 = 300", l_i16 = 300)
|
||||||
else
|
else
|
||||||
assert ("json.object (jn, Void) is a INTEGER_16", False)
|
assert ("json.object (jn, Void) is a INTEGER_16", False)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
assert ("parser.parse is a JSON_NUMBER", False)
|
assert ("parser.next_parsed_json_value is a JSON_NUMBER", False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -136,15 +145,15 @@ feature -- Test
|
|||||||
-- that can represent the value of the JSON number, in this case
|
-- that can represent the value of the JSON number, in this case
|
||||||
-- we know it is INTEGER_32 since the value is 100000
|
-- we know it is INTEGER_32 since the value is 100000
|
||||||
jrep := "100000"
|
jrep := "100000"
|
||||||
create parser.make_parser (jrep)
|
create parser.make_with_string (jrep)
|
||||||
if attached {JSON_NUMBER} parser.parse as l_jn then
|
if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then
|
||||||
if attached {INTEGER_32} json.object (jn, Void) as l_i32 then
|
if attached {INTEGER_32} json.object (jn, Void) as l_i32 then
|
||||||
assert ("l_i32 = 100000", l_i32 = 100000)
|
assert ("l_i32 = 100000", l_i32 = 100000)
|
||||||
else
|
else
|
||||||
assert ("json.object (jn, Void) is a INTEGER_32", False)
|
assert ("json.object (jn, Void) is a INTEGER_32", False)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
assert ("parser.parse is a JSON_NUMBER", False)
|
assert ("parser.next_parsed_json_value is a JSON_NUMBER", False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -171,15 +180,15 @@ feature -- Test
|
|||||||
-- that can represent the value of the JSON number, in this case
|
-- that can represent the value of the JSON number, in this case
|
||||||
-- we know it is INTEGER_32 since the value is 42949672960
|
-- we know it is INTEGER_32 since the value is 42949672960
|
||||||
jrep := "42949672960"
|
jrep := "42949672960"
|
||||||
create parser.make_parser (jrep)
|
create parser.make_with_string (jrep)
|
||||||
if attached {JSON_NUMBER} parser.parse as l_jn then
|
if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then
|
||||||
if attached {INTEGER_64} json.object (jn, Void) as l_i64 then
|
if attached {INTEGER_64} json.object (jn, Void) as l_i64 then
|
||||||
assert ("l_i64 = 42949672960", l_i64 = 42949672960)
|
assert ("l_i64 = 42949672960", l_i64 = 42949672960)
|
||||||
else
|
else
|
||||||
assert ("json.object (jn, Void) is a INTEGER_64", False)
|
assert ("json.object (jn, Void) is a INTEGER_64", False)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
assert ("parser.parse is a JSON_NUMBER", False)
|
assert ("parser.next_parsed_json_value is a JSON_NUMBER", False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -206,15 +215,15 @@ feature -- Test
|
|||||||
-- that can represent the value of the JSON number, in this case
|
-- that can represent the value of the JSON number, in this case
|
||||||
-- we know it is INTEGER_16 since the value is 200
|
-- we know it is INTEGER_16 since the value is 200
|
||||||
jrep := "200"
|
jrep := "200"
|
||||||
create parser.make_parser (jrep)
|
create parser.make_with_string (jrep)
|
||||||
if attached {JSON_NUMBER} parser.parse as l_jn then
|
if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then
|
||||||
if attached {INTEGER_16} json.object (jn, Void) as i16 then
|
if attached {INTEGER_16} json.object (jn, Void) as i16 then
|
||||||
assert ("i16 = 200", i16 = 200)
|
assert ("i16 = 200", i16 = 200)
|
||||||
else
|
else
|
||||||
assert ("json.object (jn, Void) is an INTEGER_16", False)
|
assert ("json.object (jn, Void) is an INTEGER_16", False)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
assert ("parser.parse is a JSON_NUMBER", False)
|
assert ("parser.next_parsed_json_value is a JSON_NUMBER", False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -241,15 +250,15 @@ feature -- Test
|
|||||||
-- that can represent the value of the JSON number, in this case
|
-- that can represent the value of the JSON number, in this case
|
||||||
-- we know it is INTEGER_32 since the value is 32768
|
-- we know it is INTEGER_32 since the value is 32768
|
||||||
jrep := "32768"
|
jrep := "32768"
|
||||||
create parser.make_parser (jrep)
|
create parser.make_with_string (jrep)
|
||||||
if attached {JSON_NUMBER} parser.parse as l_jn then
|
if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then
|
||||||
if attached {INTEGER_32} json.object (jn, Void) as i32 then
|
if attached {INTEGER_32} json.object (jn, Void) as i32 then
|
||||||
assert ("i32 = 32768", i32 = 32768)
|
assert ("i32 = 32768", i32 = 32768)
|
||||||
else
|
else
|
||||||
assert ("json.object (jn, Void) is a INTEGER_32", False)
|
assert ("json.object (jn, Void) is a INTEGER_32", False)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
assert ("parser.parse is a JSON_NUMBER", False)
|
assert ("parser.next_parsed_json_value is a JSON_NUMBER", False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -276,15 +285,15 @@ feature -- Test
|
|||||||
-- that can represent the value of the JSON number, in this case
|
-- that can represent the value of the JSON number, in this case
|
||||||
-- we know it is INTEGER_64 since the value is 2147483648
|
-- we know it is INTEGER_64 since the value is 2147483648
|
||||||
jrep := "2147483648"
|
jrep := "2147483648"
|
||||||
create parser.make_parser (jrep)
|
create parser.make_with_string (jrep)
|
||||||
if attached {JSON_NUMBER} parser.parse as l_jn then
|
if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then
|
||||||
if attached {INTEGER_64} json.object (jn, Void) as i64 then
|
if attached {INTEGER_64} json.object (jn, Void) as i64 then
|
||||||
assert ("i64 = 2147483648", i64 = 2147483648)
|
assert ("i64 = 2147483648", i64 = 2147483648)
|
||||||
else
|
else
|
||||||
assert ("json.object (jn, Void) is a INTEGER_64", False)
|
assert ("json.object (jn, Void) is a INTEGER_64", False)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
assert ("parser.parse is a JSON_NUMBER", False)
|
assert ("parser.next_parsed_json_value is a JSON_NUMBER", False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -311,15 +320,15 @@ feature -- Test
|
|||||||
-- that can represent the value of the JSON number, in this case
|
-- that can represent the value of the JSON number, in this case
|
||||||
-- we know it is INTEGER_32 since the value is 42949672960
|
-- 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
|
jrep := "9223372036854775808" -- 1 higher than largest positive number that can be represented by INTEGER 64
|
||||||
create parser.make_parser (jrep)
|
create parser.make_with_string (jrep)
|
||||||
if attached {JSON_NUMBER} parser.parse as l_jn then
|
if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then
|
||||||
if attached {NATURAL_64} json.object (jn, Void) as l_n64 then
|
if attached {NATURAL_64} json.object (jn, Void) as l_n64 then
|
||||||
assert ("l_n64 = 9223372036854775808", l_n64 = 9223372036854775808)
|
assert ("l_n64 = 9223372036854775808", l_n64 = 9223372036854775808)
|
||||||
else
|
else
|
||||||
assert ("json.object (jn, Void) is a NATURAL_64", False)
|
assert ("json.object (jn, Void) is a NATURAL_64", False)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
assert ("parser.parse is a JSON_NUMBER", False)
|
assert ("parser.next_parsed_json_value is a JSON_NUMBER", False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -345,15 +354,15 @@ feature -- Test
|
|||||||
-- Note: The JSON_FACTORY will always return a REAL_64 if the value
|
-- Note: The JSON_FACTORY will always return a REAL_64 if the value
|
||||||
-- of the JSON number is a floating point number
|
-- of the JSON number is a floating point number
|
||||||
jrep := "3.14"
|
jrep := "3.14"
|
||||||
create parser.make_parser (jrep)
|
create parser.make_with_string (jrep)
|
||||||
if attached {JSON_NUMBER} parser.parse as l_jn then
|
if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then
|
||||||
if attached {REAL_64} json.object (jn, Void) as r64 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)
|
assert ("3.14 <= r64 and r64 <= 3.141", 3.14 <= r64 and r64 <= 3.141)
|
||||||
else
|
else
|
||||||
assert ("json.object (jn, Void) is a REAL_64", False)
|
assert ("json.object (jn, Void) is a REAL_64", False)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
assert ("parser.parse is a JSON_NUMBER", False)
|
assert ("parser.next_parsed_json_value is a JSON_NUMBER", False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -377,15 +386,15 @@ feature -- Test
|
|||||||
|
|
||||||
-- JSON representation -> JSON value -> Eiffel value
|
-- JSON representation -> JSON value -> Eiffel value
|
||||||
jrep := "3.1400001049041748"
|
jrep := "3.1400001049041748"
|
||||||
create parser.make_parser (jrep)
|
create parser.make_with_string (jrep)
|
||||||
if attached {JSON_NUMBER} parser.parse as l_jn then
|
if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then
|
||||||
if attached {REAL_64} json.object (l_jn, Void) as r64 then
|
if attached {REAL_64} json.object (l_jn, Void) as r64 then
|
||||||
assert ("r64 = 3.1400001049041748", r64 = 3.1400001049041748)
|
assert ("r64 = 3.1400001049041748", r64 = 3.1400001049041748)
|
||||||
else
|
else
|
||||||
assert ("json.object (l_jn, Void) is a REAL_64", False)
|
assert ("json.object (l_jn, Void) is a REAL_64", False)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
assert ("parser.parse is a JSON_NUMBER", False)
|
assert ("parser.next_parsed_json_value is a JSON_NUMBER", False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -410,15 +419,15 @@ feature -- Test
|
|||||||
|
|
||||||
-- JSON representation -> JSON value -> Eiffel value
|
-- JSON representation -> JSON value -> Eiffel value
|
||||||
jrep := "3.1415926535897931"
|
jrep := "3.1415926535897931"
|
||||||
create parser.make_parser (jrep)
|
create parser.make_with_string (jrep)
|
||||||
if attached {JSON_NUMBER} parser.parse as l_jn then
|
if attached {JSON_NUMBER} parser.next_parsed_json_value as l_jn then
|
||||||
if attached {REAL_64} json.object (jn, Void) as l_r64 then
|
if attached {REAL_64} json.object (jn, Void) as l_r64 then
|
||||||
assert ("l_r64 = 3.1415926535897931", l_r64 = 3.1415926535897931)
|
assert ("l_r64 = 3.1415926535897931", l_r64 = 3.1415926535897931)
|
||||||
else
|
else
|
||||||
assert ("json.object (jn, Void) is a REAL_64", False)
|
assert ("json.object (jn, Void) is a REAL_64", False)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
assert ("parser.parse is a JSON_NUMBER", False)
|
assert ("parser.next_parsed_json_value is a JSON_NUMBER", False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -430,7 +439,7 @@ feature -- Test
|
|||||||
do
|
do
|
||||||
-- Eiffel value -> JSON value -> JSON representation
|
-- Eiffel value -> JSON value -> JSON representation
|
||||||
b := True
|
b := True
|
||||||
create jb.make_boolean (b)
|
create jb.make (b)
|
||||||
assert ("jb.representation.is_equal (%"true%")", jb.representation.is_equal ("true"))
|
assert ("jb.representation.is_equal (%"true%")", jb.representation.is_equal ("true"))
|
||||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||||
if attached {JSON_BOOLEAN} json.value (b) as l_jb then
|
if attached {JSON_BOOLEAN} json.value (b) as l_jb then
|
||||||
@@ -440,20 +449,20 @@ feature -- Test
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- JSON representation -> JSON value -> Eiffel value
|
-- JSON representation -> JSON value -> Eiffel value
|
||||||
create parser.make_parser ("true")
|
create parser.make_with_string ("true")
|
||||||
if attached {JSON_BOOLEAN} parser.parse as l_jb then
|
if attached {JSON_BOOLEAN} parser.next_parsed_json_value as l_jb then
|
||||||
if attached {BOOLEAN} json.object (l_jb, Void) as l_b then
|
if attached {BOOLEAN} json.object (l_jb, Void) as l_b then
|
||||||
assert ("l_b = True", l_b = True)
|
assert ("l_b = True", l_b = True)
|
||||||
else
|
else
|
||||||
assert ("json.object (l_jb, Void) is BOOLEAN", False)
|
assert ("json.object (l_jb, Void) is BOOLEAN", False)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
assert ("parser.parse is a JSON_BOOLEAN", False)
|
assert ("parser.next_parsed_json_value is a JSON_BOOLEAN", False)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Eiffel value -> JSON value -> JSON representation
|
-- Eiffel value -> JSON value -> JSON representation
|
||||||
b := False
|
b := False
|
||||||
create jb.make_boolean (b)
|
create jb.make (b)
|
||||||
assert ("jb.representation.same_string (%"false%")", jb.representation.same_string ("false"))
|
assert ("jb.representation.same_string (%"false%")", jb.representation.same_string ("false"))
|
||||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||||
if attached {JSON_BOOLEAN} json.value (b) as l_jb then
|
if attached {JSON_BOOLEAN} json.value (b) as l_jb then
|
||||||
@@ -463,78 +472,72 @@ feature -- Test
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- JSON representation -> JSON value -> Eiffel value
|
-- JSON representation -> JSON value -> Eiffel value
|
||||||
create parser.make_parser ("false")
|
create parser.make_with_string ("false")
|
||||||
if attached {JSON_BOOLEAN} parser.parse as l_jb then
|
if attached {JSON_BOOLEAN} parser.next_parsed_json_value as l_jb then
|
||||||
if attached {BOOLEAN} json.object (l_jb, Void) as l_b then
|
if attached {BOOLEAN} json.object (l_jb, Void) as l_b then
|
||||||
assert ("l_b = False", l_b = False)
|
assert ("l_b = False", l_b = False)
|
||||||
else
|
else
|
||||||
assert ("json.object (l_jb, Void) is a BOOLEAN", False)
|
assert ("json.object (l_jb, Void) is a BOOLEAN", False)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
assert ("parser.parse is a JSON_BOOLEAN", False)
|
assert ("parser.next_parsed_json_value is a JSON_BOOLEAN", False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test_json_null
|
test_json_null
|
||||||
local
|
local
|
||||||
a: detachable ANY
|
|
||||||
dummy_object: STRING
|
|
||||||
jn: detachable JSON_NULL
|
|
||||||
jrep: STRING
|
jrep: STRING
|
||||||
|
jn: JSON_NULL
|
||||||
parser: JSON_PARSER
|
parser: JSON_PARSER
|
||||||
do
|
do
|
||||||
-- Eiffel value -> JSON value -> JSON representation
|
-- Eiffel value -> JSON value -> JSON representation
|
||||||
create jn
|
create jn
|
||||||
assert ("jn /= Void", jn /= Void)
|
jrep := "null"
|
||||||
assert ("jn.representation.is_equal (%"%"null%"%")", jn.representation.is_equal ("null"))
|
assert ("jn.representation.is_equal (%"%"null%"%")", jn.representation.is_equal (jrep))
|
||||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||||
jn ?= json.value (Void)
|
if attached {JSON_NULL} json.value (Void) as l_json_null then
|
||||||
assert ("jn /= Void", jn /= Void)
|
assert ("jn.representation.is_equal (%"null%")", l_json_null.representation.is_equal ("null"))
|
||||||
if attached jn as l_jn then
|
else
|
||||||
assert ("jn.representation.is_equal (%"null%")", l_jn.representation.is_equal ("null"))
|
assert ("json.value (Void) /= Void", False)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- JSON representation -> JSON value -> Eiffel value
|
-- JSON representation -> JSON value -> Eiffel value
|
||||||
jrep := "null"
|
create parser.make_with_string (jrep)
|
||||||
create parser.make_parser (jrep)
|
if attached parser.next_parsed_json_value as l_json_null then
|
||||||
jn := Void
|
assert ("a = Void", json.object (l_json_null, Void) = Void)
|
||||||
jn ?= parser.parse
|
else
|
||||||
assert ("jn /= Void", jn /= Void)
|
assert ("parser.next_parsed_json_value /= Void", False)
|
||||||
create dummy_object.make_empty
|
end
|
||||||
a := dummy_object
|
|
||||||
a ?= json.object (jn, Void)
|
|
||||||
assert ("a = Void", a = Void)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
test_json_string_and_character
|
test_json_string_and_character
|
||||||
local
|
local
|
||||||
c: CHARACTER
|
c: CHARACTER
|
||||||
js: detachable JSON_STRING
|
|
||||||
jrep: STRING
|
jrep: STRING
|
||||||
|
js: JSON_STRING
|
||||||
parser: JSON_PARSER
|
parser: JSON_PARSER
|
||||||
do
|
do
|
||||||
c := 'a'
|
c := 'a'
|
||||||
-- Eiffel value -> JSON value -> JSON representation
|
-- Eiffel value -> JSON value -> JSON representation
|
||||||
create js.make_json (c.out)
|
create js.make_from_string (c.out)
|
||||||
assert ("js /= Void", js /= Void)
|
|
||||||
assert ("js.representation.is_equal (%"%"a%"%")", js.representation.is_equal ("%"a%""))
|
assert ("js.representation.is_equal (%"%"a%"%")", js.representation.is_equal ("%"a%""))
|
||||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||||
js ?= json.value (c)
|
if attached {JSON_STRING} json.value (c) as l_json_str then
|
||||||
assert ("js /= Void", js /= Void)
|
assert ("js.representation.is_equal (%"%"a%"%")", l_json_str.representation.is_equal ("%"a%""))
|
||||||
if attached js as l_js then
|
else
|
||||||
assert ("js.representation.is_equal (%"%"a%"%")", l_js.representation.is_equal ("%"a%""))
|
assert ("json.value (c) /= Void", False)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- JSON representation -> JSON value -> Eiffel value
|
-- JSON representation -> JSON value -> Eiffel value
|
||||||
jrep := "%"a%""
|
jrep := "%"a%""
|
||||||
create parser.make_parser (jrep)
|
create parser.make_with_string (jrep)
|
||||||
js := Void
|
if attached {JSON_STRING} parser.next_parsed_json_value as l_json_str then
|
||||||
js ?= parser.parse
|
if attached {STRING_32} json.object (l_json_str, Void) as ucs then
|
||||||
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"))
|
assert ("ucs.string.is_equal (%"a%")", ucs.string.is_equal ("a"))
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
assert ("parser.next_parsed_json_value /= Void", False)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test_json_string_and_string
|
test_json_string_and_string
|
||||||
@@ -545,25 +548,26 @@ feature -- Test
|
|||||||
parser: JSON_PARSER
|
parser: JSON_PARSER
|
||||||
do
|
do
|
||||||
s := "foobar"
|
s := "foobar"
|
||||||
|
jrep := "%"foobar%""
|
||||||
|
|
||||||
-- Eiffel value -> JSON value -> JSON representation
|
-- Eiffel value -> JSON value -> JSON representation
|
||||||
create js.make_json (s)
|
create js.make_from_string (s)
|
||||||
assert ("js /= Void", js /= Void)
|
assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.is_equal (jrep))
|
||||||
assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.is_equal ("%"foobar%""))
|
|
||||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||||
js ?= json.value (s)
|
if attached {JSON_STRING} json.value (s) as l_js then
|
||||||
assert ("js /= Void", js /= Void)
|
assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.is_equal (jrep))
|
||||||
if attached js as l_js then
|
else
|
||||||
assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.is_equal ("%"foobar%""))
|
assert ("json.value (s) /= Void", False)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- JSON representation -> JSON value -> Eiffel value
|
-- JSON representation -> JSON value -> Eiffel value
|
||||||
jrep := "%"foobar%""
|
create parser.make_with_string (jrep)
|
||||||
create parser.make_parser (jrep)
|
if attached {JSON_STRING} parser.next_parsed_json_value as l_js then
|
||||||
js := Void
|
if attached {STRING_32} json.object (l_js, Void) as l_ucs then
|
||||||
js ?= parser.parse
|
assert ("ucs.string.is_equal (%"foobar%")", l_ucs.string.is_equal (s))
|
||||||
assert ("js /= Void", js /= Void)
|
end
|
||||||
if attached {STRING_32} json.object (js, Void) as l_ucs then
|
else
|
||||||
assert ("ucs.string.is_equal (%"foobar%")", l_ucs.string.is_equal ("foobar"))
|
assert ("parser.next_parsed_json_value /= Void", False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -571,31 +575,34 @@ feature -- Test
|
|||||||
local
|
local
|
||||||
js: detachable JSON_STRING
|
js: detachable JSON_STRING
|
||||||
ucs: detachable STRING_32
|
ucs: detachable STRING_32
|
||||||
jrep: STRING
|
jrep, s: STRING
|
||||||
parser: JSON_PARSER
|
parser: JSON_PARSER
|
||||||
do
|
do
|
||||||
create ucs.make_from_string ("foobar")
|
s := "foobar"
|
||||||
|
jrep := "%"foobar%""
|
||||||
|
create ucs.make_from_string (s)
|
||||||
|
|
||||||
-- Eiffel value -> JSON value -> JSON representation
|
-- Eiffel value -> JSON value -> JSON representation
|
||||||
create js.make_json (ucs)
|
create js.make_from_string (ucs)
|
||||||
assert ("js /= Void", js /= Void)
|
assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.is_equal (jrep))
|
||||||
assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.is_equal ("%"foobar%""))
|
|
||||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||||
js ?= json.value (ucs)
|
if attached {JSON_STRING} json.value (ucs) as l_js then
|
||||||
assert ("js /= Void", js /= Void)
|
assert ("js.representation.is_equal (%"%"foobar%"%")", l_js.representation.is_equal (jrep))
|
||||||
if attached js as l_js then
|
else
|
||||||
assert ("js.representation.is_equal (%"%"foobar%"%")", l_js.representation.is_equal ("%"foobar%""))
|
assert ("json.value (ucs) /= Void", False)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- JSON representation -> JSON value -> Eiffel value
|
-- JSON representation -> JSON value -> Eiffel value
|
||||||
jrep := "%"foobar%""
|
create parser.make_with_string (jrep)
|
||||||
create parser.make_parser (jrep)
|
if attached {JSON_STRING} parser.next_parsed_json_value as l_js then
|
||||||
js := Void
|
if attached {STRING_32} json.object (l_js, Void) as l_ucs then
|
||||||
js ?= parser.parse
|
assert ("ucs.string.is_equal (%"foobar%")", l_ucs.string.is_equal (s))
|
||||||
assert ("js /= Void", js /= Void)
|
else
|
||||||
ucs := Void
|
assert ("json.object (js, Void) /= Void", False)
|
||||||
ucs ?= json.object (js, Void)
|
end
|
||||||
if attached ucs as l_ucs then
|
else
|
||||||
assert ("ucs.string.is_equal (%"foobar%")", l_ucs.string.is_equal ("foobar"))
|
assert ("parser.next_parsed_json_value /= Void", False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -603,52 +610,103 @@ feature -- Test
|
|||||||
local
|
local
|
||||||
js: detachable JSON_STRING
|
js: detachable JSON_STRING
|
||||||
s: detachable STRING_8
|
s: detachable STRING_8
|
||||||
ucs: detachable STRING_32
|
|
||||||
jrep: STRING
|
jrep: STRING
|
||||||
parser: JSON_PARSER
|
parser: JSON_PARSER
|
||||||
do
|
do
|
||||||
|
jrep := "%"foo\\bar%""
|
||||||
create s.make_from_string ("foo\bar")
|
create s.make_from_string ("foo\bar")
|
||||||
create js.make_json (s)
|
create js.make_from_string (s)
|
||||||
|
assert ("js.representation.same_string (%"%"foo\\bar%"%")", js.representation.same_string (jrep))
|
||||||
assert ("js.representation.same_string (%"%"foo\\bar%"%")", js.representation.same_string ("%"foo\\bar%""))
|
|
||||||
|
|
||||||
-- Eiffel value -> JSON value -> JSON representation with factory
|
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||||
js ?= json.value (s)
|
if attached {JSON_STRING} json.value (s) as l_js then
|
||||||
assert ("js /= Void", js /= Void)
|
assert ("js.representation.is_equal (%"%"foobar%"%")", l_js.representation.same_string (jrep))
|
||||||
if js /= Void then
|
else
|
||||||
assert ("js.representation.is_equal (%"%"foobar%"%")", js.representation.same_string ("%"foo\\bar%""))
|
assert ("json.value (s) /= Void", False)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- JSON representation -> JSON value -> Eiffel value
|
-- JSON representation -> JSON value -> Eiffel value
|
||||||
jrep := "%"foo\\bar%""
|
create parser.make_with_string (jrep)
|
||||||
create parser.make_parser (jrep)
|
if attached {JSON_STRING} parser.next_parsed_json_value as l_js then
|
||||||
js ?= parser.parse
|
if attached {STRING_32} json.object (l_js, Void) as l_ucs then
|
||||||
assert ("js /= Void", js /= Void)
|
assert ("ucs.same_string (%"foo\bar%")", l_ucs.same_string ("foo\bar"))
|
||||||
ucs ?= json.object (js, Void)
|
end
|
||||||
if ucs /= Void then
|
else
|
||||||
assert ("ucs.same_string (%"foo\bar%")", ucs.same_string ("foo\bar"))
|
assert ("parser.next_parsed_json_value /= Void", False)
|
||||||
end
|
end
|
||||||
|
|
||||||
jrep := "%"foo\\bar%""
|
jrep := "%"foo\\bar%""
|
||||||
create parser.make_parser (jrep)
|
create parser.make_with_string (jrep)
|
||||||
if attached {JSON_STRING} parser.parse as jstring then
|
if attached {JSON_STRING} parser.next_parsed_json_value as jstring then
|
||||||
assert ("unescaped string %"foo\\bar%" to %"foo\bar%"", jstring.unescaped_string_8.same_string ("foo\bar"))
|
assert ("unescaped string %"foo\\bar%" to %"foo\bar%"", jstring.unescaped_string_8.same_string ("foo\bar"))
|
||||||
|
else
|
||||||
|
assert ("parser.next_parsed_json_value /= Void", False)
|
||||||
end
|
end
|
||||||
|
create js.make_from_string_32 ({STRING_32} "你好")
|
||||||
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"))
|
assert ("escaping unicode string32 %"%%/20320/%%/22909/%" %"\u4F60\u597D%"", js.item.same_string ("\u4F60\u597D"))
|
||||||
|
|
||||||
jrep := "%"\u4F60\u597D%"" --| Ni hao
|
jrep := "%"\u4F60\u597D%"" --| Ni hao
|
||||||
create parser.make_parser (jrep)
|
create parser.make_with_string (jrep)
|
||||||
if attached {JSON_STRING} parser.parse as jstring then
|
if attached {JSON_STRING} parser.next_parsed_json_value as jstring then
|
||||||
assert ("same unicode string32 %"%%/20320/%%/22909/%"", jstring.unescaped_string_32.same_string ({STRING_32}"%/20320/%/22909/"))
|
assert ("same unicode string32 %"%%/20320/%%/22909/%"", jstring.unescaped_string_32.same_string ({STRING_32} "你好"))
|
||||||
|
else
|
||||||
|
assert ("parser.next_parsed_json_value /= Void", False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test_json_string_and_special_characters_2
|
||||||
|
local
|
||||||
|
js: detachable JSON_STRING
|
||||||
|
s,j: STRING
|
||||||
|
do
|
||||||
|
s := "foo%Tbar"
|
||||||
|
j := "foo\tbar"
|
||||||
|
create js.make_from_string (s)
|
||||||
|
assert ("string %"" + s + "%" to json %"" + j + "%"", js.item.same_string (j))
|
||||||
|
create js.make_from_escaped_json_string (js.item)
|
||||||
|
assert ("json %"" + j + "%" to string %"" + s + "%"", js.unescaped_string_8.same_string (s))
|
||||||
|
|
||||||
|
s := "tab=%T cr=%R newline=%N backslash=%H slash=/ end"
|
||||||
|
j := "tab=\t cr=\r newline=\n backslash=\\ slash=/ end"
|
||||||
|
create js.make_from_string (s)
|
||||||
|
assert ("string %"" + s + "%" to json %"" + j + "%"", js.item.same_string (j))
|
||||||
|
create js.make_from_escaped_json_string (js.item)
|
||||||
|
assert ("json %"" + j + "%" to string %"" + s + "%"", js.unescaped_string_8.same_string (s))
|
||||||
|
|
||||||
|
s := "<script>tab=%T cr=%R newline=%N backslash=%H slash=/ end</script>"
|
||||||
|
j := "<script>tab=\t cr=\r newline=\n backslash=\\ slash=/ end<\/script>"
|
||||||
|
create js.make_from_string (s)
|
||||||
|
assert ("string %"" + s + "%" to json %"" + j + "%"", js.item.same_string (j))
|
||||||
|
create js.make_from_escaped_json_string (js.item)
|
||||||
|
assert ("json %"" + j + "%" to string %"" + s + "%"", js.unescaped_string_8.same_string (s))
|
||||||
|
|
||||||
|
create js.make_from_escaped_json_string ("tab=\t")
|
||||||
|
assert ("js.item.same_string (%"tab=\t%")", js.item.same_string ("tab=\t"))
|
||||||
|
create js.make_from_escaped_json_string (js.item)
|
||||||
|
assert ("js.item.same_string (%"tab=\t%")", js.item.same_string ("tab=\t"))
|
||||||
|
|
||||||
|
|
||||||
|
-- <\/script>
|
||||||
|
create js.make_from_escaped_json_string ("<script>tab=\t<\/script>")
|
||||||
|
assert ("js.item.same_string (%"<script>tab=\t<\/script>%")", js.item.same_string ("<script>tab=\t<\/script>"))
|
||||||
|
assert ("js.unescaped_string_8.same_string (%"<script>tab=%%T</script>%")", js.unescaped_string_8.same_string ("<script>tab=%T</script>"))
|
||||||
|
|
||||||
|
create js.make_from_escaped_json_string (js.item)
|
||||||
|
assert ("js.item.same_string (%"<script>tab=\t<\/script>%")", js.item.same_string ("<script>tab=\t<\/script>"))
|
||||||
|
assert ("js.unescaped_string_8.same_string (%"<script>tab=%%T</script>%")", js.unescaped_string_8.same_string ("<script>tab=%T</script>"))
|
||||||
|
|
||||||
|
-- </script>
|
||||||
|
create js.make_from_escaped_json_string ("<script>tab=\t</script>")
|
||||||
|
assert ("js.item.same_string (%"<script>tab=\t</script>%")", js.item.same_string ("<script>tab=\t</script>"))
|
||||||
|
assert ("js.unescaped_string_8.same_string (%"<script>tab=%%T</script>%")", js.unescaped_string_8.same_string ("<script>tab=%T</script>"))
|
||||||
|
|
||||||
|
create js.make_from_escaped_json_string (js.item)
|
||||||
|
assert ("js.item.same_string (%"<script>tab=\t<\/script>%")", js.item.same_string ("<script>tab=\t</script>"))
|
||||||
|
assert ("js.unescaped_string_8.same_string (%"<script>tab=%%T</script>%")", js.unescaped_string_8.same_string ("<script>tab=%T</script>"))
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
test_json_array
|
test_json_array
|
||||||
local
|
local
|
||||||
ll: LINKED_LIST [INTEGER_8]
|
ll: LINKED_LIST [INTEGER_8]
|
||||||
ll2: detachable LINKED_LIST [detachable ANY]
|
|
||||||
ja: detachable JSON_ARRAY
|
ja: detachable JSON_ARRAY
|
||||||
jn: JSON_NUMBER
|
jn: JSON_NUMBER
|
||||||
jrep: STRING
|
jrep: STRING
|
||||||
@@ -664,7 +722,7 @@ feature -- Test
|
|||||||
ll.extend (5)
|
ll.extend (5)
|
||||||
-- Note: Currently there is no simple way of creating a JSON_ARRAY
|
-- Note: Currently there is no simple way of creating a JSON_ARRAY
|
||||||
-- from an LINKED_LIST.
|
-- from an LINKED_LIST.
|
||||||
create ja.make_array
|
create ja.make (ll.count)
|
||||||
from
|
from
|
||||||
ll.start
|
ll.start
|
||||||
until
|
until
|
||||||
@@ -677,11 +735,10 @@ feature -- Test
|
|||||||
assert ("ja /= Void", ja /= Void)
|
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]"))
|
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
|
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||||
ja := Void
|
if attached {JSON_ARRAY} json.value (ll) as l_ja then
|
||||||
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]"))
|
assert ("ja.representation.is_equal (%"[0,1,1,2,3,5]%")", l_ja.representation.is_equal ("[0,1,1,2,3,5]"))
|
||||||
|
else
|
||||||
|
assert ("json.value (ll) /= Void", False)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- JSON representation -> JSON value -> Eiffel value
|
-- JSON representation -> JSON value -> Eiffel value
|
||||||
@@ -690,23 +747,21 @@ feature -- Test
|
|||||||
-- it means we will get an LINKED_LIST [ANY] containing the INTEGER_8
|
-- it means we will get an LINKED_LIST [ANY] containing the INTEGER_8
|
||||||
-- values 0, 1, 1, 2, 3, 5
|
-- values 0, 1, 1, 2, 3, 5
|
||||||
jrep := "[0,1,1,2,3,5]"
|
jrep := "[0,1,1,2,3,5]"
|
||||||
create parser.make_parser (jrep)
|
create parser.make_with_string (jrep)
|
||||||
ja := Void
|
if attached {JSON_ARRAY} parser.next_parsed_json_value as l_ja then
|
||||||
ja ?= parser.parse
|
if attached {LINKED_LIST [detachable ANY]} json.object (ja, Void) as l_ll2 then
|
||||||
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))
|
assert ("ll2.is_equal (ll)", l_ll2.is_equal (ll))
|
||||||
|
else
|
||||||
|
assert ("json.object (ja, Void) /= Void", False)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
assert ("parser.next_parsed_json_value /= Void", False)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
test_json_object
|
test_json_object
|
||||||
local
|
local
|
||||||
t, t2: detachable HASH_TABLE [detachable ANY, STRING_GENERAL]
|
t: detachable HASH_TABLE [detachable ANY, STRING_GENERAL]
|
||||||
i: INTEGER
|
i: INTEGER
|
||||||
ucs_key, ucs: STRING_32
|
ucs_key, ucs: STRING_32
|
||||||
a: ARRAY [INTEGER]
|
a: ARRAY [INTEGER]
|
||||||
@@ -722,14 +777,14 @@ feature -- Test
|
|||||||
-- a HASH_TABLE, so we do it manually.
|
-- a HASH_TABLE, so we do it manually.
|
||||||
-- t = {"name": "foobar", "size": 42, "contents", [0, 1, 1, 2, 3, 5]}
|
-- t = {"name": "foobar", "size": 42, "contents", [0, 1, 1, 2, 3, 5]}
|
||||||
create jo.make
|
create jo.make
|
||||||
create js_key.make_json ("name")
|
create js_key.make_from_string ("name")
|
||||||
create js.make_json ("foobar")
|
create js.make_from_string ("foobar")
|
||||||
jo.put (js, js_key)
|
jo.put (js, js_key)
|
||||||
create js_key.make_json ("size")
|
create js_key.make_from_string ("size")
|
||||||
create jn.make_integer (42)
|
create jn.make_integer (42)
|
||||||
jo.put (jn, js_key)
|
jo.put (jn, js_key)
|
||||||
create js_key.make_json ("contents")
|
create js_key.make_from_string ("contents")
|
||||||
create ja.make_array
|
create ja.make (6)
|
||||||
create jn.make_integer (0)
|
create jn.make_integer (0)
|
||||||
ja.add (jn)
|
ja.add (jn)
|
||||||
create jn.make_integer (1)
|
create jn.make_integer (1)
|
||||||
@@ -745,6 +800,7 @@ feature -- Test
|
|||||||
jo.put (ja, js_key)
|
jo.put (ja, js_key)
|
||||||
assert ("jo /= Void", jo /= Void)
|
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]}"))
|
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
|
-- Eiffel value -> JSON value -> JSON representation with factory
|
||||||
create t.make (3)
|
create t.make (3)
|
||||||
create ucs_key.make_from_string ("name")
|
create ucs_key.make_from_string ("name")
|
||||||
@@ -756,26 +812,28 @@ feature -- Test
|
|||||||
create ucs_key.make_from_string ("contents")
|
create ucs_key.make_from_string ("contents")
|
||||||
a := <<0, 1, 1, 2, 3, 5>>
|
a := <<0, 1, 1, 2, 3, 5>>
|
||||||
t.put (a, ucs_key)
|
t.put (a, ucs_key)
|
||||||
jo := Void
|
if attached {JSON_OBJECT} json.value (t) as l_jo then
|
||||||
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]}"))
|
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
|
else
|
||||||
-- JSON representation -> JSON value -> Eiffel value -> JSON value -> JSON representation
|
assert ("json.value (t) /= Void", False)
|
||||||
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
|
||||||
|
|
||||||
|
-- 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_with_string (jrep)
|
||||||
|
if attached {JSON_OBJECT} parser.next_parsed_json_value as l_jo then
|
||||||
|
if attached {HASH_TABLE [detachable ANY, STRING_GENERAL]} json.object (l_jo, Void) as l_t2 then
|
||||||
|
if attached json.value (l_t2) as l_jo_2 then
|
||||||
|
assert ("jrep.is_equal (jo.representation)", jrep.is_equal (l_jo_2.representation))
|
||||||
|
else
|
||||||
|
assert ("json.value (t2) /= Void", False)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
assert ("json.object (jo, Void) /= Void", False)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
assert ("parser.next_parsed_json_value /= Void", jo /= Void)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
test_json_object_hash_code
|
test_json_object_hash_code
|
||||||
@@ -802,7 +860,6 @@ feature -- Test
|
|||||||
jv := json.value (gv)
|
jv := json.value (gv)
|
||||||
else
|
else
|
||||||
assert ("exceptions.is_developer_exception", json.is_developer_exception)
|
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
|
end
|
||||||
rescue
|
rescue
|
||||||
exception := True
|
exception := True
|
||||||
@@ -813,17 +870,15 @@ feature -- Test
|
|||||||
-- Test converting from a JSON value to an Eiffel object based on a
|
-- Test converting from a JSON value to an Eiffel object based on a
|
||||||
-- class for which no JSON converter has been registered.
|
-- class for which no JSON converter has been registered.
|
||||||
local
|
local
|
||||||
gv : detachable OPERATING_ENVIRONMENT
|
gv: detachable ANY
|
||||||
jo: JSON_OBJECT
|
jo: JSON_OBJECT
|
||||||
exception: BOOLEAN
|
exception: BOOLEAN
|
||||||
do
|
do
|
||||||
if not exception then
|
if not exception then
|
||||||
create jo.make
|
create jo.make
|
||||||
gv ?= json.object (jo, "OPERATING_ENVIRONMENT")
|
gv := json.object (jo, "OPERATING_ENVIRONMENT")
|
||||||
else
|
else
|
||||||
assert ("exceptions.is_developer_exception", json.is_developer_exception)
|
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
|
end
|
||||||
rescue
|
rescue
|
||||||
exception := True
|
exception := True
|
||||||
|
|||||||
@@ -1,19 +1,28 @@
|
|||||||
class TEST_JSON_CUSTOM_CLASSES
|
note
|
||||||
|
description: "Parsing and converter of book collection test."
|
||||||
|
date: "$Date$"
|
||||||
|
revision: "$Revision$"
|
||||||
|
|
||||||
|
class
|
||||||
|
TEST_JSON_CUSTOM_CLASSES
|
||||||
|
|
||||||
inherit
|
inherit
|
||||||
|
|
||||||
SHARED_EJSON
|
SHARED_EJSON
|
||||||
rename default_create as shared_default_create end
|
undefine
|
||||||
|
default_create
|
||||||
|
end
|
||||||
|
|
||||||
EQA_TEST_SET
|
EQA_TEST_SET
|
||||||
select default_create end
|
|
||||||
feature -- Test
|
feature -- Test
|
||||||
|
|
||||||
test_custom_classes
|
test_custom_classes
|
||||||
|
-- Parse JSON representation to JSON_OBJECT and test book collection converter.
|
||||||
local
|
local
|
||||||
bc: detachable BOOK_COLLECTION
|
|
||||||
jbc: JSON_BOOK_CONVERTER
|
jbc: JSON_BOOK_CONVERTER
|
||||||
jbcc: JSON_BOOK_COLLECTION_CONVERTER
|
jbcc: JSON_BOOK_COLLECTION_CONVERTER
|
||||||
jac: JSON_AUTHOR_CONVERTER
|
jac: JSON_AUTHOR_CONVERTER
|
||||||
jo: detachable JSON_OBJECT
|
|
||||||
parser: JSON_PARSER
|
parser: JSON_PARSER
|
||||||
jrep: STRING
|
jrep: STRING
|
||||||
do
|
do
|
||||||
@@ -25,18 +34,19 @@ feature -- Test
|
|||||||
json.add_converter (jac)
|
json.add_converter (jac)
|
||||||
jrep := "{%"name%":%"Test collection%",%"books%":[{%"title%":%"eJSON: The Definitive Guide%",%"isbn%":%"123123-413243%",%"author%":{%"name%":%"Foo Bar%"}}]}"
|
jrep := "{%"name%":%"Test collection%",%"books%":[{%"title%":%"eJSON: The Definitive Guide%",%"isbn%":%"123123-413243%",%"author%":{%"name%":%"Foo Bar%"}}]}"
|
||||||
create parser.make_parser (jrep)
|
create parser.make_parser (jrep)
|
||||||
jo := Void
|
if attached {JSON_OBJECT} parser.parse as l_json_object then
|
||||||
jo ?= parser.parse
|
if attached {BOOK_COLLECTION} json.object (l_json_object, "BOOK_COLLECTION") as l_collection then
|
||||||
assert ("jo /= Void", jo /= Void)
|
if attached {JSON_OBJECT} json.value (l_collection) as l_json_object_2 then
|
||||||
bc := Void
|
assert ("JSON representation is correct", l_json_object_2.representation.same_string (jrep))
|
||||||
bc ?= json.object (jo, "BOOK_COLLECTION")
|
else
|
||||||
assert ("bc /= Void", bc /= Void)
|
assert ("BOOK_COLLECTION converted to JSON_OBJECT", False)
|
||||||
jo ?= json.value (bc)
|
end
|
||||||
assert ("jo /= Void", jo /= Void)
|
else
|
||||||
if attached jo as l_jo then
|
assert ("JSON_OBJECT converted to BOOK_COLLECTION", False)
|
||||||
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
|
||||||
|
else
|
||||||
|
assert ("JSON object representation to JSON_OBJECT", False)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end -- class TEST_JSON_CUSTOM_CLASS
|
end -- class TEST_JSON_CUSTOM_CLASS
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
note
|
note
|
||||||
description: "[
|
description: "[
|
||||||
Eiffel tests that can be executed by testing tool.
|
Eiffel tests that can be executed by testing tool.
|
||||||
]"
|
]"
|
||||||
@@ -33,8 +33,8 @@ feature -- Tests Pass
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("pass1.json") as json_file then
|
if attached json_file_from ("pass1.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("pass1.json",parse_json.is_parsed = True)
|
assert ("pass1.json", parse_json.is_valid)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -45,8 +45,8 @@ feature -- Tests Pass
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("pass2.json") as json_file then
|
if attached json_file_from ("pass2.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("pass2.json",parse_json.is_parsed = True)
|
assert ("pass2.json",parse_json.is_valid)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -57,8 +57,8 @@ feature -- Tests Pass
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("pass3.json") as json_file then
|
if attached json_file_from ("pass3.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("pass3.json",parse_json.is_parsed = True)
|
assert ("pass3.json",parse_json.is_valid)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -68,16 +68,12 @@ feature -- Tests Pass
|
|||||||
utf: UTF_CONVERTER
|
utf: UTF_CONVERTER
|
||||||
s: READABLE_STRING_32
|
s: READABLE_STRING_32
|
||||||
do
|
do
|
||||||
s := {STRING_32} "{ %"nihaoma%": %"你好吗\t?%" }"
|
s := {STRING_32} "{ %"nihaoma%": %"ä½ å¥½å—\t?%" }"
|
||||||
|
|
||||||
parse_json := new_json_parser (utf.string_32_to_utf_8_string_8 (s))
|
parse_json := new_json_parser (utf.string_32_to_utf_8_string_8 (s))
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("utf8.pass1.json", parse_json.is_parsed = True)
|
assert ("utf8.pass1.json", parse_json.is_valid)
|
||||||
if
|
if attached {JSON_OBJECT} parse_json.parsed_json_value as jo and then attached {JSON_STRING} jo.item ("nihaoma") as js then
|
||||||
attached {JSON_OBJECT} json_value as jo and then
|
assert ("utf8.nihaoma", js.unescaped_string_32.same_string ({STRING_32} "ä½ å¥½å—%T?"))
|
||||||
attached {JSON_STRING} jo.item ("nihaoma") as js
|
|
||||||
then
|
|
||||||
assert ("utf8.nihaoma", js.unescaped_string_32.same_string ({STRING_32} "你好吗%T?"))
|
|
||||||
else
|
else
|
||||||
assert ("utf8.nihaoma", False)
|
assert ("utf8.nihaoma", False)
|
||||||
end
|
end
|
||||||
@@ -91,8 +87,8 @@ feature -- Tests Failures
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("fail1.json") as json_file then
|
if attached json_file_from ("fail1.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("fail1.json",parse_json.is_parsed = False)
|
assert ("fail1.json", parse_json.is_valid = False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -103,8 +99,8 @@ feature -- Tests Failures
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("fail2.json") as json_file then
|
if attached json_file_from ("fail2.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("fail2.json",parse_json.is_parsed = False)
|
assert ("fail2.json",parse_json.is_valid = False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -115,8 +111,8 @@ feature -- Tests Failures
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("fail3.json") as json_file then
|
if attached json_file_from ("fail3.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("fail3.json",parse_json.is_parsed = False)
|
assert ("fail3.json",parse_json.is_valid = False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -127,8 +123,8 @@ feature -- Tests Failures
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("fail4.json") as json_file then
|
if attached json_file_from ("fail4.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("fail4.json",parse_json.is_parsed = False)
|
assert ("fail4.json",parse_json.is_valid = False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -139,8 +135,8 @@ feature -- Tests Failures
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("fail5.json") as json_file then
|
if attached json_file_from ("fail5.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("fail5.json",parse_json.is_parsed = False)
|
assert ("fail5.json",parse_json.is_valid = False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -152,8 +148,8 @@ feature -- Tests Failures
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("fail6.json") as json_file then
|
if attached json_file_from ("fail6.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("fail6.json",parse_json.is_parsed = False )
|
assert ("fail6.json",parse_json.is_valid = False )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -164,8 +160,8 @@ feature -- Tests Failures
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("fail7.json") as json_file then
|
if attached json_file_from ("fail7.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("fail7.json",parse_json.is_parsed = False)
|
assert ("fail7.json",parse_json.is_valid = False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -176,8 +172,8 @@ feature -- Tests Failures
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("fail8.json") as json_file then
|
if attached json_file_from ("fail8.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("fail8.json",parse_json.is_parsed = False )
|
assert ("fail8.json",parse_json.is_valid = False )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -189,8 +185,8 @@ feature -- Tests Failures
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("fail9.json") as json_file then
|
if attached json_file_from ("fail9.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("fail9.json",parse_json.is_parsed = False)
|
assert ("fail9.json",parse_json.is_valid = False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -202,8 +198,8 @@ feature -- Tests Failures
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("fail10.json") as json_file then
|
if attached json_file_from ("fail10.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("fail10.json",parse_json.is_parsed = False)
|
assert ("fail10.json",parse_json.is_valid = False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -214,8 +210,8 @@ feature -- Tests Failures
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("fail11.json") as json_file then
|
if attached json_file_from ("fail11.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("fail11.json",parse_json.is_parsed = False)
|
assert ("fail11.json",parse_json.is_valid = False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -226,8 +222,8 @@ feature -- Tests Failures
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("fail12.json") as json_file then
|
if attached json_file_from ("fail12.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("fail12.json",parse_json.is_parsed = False)
|
assert ("fail12.json",parse_json.is_valid = False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -238,8 +234,8 @@ feature -- Tests Failures
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("fail13.json") as json_file then
|
if attached json_file_from ("fail13.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("fail13.json",parse_json.is_parsed = False)
|
assert ("fail13.json",parse_json.is_valid = False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -250,8 +246,8 @@ feature -- Tests Failures
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("fail14.json") as json_file then
|
if attached json_file_from ("fail14.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("fail14.json",parse_json.is_parsed = False)
|
assert ("fail14.json",parse_json.is_valid = False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -262,8 +258,8 @@ feature -- Tests Failures
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("fail15.json") as json_file then
|
if attached json_file_from ("fail15.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("fail15.json",parse_json.is_parsed = False)
|
assert ("fail15.json",parse_json.is_valid = False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -274,8 +270,8 @@ feature -- Tests Failures
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("fail16.json") as json_file then
|
if attached json_file_from ("fail16.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("fail16.json",parse_json.is_parsed = False)
|
assert ("fail16.json",parse_json.is_valid = False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -286,8 +282,8 @@ feature -- Tests Failures
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("fail17.json") as json_file then
|
if attached json_file_from ("fail17.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("fail17.json",parse_json.is_parsed = False)
|
assert ("fail17.json",parse_json.is_valid = False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -298,8 +294,8 @@ feature -- Tests Failures
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("fail18.json") as json_file then
|
if attached json_file_from ("fail18.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("fail18.json",parse_json.is_parsed = True)
|
assert ("fail18.json",parse_json.is_valid = True)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -310,8 +306,8 @@ feature -- Tests Failures
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("fail19.json") as json_file then
|
if attached json_file_from ("fail19.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("fail19.json",parse_json.is_parsed = False)
|
assert ("fail19.json",parse_json.is_valid = False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -322,8 +318,8 @@ feature -- Tests Failures
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("fail20.json") as json_file then
|
if attached json_file_from ("fail20.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("fail20.json",parse_json.is_parsed = False)
|
assert ("fail20.json",parse_json.is_valid = False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -334,8 +330,8 @@ feature -- Tests Failures
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("fail21.json") as json_file then
|
if attached json_file_from ("fail21.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("fail21.json",parse_json.is_parsed = False)
|
assert ("fail21.json",parse_json.is_valid = False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -347,8 +343,8 @@ feature -- Tests Failures
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("fail22.json") as json_file then
|
if attached json_file_from ("fail22.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("fail22.json",parse_json.is_parsed = False)
|
assert ("fail22.json",parse_json.is_valid = False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -359,8 +355,8 @@ feature -- Tests Failures
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("fail23.json") as json_file then
|
if attached json_file_from ("fail23.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("fail23.json",parse_json.is_parsed = False)
|
assert ("fail23.json",parse_json.is_valid = False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -371,8 +367,8 @@ feature -- Tests Failures
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("fail24.json") as json_file then
|
if attached json_file_from ("fail24.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("fail24.json",parse_json.is_parsed = False)
|
assert ("fail24.json",parse_json.is_valid = False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -383,8 +379,8 @@ feature -- Tests Failures
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("fail25.json") as json_file then
|
if attached json_file_from ("fail25.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("fail25.json",parse_json.is_parsed = False)
|
assert ("fail25.json",parse_json.is_valid = False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -396,8 +392,8 @@ feature -- Tests Failures
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("fail26.json") as json_file then
|
if attached json_file_from ("fail26.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("fail26.json",parse_json.is_parsed = False)
|
assert ("fail26.json",parse_json.is_valid = False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -409,8 +405,8 @@ feature -- Tests Failures
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("fail27.json") as json_file then
|
if attached json_file_from ("fail27.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("fail27.json",parse_json.is_parsed = False)
|
assert ("fail27.json",parse_json.is_valid = False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -422,8 +418,8 @@ feature -- Tests Failures
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("fail28.json") as json_file then
|
if attached json_file_from ("fail28.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("fail28.json",parse_json.is_parsed = False)
|
assert ("fail28.json",parse_json.is_valid = False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -435,8 +431,8 @@ feature -- Tests Failures
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("fail29.json") as json_file then
|
if attached json_file_from ("fail29.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("fail29.json",parse_json.is_parsed = False )
|
assert ("fail29.json",parse_json.is_valid = False )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -448,8 +444,8 @@ feature -- Tests Failures
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("fail30.json") as json_file then
|
if attached json_file_from ("fail30.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("fail30.json",parse_json.is_parsed = False)
|
assert ("fail30.json",parse_json.is_valid = False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -460,8 +456,8 @@ feature -- Tests Failures
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("fail31.json") as json_file then
|
if attached json_file_from ("fail31.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("fail31.json",parse_json.is_parsed = False)
|
assert ("fail31.json",parse_json.is_valid = False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -472,8 +468,8 @@ feature -- Tests Failures
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("fail32.json") as json_file then
|
if attached json_file_from ("fail32.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("fail32.json",parse_json.is_parsed = False)
|
assert ("fail32.json",parse_json.is_valid = False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -484,8 +480,8 @@ feature -- Tests Failures
|
|||||||
do
|
do
|
||||||
if attached json_file_from ("fail33.json") as json_file then
|
if attached json_file_from ("fail33.json") as json_file then
|
||||||
parse_json := new_json_parser (json_file)
|
parse_json := new_json_parser (json_file)
|
||||||
json_value := parse_json.parse_json
|
parse_json.parse_content
|
||||||
assert ("fail33.json",parse_json.is_parsed = False)
|
assert ("fail33.json",parse_json.is_valid = False)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -493,20 +489,16 @@ feature -- JSON_FROM_FILE
|
|||||||
|
|
||||||
file_reader: JSON_FILE_READER
|
file_reader: JSON_FILE_READER
|
||||||
|
|
||||||
json_value: detachable JSON_VALUE
|
json_file_from (fn: READABLE_STRING_GENERAL): detachable STRING
|
||||||
|
|
||||||
json_file_from (fn: STRING): detachable STRING
|
|
||||||
local
|
local
|
||||||
f: RAW_FILE
|
f: RAW_FILE
|
||||||
l_path: STRING
|
l_path: PATH
|
||||||
test_dir: STRING
|
test_dir: PATH
|
||||||
i: INTEGER
|
i: INTEGER
|
||||||
do
|
do
|
||||||
test_dir := (create {EXECUTION_ENVIRONMENT}).current_working_directory
|
test_dir := (create {EXECUTION_ENVIRONMENT}).current_working_path
|
||||||
test_dir.append_character ((create {OPERATING_ENVIRONMENT}).directory_separator)
|
l_path := test_dir.extended (fn)
|
||||||
|
create f.make_with_path (l_path)
|
||||||
l_path := test_dir + fn
|
|
||||||
create f.make_with_name (l_path)
|
|
||||||
if f.exists then
|
if f.exists then
|
||||||
-- Found json file
|
-- Found json file
|
||||||
else
|
else
|
||||||
@@ -517,28 +509,27 @@ feature -- JSON_FROM_FILE
|
|||||||
until
|
until
|
||||||
i = 0
|
i = 0
|
||||||
loop
|
loop
|
||||||
test_dir.append_character ('.')
|
test_dir := test_dir.extended ("..")
|
||||||
test_dir.append_character ('.')
|
|
||||||
test_dir.append_character ((create {OPERATING_ENVIRONMENT}).directory_separator)
|
|
||||||
i := i - 1
|
i := i - 1
|
||||||
end
|
end
|
||||||
l_path := test_dir + fn
|
l_path := test_dir.extended (fn)
|
||||||
end
|
end
|
||||||
create f.make_with_name (l_path)
|
create f.make_with_path (l_path)
|
||||||
if f.exists then
|
if f.exists then
|
||||||
Result := file_reader.read_json_from (l_path)
|
Result := file_reader.read_json_from (l_path.name)
|
||||||
end
|
end
|
||||||
assert ("File contains json data", Result /= Void)
|
assert ("File contains json data", Result /= Void)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
new_json_parser (a_string: STRING): JSON_PARSER
|
new_json_parser (a_string: STRING): JSON_PARSER
|
||||||
do
|
do
|
||||||
create Result.make_parser (a_string)
|
create Result.make_with_string (a_string)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
invariant
|
invariant
|
||||||
file_reader /= Void
|
file_reader /= Void
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
<?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">
|
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="test_suite" uuid="EA141B17-6A21-4781-8B5F-E9939BAE968A">
|
||||||
<target name="test_suite">
|
<target name="test_suite">
|
||||||
<root cluster="test_suite" class="APPLICATION" feature="make"/>
|
<root cluster="test_suite" class="APPLICATION" feature="make"/>
|
||||||
<file_rule>
|
<file_rule>
|
||||||
@@ -7,11 +7,11 @@
|
|||||||
<exclude>/CVS$</exclude>
|
<exclude>/CVS$</exclude>
|
||||||
<exclude>/.svn$</exclude>
|
<exclude>/.svn$</exclude>
|
||||||
</file_rule>
|
</file_rule>
|
||||||
<option warning="true" is_attached_by_default="true" void_safety="all" syntax="standard">
|
<option warning="true" full_class_checking="false" is_attached_by_default="true" void_safety="transitional" syntax="standard">
|
||||||
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||||
</option>
|
</option>
|
||||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||||
<library name="json" location="..\..\..\library\json-safe.ecf"/>
|
<library name="json" location="..\..\..\library\json-safe.ecf" readonly="false"/>
|
||||||
<library name="testing" location="$ISE_LIBRARY\library\testing\testing-safe.ecf"/>
|
<library name="testing" location="$ISE_LIBRARY\library\testing\testing-safe.ecf"/>
|
||||||
<cluster name="test_suite" location=".\" recursive="true"/>
|
<cluster name="test_suite" location=".\" recursive="true"/>
|
||||||
</target>
|
</target>
|
||||||
|
|||||||
Reference in New Issue
Block a user