forked from Telodendria/Telodendria
264 lines
8.5 KiB
Groff
264 lines
8.5 KiB
Groff
.Dd $Mdocdate: March 12 2023 $
|
|
.Dt JSON 3
|
|
.Os Telodendria Project
|
|
.Sh NAME
|
|
.Nm Json
|
|
.Nd A fully-featured JSON API.
|
|
.Sh SYNOPSIS
|
|
.In Json.h
|
|
.Ft JsonType
|
|
.Fn JsonValueType "JsonValue *"
|
|
.Ft JsonValue *
|
|
.Fn JsonValueObject "HashMap *"
|
|
.Ft HashMap *
|
|
.Fn JsonValueAsObject "JsonValue *"
|
|
.Ft JsonValue *
|
|
.Fn JsonValueArray "Array *"
|
|
.Ft Array *
|
|
.Fn JsonValueAsArray "
|
|
.Ft JsonValue *
|
|
.Fn JsonValueString "char *"
|
|
.Ft char *
|
|
.Fn JsonValueAsString "JsonValue *"
|
|
.Ft JsonValue *
|
|
.Fn JsonValueInteger "long"
|
|
.Ft long
|
|
.Fn JsonValueAsInteger "JsonValue *"
|
|
.Ft JsonValue *
|
|
.Fn JsonValueFloat "double"
|
|
.Ft double
|
|
.Fn JsonValueAsFloat "JsonValue *"
|
|
.Ft JsonValue *
|
|
.Fn JsonValueBoolean "int"
|
|
.Ft int
|
|
.Fn JsonValueAsBoolean "JsonValue *"
|
|
.Ft JsonValue *
|
|
.Fn JsonValueNull "void"
|
|
.Ft void
|
|
.Fn JsonValueFree "JsonValue *"
|
|
.Ft void
|
|
.Fn JsonFree "HashMap *"
|
|
.Ft void
|
|
.Fn JsonEncodeString "const char *" "FILE *"
|
|
.Ft void
|
|
.Fn JsonEncodeValue "JsonValue *" "FILE *" "int"
|
|
.Ft int
|
|
.Fn JsonEncode "HashMap *" "FILE *" "int"
|
|
.Ft HashMap *
|
|
.Fn JsonDecode "FILE *"
|
|
.Ft JsonValue *
|
|
.Fn JsonGet "HashMap *" "size_t" "..."
|
|
.Ft JsonValue *
|
|
.Fn JsonSet "HashMap *" "size_t" "..."
|
|
.Sh DESCRIPTION
|
|
.Nm
|
|
is a fully-featured JSON API for C using
|
|
.Xr Array 3
|
|
and
|
|
.Xr HashMap 3
|
|
that can parse JSON, and serialize an in-memory structure
|
|
to JSON.
|
|
It builds on the foundation set up by those APIs because
|
|
that's all JSON really is, just maps and arrays.
|
|
.Nm
|
|
also provides a structure for encapsulating an arbitrary
|
|
value and identifying its type, making it easy for a program
|
|
to work with JSON data.
|
|
.Nm
|
|
is very strict and tries to adhere as closely as possible to
|
|
the proper defintion of JSON. It will fail on syntax errors
|
|
of any kind, which is fine for a Matrix homeserver because we can
|
|
just return M_BAD_JSON if anything here fails, but it may not
|
|
be suitable for other purposes.
|
|
.Pp
|
|
This JSON implementation focuses primarily on serialization and
|
|
deserialization to and from streams. It does not provide facilities
|
|
for handling JSON strings; it only writes JSON to output streams, and
|
|
reads them from input streams. If course, you can use the POSIX
|
|
.Xr fmemopen 3
|
|
and
|
|
.Xr open_memstream 3
|
|
if you want to deal with JSON strings, but JSON is intended to be an
|
|
exchange format. Data should be converted to JSON right before it is
|
|
leaving the program, and converted from JSON as soon as it is coming
|
|
in.
|
|
.Pp
|
|
The
|
|
.Nm
|
|
header defines the following enumeration for identifying types of
|
|
values:
|
|
.Bd -literal -offset indent
|
|
typedef enum JsonType
|
|
{
|
|
JSON_NULL, /* Maps to C NULL */
|
|
JSON_OBJECT, /* Maps to a HashMap of JsonValues */
|
|
JSON_ARRAY, /* Maps to an Array of JsonValues */
|
|
JSON_STRING, /* Maps to a NULL-terminated C string */
|
|
JSON_INTEGER, /* Maps to a C long */
|
|
JSON_FLOAT, /* Maps to a C double */
|
|
JSON_BOOLEAN /* Maps to a C boolean, 1 or 0 */
|
|
} JsonType;
|
|
.Ed
|
|
.Pp
|
|
A JsonValue encapsulates all the possible types that can be stored in
|
|
JSON. It is an opaque structure that can be managed entirely by the
|
|
functions defined in this API. It is important to note that in the case
|
|
of objects, arrays, and strings, this structure only stores pointers to
|
|
the allocated data, it doesn't store the data itself, but the data IS
|
|
freed when using
|
|
.Fn JsonFree .
|
|
.Pp
|
|
Objects are represented as hash maps consisting entirely of JsonValue
|
|
structures, and arrays are represented as arrays consisting entirely
|
|
of JsonValue structures. When generating a JSON object, any
|
|
attempt to stuff a value into a hash map or array without encoding it
|
|
as a JsonValue first will result in undefined behavior.
|
|
.Pp
|
|
.Fn JsonValueType
|
|
determines the type of a given JsonValue.
|
|
.Pp
|
|
The
|
|
.Fn JsonValue*
|
|
functions wrap their input in a JsonValue that represents the given
|
|
value. The
|
|
.Fn JsonValueAs*
|
|
functions do the opposite; they unwrap a JsonValue and return the
|
|
actual usable value itself. They all closely resemble each other and
|
|
they all behave the same way, so to save on time and effort, they're
|
|
not explicitly documented individually. If something is unclear about
|
|
how these functions work, consult the source code, and feel free
|
|
to write the documentation yourself for clarification. Otherwise,
|
|
reach out to the official Matrix rooms, and someone should be able
|
|
to help you.
|
|
.Pp
|
|
.Fn JsonValueNull
|
|
is a special case that represents a JSON null. Because
|
|
.Xr Array 3
|
|
and
|
|
.Xr HashMap 3
|
|
do not accept NULL values, this function should be used to represent
|
|
NULL in JSON. Even though a small amount of memory is allocated just
|
|
to point to NULL, this keeps the APIs clean.
|
|
.Pp
|
|
.Fn JsonValueFree
|
|
frees the memory being used by a JSON value. Note that this will
|
|
recursively free all Arrays, HashMaps, and other JsonValues that
|
|
are reachable from the given value. It also invokes
|
|
.Fn Free
|
|
(documented in
|
|
.Xr Memory )
|
|
on all strings, so make sure passed string pointers point to strings
|
|
on the heap, not the stack. This will be the case for all strings
|
|
returned by
|
|
.Fn JsonDecode ,
|
|
but if you are manually creating JSON objects and stitching them
|
|
together, you should be aware that calling this function on a value
|
|
that contains a pointer to a stack string will result in undefined
|
|
behavior.
|
|
.Pp
|
|
.Fn JsonFree
|
|
recursively frees a JSON object, iterating over all the values and
|
|
freeing them using
|
|
.Fn JsonValueFree .
|
|
.Pp
|
|
.Fn JsonEncodeString
|
|
encodes the given string in such a way that it can be embedded in a
|
|
JSON stream. This entails:
|
|
.Bl -bullet -offset indent
|
|
.It
|
|
Escaping quotes, backslashes, and other special characters using
|
|
their backslash escape.
|
|
.It
|
|
Encoding bytes that are not UTF-8 using escapes.
|
|
.It
|
|
Wrapping the entire string in double quotes.
|
|
.El
|
|
.Pp
|
|
This function is provided via the public
|
|
.Nm
|
|
API so that it is accessible to custom JSON encoders, such as
|
|
.Xr CanonicalJson 3 .
|
|
This will typically be used for encoding JSON keys; for encoding
|
|
values, just use
|
|
.Fn JsonEncodeValue .
|
|
.Pp
|
|
.Fn JsonEncodeValue
|
|
serializes a JsonValue as it would appear in JSON output. This is
|
|
a recursive function that also encodes all child values reachable
|
|
from the given value. This function is exposed via the public
|
|
.Nm
|
|
API so that it is accessible to custom JSON encoders. Normal users
|
|
that are not writing custom encoders should in most cases just use
|
|
.Fn JsonEncode
|
|
to encode an entire object. The third parameter is an integer that
|
|
represents the indent level of the value to be printed, or a negative
|
|
number if pretty-printing should be disabled, and JSON should be
|
|
printed as minimized as possible. If you want to pretty-print a
|
|
JSON object, set this to
|
|
.Va JSON_PRETTY .
|
|
To get the minified output, set it to
|
|
.Va JSON_DEFAULT .
|
|
.Pp
|
|
.Fn JsonEncode
|
|
encodes a JSON object as minimized JSON and writes it to the given
|
|
output stream. This function is recursive; it will serialize
|
|
everything accessible from the passed object. The third integer
|
|
parameter has the same behavior asa described above.
|
|
.Pp
|
|
.Fn JsonDecode
|
|
does the opposite of
|
|
.Fn JsonEncode ;
|
|
it reads from a JSON stream and decodes it into a hash map
|
|
of JsonValues.
|
|
.Pp
|
|
.Fn JsonSet
|
|
and
|
|
.Fn JsonGet
|
|
are convenience functions that allow the caller to retrieve and
|
|
manipulate arbitrarily deep keys within a JSON object. They take
|
|
a root JSON object, the number of levels deep to go, and then that
|
|
number of keys as a varargs list. All keys must have objects
|
|
as values, with the exception of the last one, which is the one
|
|
being retrieved or set.
|
|
.Fn JsonSet
|
|
will create any intermediate objects as necessary to set the
|
|
proper key.
|
|
.Sh RETURN VALUES
|
|
.Pp
|
|
.Fn JsonValueType
|
|
returns a JsonType, documented above, that tells what the given
|
|
value actually is, or JSON_NULL if the passed value is NULL.
|
|
Note that even a fully valid JsonValue may actually be of type
|
|
JSON_NULL, so this function should not be used to determine
|
|
whether or not a given value is valid.
|
|
.Pp
|
|
The
|
|
.Fn JsonValue*
|
|
functions return a JsonValue that holds a pointer to the passed
|
|
value, or NULL if there was an error allocating memory. The
|
|
.Fn JsonValueAs*
|
|
functions return the actual value represented by the given
|
|
JsonValue so that it can be manipulated by the program, or
|
|
NULL if no value was provided, or the value is not of the
|
|
correct type expected by the function.
|
|
.Pp
|
|
.Fn JsonEncode
|
|
returns whether or not the encoding operation was successful.
|
|
This function will fail if any passed parameters are NULL,
|
|
otherwise it will assume all pointers are valid and return a
|
|
success value.
|
|
.Pp
|
|
.Fn JsonDecode
|
|
returns a hash map of JsonValues that can be manipulated by
|
|
this API, or NULL if there was an error parsing the JSON.
|
|
.Pp
|
|
.Fn JsonGet
|
|
returns a JsonValue, or NULL if the requested key is not set
|
|
in the object.
|
|
.Fn JsonGet
|
|
returns the previous value of the provided key, or NULL if there
|
|
was no previous value.
|
|
.Sh SEE ALSO
|
|
.Xr HashMap 3 ,
|
|
.Xr Array 3
|