765 lines
39 KiB
HTML
765 lines
39 KiB
HTML
|
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Strict//EN">
|
|||
|
|
<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></meta><title>YASON - A JSON encoder/decoder for Common Lisp</title><meta name="description" content="
|
|||
|
|
YASON is a JSON encoding and decoding library for Common Lisp. It
|
|||
|
|
provides for functions to read JSON strings into Lisp data
|
|||
|
|
structures and for serializing Lisp data structures as JSON
|
|||
|
|
strings.
|
|||
|
|
"></meta><style type="text/css">
|
|||
|
|
body { background-color: #ffffff; max-width: 50em; margin-left: 2em; }
|
|||
|
|
blockquote { margin-left: 2em; margin-right: 2em; }
|
|||
|
|
pre { padding:5px; background-color:#e0e0e0 }
|
|||
|
|
pre.none { padding:5px; background-color:#ffffff }
|
|||
|
|
h3, h4, h5 { text-decoration: underline; }
|
|||
|
|
a { text-decoration: none; padding: 1px 2px 1px 2px; }
|
|||
|
|
a:visited { text-decoration: none; padding: 1px 2px 1px 2px; }
|
|||
|
|
a:hover { text-decoration: none; padding: 1px 1px 1px 1px; border: 1px solid #000000; }
|
|||
|
|
a:focus { text-decoration: none; padding: 1px 2px 1px 2px; border: none; }
|
|||
|
|
a.none { text-decoration: none; padding: 0; }
|
|||
|
|
a.none:visited { text-decoration: none; padding: 0; }
|
|||
|
|
a.none:hover { text-decoration: none; border: none; padding: 0; }
|
|||
|
|
a.none:focus { text-decoration: none; border: none; padding: 0; }
|
|||
|
|
a.noborder { text-decoration: none; padding: 0; }
|
|||
|
|
a.noborder:visited { text-decoration: none; padding: 0; }
|
|||
|
|
a.noborder:hover { text-decoration: none; border: none; padding: 0; }
|
|||
|
|
a.noborder:focus { text-decoration: none; border: none; padding: 0; }
|
|||
|
|
</style></head><body>
|
|||
|
|
|
|||
|
|
<h1 xmlns="">YASON - A JSON encoder/decoder for Common Lisp</h1>
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
<h3 xmlns="">Abstract</h3>
|
|||
|
|
<blockquote xmlns="">
|
|||
|
|
YASON is a Common Lisp library for encoding and decoding data in
|
|||
|
|
the <a xmlns="http://www.w3.org/1999/xhtml" href="http://json.org/">JSON</a> interchange format. JSON
|
|||
|
|
is used as a lightweight alternative to XML. YASON has the sole
|
|||
|
|
purpose of encoding and decoding data and does not impose any
|
|||
|
|
object model on the Common Lisp application that uses it.
|
|||
|
|
</blockquote>
|
|||
|
|
|
|||
|
|
<h3 xmlns="">Contents</h3>
|
|||
|
|
<ol xmlns="">
|
|||
|
|
<li><a href="#intro">Introduction</a></li>
|
|||
|
|
<li><a href="#install">Download and Installation</a></li>
|
|||
|
|
<li><a href="#json-package">Using JSON as package name</a></li>
|
|||
|
|
<li><a href="#mapping">Mapping between JSON and CL datatypes</a></li>
|
|||
|
|
<li>
|
|||
|
|
<a href="#parsing">Parsing JSON data</a><ol><li><a href="#parser-dict">Parser dictionary</a></li></ol>
|
|||
|
|
</li>
|
|||
|
|
<li>
|
|||
|
|
<a href="#encoding">Encoding JSON data</a><ol>
|
|||
|
|
<li><a href="#dom-encoder">Encoding a JSON DOM</a></li>
|
|||
|
|
<li><a href="#stream-encoder">Encoding JSON in streaming mode</a></li>
|
|||
|
|
<li><a href="#app-encoders">Application specific encoders</a></li>
|
|||
|
|
</ol>
|
|||
|
|
</li>
|
|||
|
|
<li><a href="#index">Symbol index</a></li>
|
|||
|
|
<li><a href="#license">License</a></li>
|
|||
|
|
<li><a href="#ack">Acknowledgements</a></li>
|
|||
|
|
</ol>
|
|||
|
|
|
|||
|
|
<h3 xmlns=""><a class="none" name="intro">Introduction</a></h3>
|
|||
|
|
<p>
|
|||
|
|
<a href="http://json.org/">JSON</a> is an established
|
|||
|
|
alternative to XML as a data interchange format for web
|
|||
|
|
applications. YASON implements reading and writing of JSON
|
|||
|
|
formatted data in Common Lisp. It does not attempt to provide a
|
|||
|
|
mapping between CLOS objects and YASON, but can be used to
|
|||
|
|
implement such mappings.
|
|||
|
|
</p>
|
|||
|
|
<p>
|
|||
|
|
<a href="http://common-lisp.net/project/cl-json/">CL-JSON</a> is
|
|||
|
|
another Common Lisp package that can be used to work with JSON
|
|||
|
|
encoded data. It takes a more integrated approach, providing
|
|||
|
|
for library internal mappings between JSON objects and CLOS
|
|||
|
|
objects. YASON was created as a lightweight, documented
|
|||
|
|
alternative with a minimalistic approach and extensibilty.
|
|||
|
|
</p>
|
|||
|
|
|
|||
|
|
|
|||
|
|
<h3 xmlns=""><a class="none" name="install">Download and Installation</a></h3>
|
|||
|
|
<p>
|
|||
|
|
YASON has its permanent home at <a href="https://github.com/hanshuebner/yason/">GitHub</a>.
|
|||
|
|
It can be obtained by downloading the <a href="https://github.com/downloads/hanshuebner/yason/yason.tar.gz">release
|
|||
|
|
tarball</a>. The current release is 0.7.6.
|
|||
|
|
</p>
|
|||
|
|
<p>
|
|||
|
|
You may also check out the current development version from its
|
|||
|
|
<a href="http://github.com/hanshuebner/yason/">git
|
|||
|
|
repository</a>. If you have suggestions regarding YASON, please
|
|||
|
|
email me at <i>hans.huebner@gmail.com</i>.
|
|||
|
|
</p>
|
|||
|
|
<p>
|
|||
|
|
YASON is written in ANSI Common Lisp. It depends on UNIT-TEST,
|
|||
|
|
TRIVIAL-GRAY-STREAMS and ALEXANDRIA open source libraries. The
|
|||
|
|
recommended way to install YASON and its dependencies is through
|
|||
|
|
the excellent <a href="http://www.quicklisp.org/">Quicklisp</a>
|
|||
|
|
library management system.
|
|||
|
|
</p>
|
|||
|
|
<p>
|
|||
|
|
YASON lives in the <b>:yason</b> package and creates a package
|
|||
|
|
nickname <b>:json</b>. Applications will not normally
|
|||
|
|
<b>:use</b> this package, but rather use qualified names to
|
|||
|
|
access YASON's symbols. For that reason, YASON's symbols do not
|
|||
|
|
contain the string "JSON" themselves. See below for usage
|
|||
|
|
samples.
|
|||
|
|
</p>
|
|||
|
|
|
|||
|
|
|
|||
|
|
<h3 xmlns=""><a class="none" name="json-package">Using JSON as package name</a></h3>
|
|||
|
|
Versions of YASON preceding the v0.6.0 release provided a package
|
|||
|
|
nickname "JSON" for the "YASON" package. This made it impossible
|
|||
|
|
to load both YASON and CL-JSON into the same image, because
|
|||
|
|
CL-JSON uses the "JSON" package name as well.
|
|||
|
|
|
|||
|
|
<p>
|
|||
|
|
As CL-JSON's use of "JSON" as package name has a much longer
|
|||
|
|
history and loading of both CL-JSON and YASON into the same
|
|||
|
|
image has become more common, the "JSON" nickname was removed
|
|||
|
|
from the YASON package with the v0.6.0 release. Users will need
|
|||
|
|
to change their applications so that the "JSON" nickname is no
|
|||
|
|
longer used to refer to the "YASON" package. It is understood
|
|||
|
|
that this is a disruptive change, but as there is no
|
|||
|
|
all-encompassing workaround, this step was felt to be the right
|
|||
|
|
one to make
|
|||
|
|
</p>
|
|||
|
|
|
|||
|
|
|
|||
|
|
<h3 xmlns=""><a class="none" name="mapping">Mapping between JSON and CL datatypes</a></h3>
|
|||
|
|
By default, YASON performs the following mappings between JSON and
|
|||
|
|
CL datatypes:
|
|||
|
|
<table border="1">
|
|||
|
|
<thead>
|
|||
|
|
<tr>
|
|||
|
|
<th>JSON<br></br>datatype</th>
|
|||
|
|
<th>CL<br></br>datatype</th>
|
|||
|
|
<th>Notes</th>
|
|||
|
|
</tr>
|
|||
|
|
</thead>
|
|||
|
|
<tbody>
|
|||
|
|
<tr>
|
|||
|
|
<td>object</td>
|
|||
|
|
<td>hash-table<br></br>:test #'equal</td>
|
|||
|
|
<td>
|
|||
|
|
Keys are strings by default (see
|
|||
|
|
<code xmlns=""><a href="#*parse-object-key-fn*">*parse-object-key-fn*</a></code>). Set
|
|||
|
|
<code xmlns=""><a href="#*parse-object-as*">*parse-object-as*</a></code> to <b>:alist</b> in
|
|||
|
|
order to have YASON parse objects as alists or to
|
|||
|
|
<b>:plist</b> to parse them as plists. When using plists,
|
|||
|
|
you probably want to also set
|
|||
|
|
<code xmlns=""><a href="#*parse-object-key-fn*">*parse-object-key-fn*</a></code> to a function
|
|||
|
|
that interns the object's keys to symbols.
|
|||
|
|
</td>
|
|||
|
|
</tr>
|
|||
|
|
<tr>
|
|||
|
|
<td>array</td>
|
|||
|
|
<td>list</td>
|
|||
|
|
<td>
|
|||
|
|
Can be changed to read to vectors (see
|
|||
|
|
<code xmlns=""><a href="#*parse-json-arrays-as-vectors*">*parse-json-arrays-as-vectors*</a></code>).
|
|||
|
|
</td>
|
|||
|
|
</tr>
|
|||
|
|
<tr>
|
|||
|
|
<td>string</td>
|
|||
|
|
<td>string</td>
|
|||
|
|
<td>
|
|||
|
|
JSON escape characters are recognized upon reading. Upon
|
|||
|
|
writing, known escape characters are used, but non-ASCII
|
|||
|
|
Unicode characters are written as is.
|
|||
|
|
</td>
|
|||
|
|
</tr>
|
|||
|
|
<tr>
|
|||
|
|
<td>number</td>
|
|||
|
|
<td>number</td>
|
|||
|
|
<td>
|
|||
|
|
Parsed with READ, printed with PRINC. This is not a
|
|||
|
|
faithful implementation of the specification.
|
|||
|
|
</td>
|
|||
|
|
</tr>
|
|||
|
|
<tr>
|
|||
|
|
<td>true</td>
|
|||
|
|
<td>t</td>
|
|||
|
|
<td>
|
|||
|
|
Can be changed to read as TRUE (see
|
|||
|
|
<code xmlns=""><a href="#*parse-json-booleans-as-symbols*">*parse-json-booleans-as-symbols*</a></code>).
|
|||
|
|
</td>
|
|||
|
|
</tr>
|
|||
|
|
<tr>
|
|||
|
|
<td>false</td>
|
|||
|
|
<td>nil</td>
|
|||
|
|
<td>
|
|||
|
|
Can be changed to read as FALSE (see
|
|||
|
|
<code xmlns=""><a href="#*parse-json-booleans-as-symbols*">*parse-json-booleans-as-symbols*</a></code>).
|
|||
|
|
</td>
|
|||
|
|
</tr>
|
|||
|
|
<tr>
|
|||
|
|
<td>null</td>
|
|||
|
|
<td>nil</td>
|
|||
|
|
<td></td>
|
|||
|
|
</tr>
|
|||
|
|
</tbody>
|
|||
|
|
</table>
|
|||
|
|
|
|||
|
|
|
|||
|
|
<h3 xmlns=""><a class="none" name="parsing">Parsing JSON data</a></h3>
|
|||
|
|
<p>
|
|||
|
|
JSON data is always completely parsed into an equivalent
|
|||
|
|
in-memory representation. Upon reading, some translations are
|
|||
|
|
performed by default to make it easier for the Common Lisp
|
|||
|
|
program to work with the data; see <code xmlns=""><a href="#mapping">mapping</a></code>
|
|||
|
|
for details. If desired, the parser can be configured to
|
|||
|
|
preserve the full semantics of the JSON data read.
|
|||
|
|
</p>
|
|||
|
|
|
|||
|
|
For example
|
|||
|
|
|
|||
|
|
<pre>CL-USER> (defvar *json-string* "[{\"foo\":1,\"bar\":[7,8,9]},2,3,4,[5,6,7],true,null]")
|
|||
|
|
*JSON-STRING*
|
|||
|
|
CL-USER> (let* ((result (yason:parse *json-string*)))
|
|||
|
|
(print result)
|
|||
|
|
(alexandria:hash-table-plist (first result)))
|
|||
|
|
|
|||
|
|
(#<HASH-TABLE :TEST EQUAL :COUNT 2 {5A4420F1}> 2 3 4 (5 6 7) T NIL)
|
|||
|
|
("bar" (7 8 9) "foo" 1)
|
|||
|
|
CL-USER> (defun maybe-convert-to-keyword (js-name)
|
|||
|
|
(or (find-symbol (string-upcase js-name) :keyword)
|
|||
|
|
js-name))
|
|||
|
|
MAYBE-CONVERT-TO-KEYWORD
|
|||
|
|
CL-USER> :FOO ; intern the :FOO keyword
|
|||
|
|
:FOO
|
|||
|
|
CL-USER> (let* ((yason:*parse-json-arrays-as-vectors* t)
|
|||
|
|
(yason:*parse-json-booleans-as-symbols* t)
|
|||
|
|
(yason:*parse-object-key-fn* #'maybe-convert-to-keyword)
|
|||
|
|
(result (yason:parse *json-string*)))
|
|||
|
|
(print result)
|
|||
|
|
(alexandria:hash-table-plist (aref result 0)))
|
|||
|
|
|
|||
|
|
#(#<HASH-TABLE :TEST EQUAL :COUNT 2 {59B4EAD1}> 2 3 4 #(5 6 7) YASON:TRUE NIL)
|
|||
|
|
("bar" #(7 8 9) :FOO 1)</pre>
|
|||
|
|
|
|||
|
|
<p>
|
|||
|
|
The second example modifies the parser's behaviour so that JSON
|
|||
|
|
arrays are read as CL vectors, JSON booleans will be read as the
|
|||
|
|
symbols TRUE and FALSE and JSON object keys will be looked up in
|
|||
|
|
the <b>:keyword</b> package. Interning strings coming from an
|
|||
|
|
external source is not recommended practice.
|
|||
|
|
</p>
|
|||
|
|
|
|||
|
|
<h4 xmlns=""><a name="parser-dict">Parser dictionary</a></h4>
|
|||
|
|
<p xmlns="">[Function]<br><a class="none" name="parse"><b>parse</b> <i><clix:lambda-list xmlns:clix="http://bknr.net/clixdoc">input &key (object-key-fn
|
|||
|
|
*parse-object-as-key-fn*) (object-as *parse-object-as*)
|
|||
|
|
(json-arrays-as-vectors *parse-json-arrays-as-vectors*)
|
|||
|
|
(json-booleans-as-symbols *parse-json-booleans-as-symbols*)
|
|||
|
|
(json-nulls-as-keyword *parse-json-null-as-keyword*)</clix:lambda-list></i>
|
|||
|
|
=>
|
|||
|
|
<i>object</i></a><blockquote><clix:description xmlns:clix="http://bknr.net/clixdoc">
|
|||
|
|
Parse <code><i>input</i></code>, which must be a string or
|
|||
|
|
a stream, as JSON. Returns the Lisp representation of the
|
|||
|
|
JSON structure parsed.
|
|||
|
|
<p xmlns="http://www.w3.org/1999/xhtml">
|
|||
|
|
The keyword arguments <code xmlns=""><i>object-key-fn</i></code>,
|
|||
|
|
<code xmlns=""><i>object-as</i></code>,
|
|||
|
|
<code xmlns=""><i>json-arrays-as-vectors</i></code>,
|
|||
|
|
<code xmlns=""><i>json-booleans-as-symbols</i></code>, and
|
|||
|
|
<code xmlns=""><i>json-null-as-keyword</i></code> may be used
|
|||
|
|
to specify different values for the parsing parameters
|
|||
|
|
from the current bindings of the respective special
|
|||
|
|
variables.
|
|||
|
|
</p>
|
|||
|
|
</clix:description></blockquote></p>
|
|||
|
|
|
|||
|
|
<p xmlns="">
|
|||
|
|
[Special variable]<br><a class="none" name="*parse-json-arrays-as-vectors*"><b>*parse-json-arrays-as-vectors*</b></a><blockquote><clix:description xmlns:clix="http://bknr.net/clixdoc">
|
|||
|
|
If set to a true value, JSON arrays will be parsed as
|
|||
|
|
vectors, not as lists. NIL is the default.
|
|||
|
|
</clix:description></blockquote></p>
|
|||
|
|
|
|||
|
|
<p xmlns="">
|
|||
|
|
[Special variable]<br><a class="none" name="*parse-object-as*"><b>*parse-object-as*</b></a><blockquote><clix:description xmlns:clix="http://bknr.net/clixdoc">
|
|||
|
|
Can be set to <b xmlns="http://www.w3.org/1999/xhtml">:hash-table</b> to parse objects as hash
|
|||
|
|
tables, <b xmlns="http://www.w3.org/1999/xhtml">:alist</b> to parse them as alists or
|
|||
|
|
<b xmlns="http://www.w3.org/1999/xhtml">:plist</b> to parse them as plists. <b xmlns="http://www.w3.org/1999/xhtml">:hash-table</b>
|
|||
|
|
is the default.
|
|||
|
|
</clix:description></blockquote></p>
|
|||
|
|
|
|||
|
|
<p xmlns="">
|
|||
|
|
[Special variable]<br><a class="none" name="*parse-json-booleans-as-symbols*"><b>*parse-json-booleans-as-symbols*</b></a><blockquote><clix:description xmlns:clix="http://bknr.net/clixdoc">
|
|||
|
|
If set to a true value, JSON booleans will be read as the
|
|||
|
|
symbols TRUE and FALSE instead of T and NIL, respectively.
|
|||
|
|
NIL is the default.
|
|||
|
|
</clix:description></blockquote></p>
|
|||
|
|
|
|||
|
|
<p xmlns="">
|
|||
|
|
[Special variable]<br><a class="none" name="*parse-json-null-as-keyword*"><b>*parse-json-null-as-keyword*</b></a><blockquote><clix:description xmlns:clix="http://bknr.net/clixdoc">
|
|||
|
|
If set to a true value, JSON null will be read as the
|
|||
|
|
keyword :NULL, instead of NIL.
|
|||
|
|
NIL is the default.
|
|||
|
|
</clix:description></blockquote></p>
|
|||
|
|
|
|||
|
|
<p xmlns="">
|
|||
|
|
[Special variable]<br><a class="none" name="*parse-object-key-fn*"><b>*parse-object-key-fn*</b></a><blockquote><clix:description xmlns:clix="http://bknr.net/clixdoc">
|
|||
|
|
Function to call to convert a key string in a JSON object to
|
|||
|
|
a key in the CL hash produced. IDENTITY is the default.
|
|||
|
|
</clix:description></blockquote></p>
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
<h3 xmlns=""><a class="none" name="encoding">Encoding JSON data</a></h3>
|
|||
|
|
YASON provides two distinct modes to encode JSON data:
|
|||
|
|
applications can either create an in-memory representation of the
|
|||
|
|
data to be serialized, then have YASON convert it to JSON in one
|
|||
|
|
go, or they can use a set of macros to serialze the JSON data
|
|||
|
|
element-by-element, allowing fine-grained control over the layout
|
|||
|
|
of the generated data.
|
|||
|
|
|
|||
|
|
<p>
|
|||
|
|
Optionally, the JSON that is produced can be indented.
|
|||
|
|
Indentation requires the use of a
|
|||
|
|
<code xmlns=""><a href="#json-output-stream">JSON-OUTPUT-STREAM</a></code> as serialization target.
|
|||
|
|
With the stream serializer, such a stream is automatically used.
|
|||
|
|
If indentation is desired with the DOM serializer, such a stream
|
|||
|
|
can be obtained by calling the
|
|||
|
|
<code xmlns=""><a href="#make-json-output-stream">MAKE-JSON-OUTPUT-STREAM</a></code> function with the
|
|||
|
|
target output string as argument. Please be aware that indented
|
|||
|
|
output not requires more space, but is also slower and should
|
|||
|
|
not be enabled in performance critical applications.
|
|||
|
|
</p>
|
|||
|
|
|
|||
|
|
<h4 xmlns=""><a name="dom-encoder">Encoding a JSON DOM</a></h4>
|
|||
|
|
<p>
|
|||
|
|
In this mode, an in-memory structure is encoded in JSON
|
|||
|
|
format. The structure must consist of objects that are
|
|||
|
|
serializable using the <code xmlns=""><a href="#encode">ENCODE</a></code> function.
|
|||
|
|
YASON defines a number of encoders for standard data types
|
|||
|
|
(see <code xmlns=""><a href="#mapping">MAPPING</a></code>), but the application can
|
|||
|
|
define additional methods (e.g. for encoding CLOS objects).
|
|||
|
|
</p>
|
|||
|
|
For example:
|
|||
|
|
<pre>CL-USER> (yason:encode
|
|||
|
|
(list (alexandria:plist-hash-table
|
|||
|
|
'("foo" 1 "bar" (7 8 9))
|
|||
|
|
:test #'equal)
|
|||
|
|
2 3 4
|
|||
|
|
'(5 6 7)
|
|||
|
|
t nil)
|
|||
|
|
*standard-output*)
|
|||
|
|
[{"foo":1,"bar":[7,8,9]},2,3,4,[5,6,7],true,null]
|
|||
|
|
(#<HASH-TABLE :TEST EQUAL :COUNT 2 {59942D21}> 2 3 4 (5 6 7) T NIL)</pre>
|
|||
|
|
|
|||
|
|
<h4 xmlns=""><a name="dom-encoder-dict">DOM encoder dictionary</a></h4>
|
|||
|
|
<p xmlns="">[Generic function]<br><a class="none" name="encode"><b>encode</b> <i><clix:lambda-list xmlns:clix="http://bknr.net/clixdoc">object &optional
|
|||
|
|
stream</clix:lambda-list></i>
|
|||
|
|
=>
|
|||
|
|
<i>object</i></a><blockquote><clix:description xmlns:clix="http://bknr.net/clixdoc">
|
|||
|
|
Encode <code><i>object</i></code> in JSON format and
|
|||
|
|
write to <code><i>stream</i></code>. May be specialized
|
|||
|
|
by applications to perform specific rendering. Stream
|
|||
|
|
defaults to *STANDARD-OUTPUT*.
|
|||
|
|
</clix:description></blockquote></p>
|
|||
|
|
|
|||
|
|
<p xmlns="">[Function]<br><a class="none" name="encode-alist"><b>encode-alist</b> <i><clix:lambda-list xmlns:clix="http://bknr.net/clixdoc">object &optional (stream
|
|||
|
|
*standard-output*)</clix:lambda-list></i>
|
|||
|
|
=>
|
|||
|
|
<i>object</i></a><blockquote><clix:description xmlns:clix="http://bknr.net/clixdoc">
|
|||
|
|
Encodes <code><i>object</i></code>, an alist, in JSON
|
|||
|
|
format and write to <code><i>stream</i></code>.
|
|||
|
|
</clix:description></blockquote></p>
|
|||
|
|
|
|||
|
|
<p xmlns="">[Function]<br><a class="none" name="encode-plist"><b>encode-plist</b> <i><clix:lambda-list xmlns:clix="http://bknr.net/clixdoc">object &optional (stream
|
|||
|
|
*standard-output*)</clix:lambda-list></i>
|
|||
|
|
=>
|
|||
|
|
<i>object</i></a><blockquote><clix:description xmlns:clix="http://bknr.net/clixdoc">
|
|||
|
|
Encodes <code><i>object</i></code>, a plist, in JSON
|
|||
|
|
format and write to <code><i>stream</i></code>.
|
|||
|
|
</clix:description></blockquote></p>
|
|||
|
|
|
|||
|
|
<p xmlns="">[Function]<br><a class="none" name="make-json-output-stream"><b>make-json-output-stream</b> <i><clix:lambda-list xmlns:clix="http://bknr.net/clixdoc">stream &key (indent t)</clix:lambda-list></i>
|
|||
|
|
=>
|
|||
|
|
<i>stream</i></a><blockquote><clix:description xmlns:clix="http://bknr.net/clixdoc">
|
|||
|
|
Creates a <code><a href="#json-output-stream">json-output-stream</a></code> instance
|
|||
|
|
that wraps the supplied <code><i>stream</i></code> and
|
|||
|
|
optionally performs indentation of the generated JSON
|
|||
|
|
data. The <code><i>indent</i></code> argument is
|
|||
|
|
described in <code><a href="#with-output">WITH-OUTPUT</a></code>. Note that
|
|||
|
|
if the <code><i>indent</i></code> argument is NIL, the
|
|||
|
|
original stream is returned in order to avoid the
|
|||
|
|
performance penalty of the indentation algorithm.
|
|||
|
|
</clix:description></blockquote></p>
|
|||
|
|
|
|||
|
|
<p xmlns="">
|
|||
|
|
[Special variable]<br><a class="none" name="*list-encoder*"><b>*list-encoder*</b></a><blockquote><clix:description xmlns:clix="http://bknr.net/clixdoc">
|
|||
|
|
Function to call to translate a CL list into JSON data.
|
|||
|
|
<code><i>'YASON:ENCODE-PLAIN-LIST-TO-ARRAY</i></code> is the default;
|
|||
|
|
<code><i>'YASON:ENCODE-PLIST</i></code> and
|
|||
|
|
<code><i>'YASON:ENCODE-ALIST</i></code> are available to produce
|
|||
|
|
JSON objects.
|
|||
|
|
<p xmlns="http://www.w3.org/1999/xhtml">
|
|||
|
|
This is useful to translate a deeply recursive structure in a single
|
|||
|
|
<code xmlns=""><i>YASON:ENCODE</i></code> call.
|
|||
|
|
</p>
|
|||
|
|
</clix:description></blockquote></p>
|
|||
|
|
|
|||
|
|
|
|||
|
|
<p xmlns="">
|
|||
|
|
[Special variable]<br><a class="none" name="*symbol-key-encoder*"><b>*symbol-key-encoder*</b></a><blockquote><clix:description xmlns:clix="http://bknr.net/clixdoc">
|
|||
|
|
Defines the policy to encode symbols as keys (eg. in hash tables).
|
|||
|
|
The default is to error out, to provide backwards-compatible behaviour.
|
|||
|
|
<p xmlns="http://www.w3.org/1999/xhtml">
|
|||
|
|
A useful function that can be bound to this variable is
|
|||
|
|
<code xmlns=""><a href="#yason:encode-symbol-as-lowercase.">YASON:ENCODE-SYMBOL-AS-LOWERCASE.</a></code>
|
|||
|
|
</p>
|
|||
|
|
</clix:description></blockquote></p>
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
<h4 xmlns=""><a name="stream-encoder">Encoding JSON in streaming mode</a></h4>
|
|||
|
|
<p>
|
|||
|
|
In this mode, the JSON structure is generated in a stream.
|
|||
|
|
The application makes explicit calls to the encoding library
|
|||
|
|
in order to generate the JSON structure. It provides for more
|
|||
|
|
control over the generated output, and can be used to generate
|
|||
|
|
arbitary JSON without requiring that there exists a directly
|
|||
|
|
matching Lisp data structure. The streaming API uses the
|
|||
|
|
<code xmlns=""><a href="#encode">encode</a></code> function, so it is possible to
|
|||
|
|
intermix the two (see <code xmlns=""><a href="#app-encoders">app-encoders</a></code> for an
|
|||
|
|
example).
|
|||
|
|
</p>
|
|||
|
|
For example:
|
|||
|
|
<pre>CL-USER> (yason:with-output (*standard-output*)
|
|||
|
|
(yason:with-array ()
|
|||
|
|
(dotimes (i 3)
|
|||
|
|
(yason:encode-array-element i))))
|
|||
|
|
[0,1,2]
|
|||
|
|
NIL
|
|||
|
|
CL-USER> (yason:with-output (*standard-output*)
|
|||
|
|
(yason:with-object ()
|
|||
|
|
(yason:encode-object-element "hello" "hu hu")
|
|||
|
|
(yason:with-object-element ("harr")
|
|||
|
|
(yason:with-array ()
|
|||
|
|
(dotimes (i 3)
|
|||
|
|
(yason:encode-array-element i))))))
|
|||
|
|
{"hello":"hu hu","harr":[0,1,2]}
|
|||
|
|
NIL</pre>
|
|||
|
|
|
|||
|
|
<h4 xmlns=""><a name="stream-encoder-dict">Streaming encoder dictionary</a></h4>
|
|||
|
|
<p xmlns="">[Macro]<br><a class="none" name="with-output"><b>with-output</b> <i><clix:lambda-list xmlns:clix="http://bknr.net/clixdoc">(stream &key indent) &body body</clix:lambda-list></i>
|
|||
|
|
=>
|
|||
|
|
<i>result*</i></a><blockquote><clix:description xmlns:clix="http://bknr.net/clixdoc">
|
|||
|
|
Set up a JSON streaming encoder context on
|
|||
|
|
<code><i>stream</i></code>, then evaluate
|
|||
|
|
<code><i>body</i></code>. <code><i>indent</i></code>
|
|||
|
|
can be set to T to enable indentation with a default
|
|||
|
|
indentation width or to an integer specifying the desired
|
|||
|
|
indentation width. By default, indentation is switched
|
|||
|
|
off.
|
|||
|
|
</clix:description></blockquote></p>
|
|||
|
|
|
|||
|
|
<p xmlns="">[Macro]<br><a class="none" name="with-output-to-string*"><b>with-output-to-string*</b> <i><clix:lambda-list xmlns:clix="http://bknr.net/clixdoc">(&key indent stream-symbol) &body body</clix:lambda-list></i>
|
|||
|
|
=>
|
|||
|
|
<i>result*</i></a><blockquote><clix:description xmlns:clix="http://bknr.net/clixdoc">
|
|||
|
|
Set up a JSON streaming encoder context on
|
|||
|
|
<code><i>stream-symbol</i></code> (by default
|
|||
|
|
a gensym), then evaluate
|
|||
|
|
<code><i>body</i></code>. Return a string with the
|
|||
|
|
generated JSON output. See
|
|||
|
|
<code><a href="#with-output">WITH-OUTPUT</a></code> for the description of
|
|||
|
|
the <code><i>indent</i></code> keyword argument.
|
|||
|
|
</clix:description></blockquote></p>
|
|||
|
|
|
|||
|
|
<p xmlns="">
|
|||
|
|
[Condition type]<br><a class="none" name="no-json-output-context"><b>no-json-output-context</b></a><blockquote><clix:description xmlns:clix="http://bknr.net/clixdoc">
|
|||
|
|
This condition is signalled when one of the stream
|
|||
|
|
encoding functions is used outside the dynamic context of
|
|||
|
|
a <code><a href="#with-output">WITH-OUTPUT</a></code> or
|
|||
|
|
<code><a href="#with-output-to-string*">WITH-OUTPUT-TO-STRING*</a></code> body.
|
|||
|
|
</clix:description></blockquote></p>
|
|||
|
|
|
|||
|
|
<p xmlns="">[Macro]<br><a class="none" name="with-array"><b>with-array</b> <i><clix:lambda-list xmlns:clix="http://bknr.net/clixdoc">() &body body</clix:lambda-list></i>
|
|||
|
|
=>
|
|||
|
|
<i>result*</i></a><blockquote><clix:description xmlns:clix="http://bknr.net/clixdoc">
|
|||
|
|
Open a JSON array, then run <code><i>body</i></code>.
|
|||
|
|
Inside the body, <code><a href="#encode-array-element">ENCODE-ARRAY-ELEMENT</a></code>
|
|||
|
|
must be called to encode elements to the opened array.
|
|||
|
|
Must be called within an existing JSON encoder context
|
|||
|
|
(see <code><a href="#with-output">WITH-OUTPUT</a></code> and
|
|||
|
|
<code><a href="#with-output-to-string*">WITH-OUTPUT-TO-STRING*</a></code>).
|
|||
|
|
</clix:description></blockquote></p>
|
|||
|
|
|
|||
|
|
<p xmlns="">[Function]<br><a class="none" name="encode-array-element"><b>encode-array-element</b> <i><clix:lambda-list xmlns:clix="http://bknr.net/clixdoc">object</clix:lambda-list></i>
|
|||
|
|
=>
|
|||
|
|
<i>object</i></a><blockquote><clix:description xmlns:clix="http://bknr.net/clixdoc">
|
|||
|
|
Encode <code><i>object</i></code> as next array element to
|
|||
|
|
the last JSON array opened
|
|||
|
|
with <code><a href="#with-array">WITH-ARRAY</a></code> in the dynamic
|
|||
|
|
context. <code><i>object</i></code> is encoded using the
|
|||
|
|
<code><a href="#encode">ENCODE</a></code> generic function, so it must be of
|
|||
|
|
a type for which an <code><a href="#encode">ENCODE</a></code> method is
|
|||
|
|
defined.
|
|||
|
|
</clix:description></blockquote></p>
|
|||
|
|
|
|||
|
|
<p xmlns="">[Function]<br><a class="none" name="encode-array-elements"><b>encode-array-elements</b> <i><clix:lambda-list xmlns:clix="http://bknr.net/clixdoc">&rest objects</clix:lambda-list></i>
|
|||
|
|
=>
|
|||
|
|
<i>result*</i></a><blockquote><clix:description xmlns:clix="http://bknr.net/clixdoc">
|
|||
|
|
Encode <code><i>objects</i></code>, a series of JSON
|
|||
|
|
encodable objects, as the next array elements in a JSON
|
|||
|
|
array opened with
|
|||
|
|
<code><a href="#with-array">WITH-ARRAY</a></code>. ENCODE-ARRAY-ELEMENTS
|
|||
|
|
uses <code><a href="#encode-array-element">ENCODE-ARRAY-ELEMENT</a></code>, which must
|
|||
|
|
be applicable to each object in the list
|
|||
|
|
(i.e. <code><a href="#encode">ENCODE</a></code> must be defined for each
|
|||
|
|
object type). Additionally, this must be called within a
|
|||
|
|
valid stream context.
|
|||
|
|
</clix:description></blockquote></p>
|
|||
|
|
|
|||
|
|
<p xmlns="">[Macro]<br><a class="none" name="with-object"><b>with-object</b> <i><clix:lambda-list xmlns:clix="http://bknr.net/clixdoc">() &body body</clix:lambda-list></i>
|
|||
|
|
=>
|
|||
|
|
<i>result*</i></a><blockquote><clix:description xmlns:clix="http://bknr.net/clixdoc">
|
|||
|
|
Open a JSON object, then run <code><i>body</i></code>.
|
|||
|
|
Inside the body,
|
|||
|
|
<code><a href="#encode-object-element">ENCODE-OBJECT-ELEMENT</a></code> or
|
|||
|
|
<code><a href="#with-object-element">WITH-OBJECT-ELEMENT</a></code> must be called to
|
|||
|
|
encode elements to the object. Must be called within an
|
|||
|
|
existing JSON encoder
|
|||
|
|
<code><a href="#with-output">WITH-OUTPUT</a></code> and
|
|||
|
|
<code><a href="#with-output-to-string*">WITH-OUTPUT-TO-STRING*</a></code>.
|
|||
|
|
</clix:description></blockquote></p>
|
|||
|
|
|
|||
|
|
<p xmlns="">[Macro]<br><a class="none" name="with-object-element"><b>with-object-element</b> <i><clix:lambda-list xmlns:clix="http://bknr.net/clixdoc">(key) &body body</clix:lambda-list></i>
|
|||
|
|
=>
|
|||
|
|
<i>result*</i></a><blockquote><clix:description xmlns:clix="http://bknr.net/clixdoc">
|
|||
|
|
Open a new encoding context to encode a JSON object
|
|||
|
|
element. <code><i>key</i></code> is the key of the
|
|||
|
|
element. The value will be whatever
|
|||
|
|
<code><i>body</i></code> serializes to the current JSON
|
|||
|
|
output context using one of the stream encoding functions.
|
|||
|
|
This can be used to stream out nested object structures.
|
|||
|
|
</clix:description></blockquote></p>
|
|||
|
|
|
|||
|
|
<p xmlns="">[Function]<br><a class="none" name="encode-object-element"><b>encode-object-element</b> <i><clix:lambda-list xmlns:clix="http://bknr.net/clixdoc">key value</clix:lambda-list></i>
|
|||
|
|
=>
|
|||
|
|
<i>value</i></a><blockquote><clix:description xmlns:clix="http://bknr.net/clixdoc">
|
|||
|
|
Encode <code><i>key</i></code> and
|
|||
|
|
<code><i>value</i></code> as object element to the last
|
|||
|
|
JSON object opened with <code><a href="#with-object">WITH-OBJECT</a></code>
|
|||
|
|
in the dynamic context. <code><i>key</i></code> and
|
|||
|
|
<code><i>value</i></code> are encoded using the
|
|||
|
|
<code><a href="#encode">ENCODE</a></code> generic function, so they both
|
|||
|
|
must be of a type for which an <code><a href="#encode">ENCODE</a></code>
|
|||
|
|
method is defined.
|
|||
|
|
</clix:description></blockquote></p>
|
|||
|
|
|
|||
|
|
<p xmlns="">[Function]<br><a class="none" name="encode-object-elements"><b>encode-object-elements</b> <i><clix:lambda-list xmlns:clix="http://bknr.net/clixdoc">&rest elements</clix:lambda-list></i>
|
|||
|
|
=>
|
|||
|
|
<i>result*</i></a><blockquote><clix:description xmlns:clix="http://bknr.net/clixdoc">
|
|||
|
|
Encodes the parameters into JSON in the last object opened
|
|||
|
|
with <code><a href="#with-object">WITH-OBJECT</a></code> using
|
|||
|
|
<code><a href="#encode-object-element">ENCODE-OBJECT-ELEMENT</a></code>. The parameters
|
|||
|
|
should consist of alternating key/value pairs, and this
|
|||
|
|
must be called within a valid stream context.
|
|||
|
|
</clix:description></blockquote></p>
|
|||
|
|
|
|||
|
|
<p xmlns="">[Function]<br><a class="none" name="encode-object-slots"><b>encode-object-slots</b> <i><clix:lambda-list xmlns:clix="http://bknr.net/clixdoc">object slots</clix:lambda-list></i>
|
|||
|
|
=>
|
|||
|
|
<i>result*</i></a><blockquote><clix:description xmlns:clix="http://bknr.net/clixdoc">
|
|||
|
|
Encodes each slot in SLOTS for OBJECT in the last object
|
|||
|
|
opened with <code><a href="#with-object">WITH-OBJECT</a></code> using
|
|||
|
|
<code><a href="#encode-object-element">ENCODE-OBJECT-ELEMENT</a></code>. The key is the
|
|||
|
|
slot name, and the value is the slot value for the slot on
|
|||
|
|
OBJECT. It is equivalent to
|
|||
|
|
<pre xmlns="http://www.w3.org/1999/xhtml">(loop for slot in slots
|
|||
|
|
do (encode-object-element (string slot)
|
|||
|
|
(slot-value object slot)))
|
|||
|
|
</pre>
|
|||
|
|
</clix:description></blockquote></p>
|
|||
|
|
|
|||
|
|
<p xmlns="">[Function]<br><a class="none" name="encode-slots"><b>encode-slots</b> <i><clix:lambda-list xmlns:clix="http://bknr.net/clixdoc">object</clix:lambda-list></i>
|
|||
|
|
=>
|
|||
|
|
<i>result*</i></a><blockquote><clix:description xmlns:clix="http://bknr.net/clixdoc">
|
|||
|
|
Generic function to encode object slots. There is no default
|
|||
|
|
implementation.
|
|||
|
|
It should be called in an object encoding context. It uses
|
|||
|
|
PROGN combinatation with MOST-SPECIFIC-LAST order, so that
|
|||
|
|
base class slots are encoded before derived class slots.
|
|||
|
|
</clix:description></blockquote></p>
|
|||
|
|
|
|||
|
|
<p xmlns="">[Function]<br><a class="none" name="encode-object"><b>encode-object</b> <i><clix:lambda-list xmlns:clix="http://bknr.net/clixdoc">object</clix:lambda-list></i>
|
|||
|
|
=>
|
|||
|
|
<i>result*</i></a><blockquote><clix:description xmlns:clix="http://bknr.net/clixdoc">
|
|||
|
|
Generic function to encode an object. The default implementation
|
|||
|
|
opens a new object encoding context and calls
|
|||
|
|
<code><a href="#encode-slots">ENCODE-SLOTS</a></code> on the argument.
|
|||
|
|
</clix:description></blockquote></p>
|
|||
|
|
|
|||
|
|
<p xmlns="">
|
|||
|
|
[Standard class]<br><a class="none" name="json-output-stream"><b>json-output-stream</b></a><blockquote><clix:description xmlns:clix="http://bknr.net/clixdoc">
|
|||
|
|
Instances of this class are used to wrap an output stream
|
|||
|
|
that is used as a serialization target in the stream
|
|||
|
|
encoder and optionally in the DOM encoder if indentation
|
|||
|
|
is desired. The class name is not exported, use
|
|||
|
|
<code><a href="#make-json-output-stream">make-json-output-stream</a></code> to create a
|
|||
|
|
wrapper stream if required.
|
|||
|
|
</clix:description></blockquote></p>
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
<h4 xmlns=""><a name="app-encoders">Application specific encoders</a></h4>
|
|||
|
|
|
|||
|
|
Suppose your application uses structs to represent its data and
|
|||
|
|
you want to encode these structs using JSON in order to send
|
|||
|
|
them to a client application. Suppose further that your structs
|
|||
|
|
also include internal information that you do not want to send.
|
|||
|
|
Here is some code that illustrates how one could implement a
|
|||
|
|
serialization function:
|
|||
|
|
|
|||
|
|
<pre>CL-USER> (defstruct user name age password)
|
|||
|
|
USER
|
|||
|
|
CL-USER> (defmethod yason:encode ((user user) &optional (stream *standard-output*))
|
|||
|
|
(yason:with-output (stream)
|
|||
|
|
(yason:with-object ()
|
|||
|
|
(yason:encode-object-element "name" (user-name user))
|
|||
|
|
(yason:encode-object-element "age" (user-age user)))))
|
|||
|
|
#<STANDARD-METHOD YASON:ENCODE (USER) {5B40A591}>
|
|||
|
|
CL-USER> (yason:encode (list (make-user :name "horst" :age 27 :password "puppy")
|
|||
|
|
(make-user :name "uschi" :age 28 :password "kitten")))
|
|||
|
|
[{"name":"horst","age":27},{"name":"uschi","age":28}]
|
|||
|
|
(#S(USER :NAME "horst" :AGE 27 :PASSWORD "puppy")
|
|||
|
|
#S(USER :NAME "uschi" :AGE 28 :PASSWORD "kitten"))</pre>
|
|||
|
|
|
|||
|
|
As you can see, the streaming API and the DOM encoder can be
|
|||
|
|
used together. <code xmlns=""><a href="#encode">ENCODE</a></code> invokes itself
|
|||
|
|
recursively, so any application defined method will be called
|
|||
|
|
while encoding in-memory objects as appropriate.
|
|||
|
|
|
|||
|
|
<p>For an example of the interplay between
|
|||
|
|
<code xmlns=""><a href="#encode-object">ENCODE-OBJECT</a></code> and
|
|||
|
|
<code xmlns=""><a href="#encode-slots">ENCODE-SLOTS</a></code>, suppose you have the following
|
|||
|
|
CLOS class heirarchy:
|
|||
|
|
|
|||
|
|
<pre>(defclass shape ()
|
|||
|
|
((color :reader color)))
|
|||
|
|
|
|||
|
|
(defclass square (shape)
|
|||
|
|
((side-length :reader side-length)))
|
|||
|
|
|
|||
|
|
(defclass circle (shape)
|
|||
|
|
((radius :reader radius)))</pre>
|
|||
|
|
|
|||
|
|
In order to implement encoding of circles and squares without
|
|||
|
|
duplicating code you can specialize
|
|||
|
|
<code xmlns=""><a href="#encode-slots">ENCODE-SLOTS</a></code> for all three classes
|
|||
|
|
|
|||
|
|
<pre>(defmethod yason:encode-slots progn ((shape shape))
|
|||
|
|
(yason:encode-object-element "color" (color shape)))
|
|||
|
|
|
|||
|
|
(defmethod yason:encode-slots progn ((square square))
|
|||
|
|
(yason:encode-object-element "side-length" (side-length square)))
|
|||
|
|
|
|||
|
|
(defmethod yason:encode-slots progn ((circle circle))
|
|||
|
|
(yason:encode-object-element "radius" (radius circle)))</pre>
|
|||
|
|
|
|||
|
|
and then use <code xmlns=""><a href="#encode-object">ENCODE-OBJECT</a></code>:
|
|||
|
|
|
|||
|
|
<pre>CL-USER> (yason:with-output-to-string* ()
|
|||
|
|
(yason:encode-object (make-instance 'square :color "red" :side-length 3)))
|
|||
|
|
"{\"color\":\"red\",\"side-length\":3}"
|
|||
|
|
CL-USER> (yason:with-output-to-string* ()
|
|||
|
|
(yason:encode-object (make-instance 'circle :color "blue" :side-length 5)))
|
|||
|
|
"{\"color\":\"blue\",\"radius\":5}"</pre>
|
|||
|
|
</p>
|
|||
|
|
<p>Alternatively, you can use the shortcut <code xmlns=""><a href="#encode-object-slots">ENCODE-OBJECT-SLOTS</a></code>
|
|||
|
|
if you want the keys to be the slot names. For example:
|
|||
|
|
<pre>(defclass person ()
|
|||
|
|
((name :reader name :initarg :name)
|
|||
|
|
(address :reader address :initarg :address)
|
|||
|
|
(phone-number :reader phone-number :initarg :phone)
|
|||
|
|
(favorite-color :reader favorite-color :initarg :color)))
|
|||
|
|
|
|||
|
|
(defmethod yason:encode-slots progn ((person person))
|
|||
|
|
(yason:encode-object-slots person '(name address phone-number favorite-color)))</pre>
|
|||
|
|
and then:
|
|||
|
|
|
|||
|
|
<pre>CL-USER> (yason:with-output-to-string* ()
|
|||
|
|
(yason:encode-object (make-instance 'person :name "John Doe"
|
|||
|
|
:address "123 Main St."
|
|||
|
|
:phone "(123)-456-7890"
|
|||
|
|
:color "blue")))
|
|||
|
|
"{\"NAME\":\"John Doe\",\"ADDRESS\":\"123 Main St.\",\"PHONE-NUMBER\":\"(123)-456-7890\",
|
|||
|
|
\"FAVORITE-COLOR\":\"blue\"}"</pre>
|
|||
|
|
</p>
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
<h3 xmlns=""><a class="none" name="index">Symbol index</a></h3>
|
|||
|
|
<ul xmlns="">
|
|||
|
|
<li><code><a href="#*list-encoder*">*list-encoder*</a></code></li>
|
|||
|
|
<li><code><a href="#*parse-json-arrays-as-vectors*">*parse-json-arrays-as-vectors*</a></code></li>
|
|||
|
|
<li><code><a href="#*parse-json-booleans-as-symbols*">*parse-json-booleans-as-symbols*</a></code></li>
|
|||
|
|
<li><code><a href="#*parse-json-null-as-keyword*">*parse-json-null-as-keyword*</a></code></li>
|
|||
|
|
<li><code><a href="#*parse-object-as*">*parse-object-as*</a></code></li>
|
|||
|
|
<li><code><a href="#*parse-object-key-fn*">*parse-object-key-fn*</a></code></li>
|
|||
|
|
<li><code><a href="#*symbol-key-encoder*">*symbol-key-encoder*</a></code></li>
|
|||
|
|
<li><code><a href="#encode">encode</a></code></li>
|
|||
|
|
<li><code><a href="#encode-alist">encode-alist</a></code></li>
|
|||
|
|
<li><code><a href="#encode-array-element">encode-array-element</a></code></li>
|
|||
|
|
<li><code><a href="#encode-array-elements">encode-array-elements</a></code></li>
|
|||
|
|
<li><code><a href="#encode-object">encode-object</a></code></li>
|
|||
|
|
<li><code><a href="#encode-object-element">encode-object-element</a></code></li>
|
|||
|
|
<li><code><a href="#encode-object-elements">encode-object-elements</a></code></li>
|
|||
|
|
<li><code><a href="#encode-object-slots">encode-object-slots</a></code></li>
|
|||
|
|
<li><code><a href="#encode-plist">encode-plist</a></code></li>
|
|||
|
|
<li><code><a href="#encode-slots">encode-slots</a></code></li>
|
|||
|
|
<li><code><a href="#json-output-stream">json-output-stream</a></code></li>
|
|||
|
|
<li><code><a href="#make-json-output-stream">make-json-output-stream</a></code></li>
|
|||
|
|
<li><code><a href="#no-json-output-context">no-json-output-context</a></code></li>
|
|||
|
|
<li><code><a href="#parse">parse</a></code></li>
|
|||
|
|
<li><code><a href="#with-array">with-array</a></code></li>
|
|||
|
|
<li><code><a href="#with-object">with-object</a></code></li>
|
|||
|
|
<li><code><a href="#with-object-element">with-object-element</a></code></li>
|
|||
|
|
<li><code><a href="#with-output">with-output</a></code></li>
|
|||
|
|
<li><code><a href="#with-output-to-string*">with-output-to-string*</a></code></li>
|
|||
|
|
</ul>
|
|||
|
|
|
|||
|
|
|
|||
|
|
<h3 xmlns=""><a class="none" name="license">License</a></h3>
|
|||
|
|
<pre class="none">Copyright (c) 2008-2014 Hans Hübner and contributors
|
|||
|
|
All rights reserved.
|
|||
|
|
|
|||
|
|
Redistribution and use in source and binary forms, with or without
|
|||
|
|
modification, are permitted provided that the following conditions are
|
|||
|
|
met:
|
|||
|
|
|
|||
|
|
- Redistributions of source code must retain the above copyright
|
|||
|
|
notice, this list of conditions and the following disclaimer.
|
|||
|
|
|
|||
|
|
- Redistributions in binary form must reproduce the above copyright
|
|||
|
|
notice, this list of conditions and the following disclaimer in
|
|||
|
|
the documentation and/or other materials provided with the
|
|||
|
|
distribution.
|
|||
|
|
|
|||
|
|
- Neither the name BKNR nor the names of its contributors may be
|
|||
|
|
used to endorse or promote products derived from this software
|
|||
|
|
without specific prior written permission.
|
|||
|
|
|
|||
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|||
|
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|||
|
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|||
|
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|||
|
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|||
|
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|||
|
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|||
|
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|||
|
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|||
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|||
|
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
|
</pre>
|
|||
|
|
|
|||
|
|
|
|||
|
|
<h3 xmlns=""><a class="none" name="ack">Acknowledgements</a></h3>
|
|||
|
|
Thanks go to Edi Weitz for being a great inspiration. This
|
|||
|
|
documentation as been generated with a hacked-up version of his <a href="http://weitz.de/documentation-template/">DOCUMENTATION-TEMPLATE</a>
|
|||
|
|
software. Thanks to David Lichteblau for coining YASON's name.
|
|||
|
|
|
|||
|
|
|
|||
|
|
</body></html>
|