Improved JSON_PRETTY_STRING_VISITOR to support STRING_8 or STRING_32 output. Added examples. Added doc in the folder "doc". Updated Readme and other files. Added package.iron file.
296 lines
10 KiB
Plaintext
296 lines
10 KiB
Plaintext
== 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.
|
|
|