.. default-domain:: chpl .. module:: JSON :synopsis: The Json module provides a ``jsonSerializer`` and ``jsonDeserializer`` that JSON ==== **Usage** .. code-block:: chapel use JSON; or .. code-block:: chapel import JSON; The Json module provides a ``jsonSerializer`` and ``jsonDeserializer`` that allow for reading and writing data in the JSON format. .. type:: type jsonWriter = fileWriter(serializerType = jsonSerializer, ?) Type Alias for an :record:`IO.fileWriter` that uses a :record:`jsonSerializer` .. type:: type jsonReader = fileReader(deserializerType = jsonDeserializer, ?) Type Alias for an :record:`IO.fileReader` that uses a :record:`jsonDeserializer` .. record:: jsonSerializer A JSON format serializer to be used by :record:`~IO.fileWriter`. Implements the 'serializeValue' method which is called by a ``fileWriter`` to produce a serialized representation of a value in JSON format. .. warning:: This serializer is designed to generate valid JSON; however, no guarantees are made about the exact formatting w.r.t. whitespace, newlines or indentation. See the :ref:`IO Serializers` technote for more information about serializers in general. .. method:: proc ref serializeValue(writer: jsonWriter, const val: ?t) throws Serialize ``val`` with ``writer``. Numeric values are serialized as though they were written with the format of ``%i`` for integers and ``%er`` for ``real`` numbers. Please refer to :ref:`the section on Formatted IO` for more information. Booleans are serialized as the literal strings ``true`` or ``false``. ``string`` values are serialized by wrapping the string in quotes, and escaping quotes inside the string. ``bytes`` values are also wrapped in quotes. Enums are serialized using the name of the corresponding value. For example with an enum like ``enum colors {red, green blue}``, the value ``red`` would be serialized as a string: ``"red"``. The ``nil`` value and nilable class variables storing ``nil`` will be serialized as the text ``null``. Classes and records will have their ``serialize`` method invoked, passing in ``writer`` and this Serializer as arguments. Please see the :ref:`serializers technote` for more. Classes and records are expected to implement the ``writeSerializable`` or ``serializable`` interface. :arg writer: The ``fileWriter`` used to write serialized output :arg val: The value to be serialized .. method:: proc startClass(writer: jsonWriter, name: string, size: int) throws Start serializing a class by writing the character ``{``. :arg writer: The ``fileWriter`` to be used when serializing :arg name: The name of the class type :arg size: The number of fields in the class :returns: A new :type:`AggregateSerializer` .. method:: proc startRecord(writer: jsonWriter, name: string, size: int) throws Start serializing a record by writing the character ``{``. :arg writer: The ``fileWriter`` to be used when serializing :arg name: The name of the class type :arg size: The number of fields in the class :returns: A new :type:`AggregateSerializer` .. record:: AggregateSerializer Returned by ``startClass`` or ``startRecord`` to provide the API for serializing classes or records. Classes and records are serialized as JSON objects. For example, a ``class`` or ``record`` with integer fields ``x`` and ``y`` with values ``0`` and ``5`` would be serialized as ``{"x":0, "y":5}``. .. method:: proc ref writeField(name: string, const field: ?) throws Serialize ``field`` named ``name``. Serializes fields in the form ``"":``. Adds a comma before the name if this is not the first field. .. method:: proc ref startClass(writer, name: string, size: int) throws Start serializing a nested class inside the current class. In this format inheritance is not represented and parent fields are printed before child fields. For example, the following classes with values ``x=5`` and ``y=2``: .. code-block:: chapel class Parent { var x : int; } class Child: Parent { var y : int; } would be serialized as: .. code-block:: text {"x":5, "y":2} :arg writer: The ``fileWriter`` to be used when serializing. Must match the writer used to create current AggregateSerializer :arg name: The name of the class type :arg size: The number of fields in the class :returns: A new AggregateSerializer .. method:: proc endClass() throws Ends serialization of the current class by writing the character ``}``. .. method:: proc endRecord() throws Ends serialization of the current record by writing the character ``}``. .. method:: proc startTuple(writer: jsonWriter, size: int) throws Start serializing a tuple by writing the character ``[``. In this format tuples are serialized as JSON lists. For example, the tuple ``(1, 2, 3)`` would be serialized as ``[1, 2, 3]``. :arg writer: The ``fileWriter`` to be used when serializing :arg size: The number of elements in the tuple :returns: A new :type:`ListSerializer` .. method:: proc startList(writer: jsonWriter, size: int) throws Start serializing a list by writing the character ``[``. :arg writer: The ``fileWriter`` to be used when serializing :arg size: The number of elements in the list :returns: A new :type:`ListSerializer` .. record:: ListSerializer Returned by ``startList`` or ``startTuple`` to provide the API for serializing JSON lists. A list will be serialized as a comma-separated series of serialized elements between two square brackets. For example, serializing a list with elements ``1``, ``2``, and ``3`` will produce the text: .. code-block:: text [1, 2, 3] Empty lists will be serialized as ``[]``. .. method:: proc ref writeElement(const element: ?) throws Serialize ``element``. Writes a leading comma before serializing the element if this is not the first element in the list. .. method:: proc endList() throws Ends serialization of the current list by writing the character ``]``. .. method:: proc endTuple() throws Ends serialization of the current tuple by writing the character ``]``. .. method:: proc startArray(writer: jsonWriter, size: int) throws Start serializing an array. :arg writer: The ``fileWriter`` to be used when serializing :arg size: The number of elements in the array :returns: A new :type:`ArraySerializer` .. record:: ArraySerializer Returned by ``startArray`` to provide the API for serializing arrays. In this format, a 1D array will be serialized as a JSON list. For example, an array with three values would be serialized as: .. code-block:: text [1, 2, 3] Multidimensional arrays will be serialized as JSON lists of lists: .. code-block:: text [ [0, 1, 2], [3, 4, 5], [6, 7, 8] ] The indenting of these multidimensional arrays is not considered stable. .. method:: proc ref startDim(size: int) throws Start serializing a new dimension of size ``size``. .. method:: proc ref endDim() throws End the current dimension. .. method:: proc ref writeElement(const element: ?) throws Serialize ``element``. Writes a leading comma if this is not the first element in the row. .. method:: proc endArray() throws Ends serialization of the current array. .. method:: proc startMap(writer: jsonWriter, size: int) throws Start serializing a map by writing the character ``{``. :arg writer: The ``fileWriter`` to be used when serializing :arg size: The number of entries in the map :returns: A new :type:`MapSerializer` .. record:: MapSerializer Returned by ``startMap`` to provide the API for serializing maps. Maps are serialized as JSON objects. For example, a map of strings to strings would be serialized as: .. code-block:: text { "east": "west", "hello": "goodbye", "north": "south", "day": "night" } The indenting and whitespace of this example is not considered stable. .. method:: proc ref writeKey(const key: ?) throws Serialize ``key``. .. note:: JSON itself only supports strings as names in objects. This module supports non-string key types by serializing them as an escaped JSON string containing the serialized key. For a simple integer key, this results in output like ``"123"``. For a record key with two integer fields, the output could look like: .. code-block:: text "{\"x\":1, \"y\":2}" Adds a leading comma if this is not the first pair in the map. .. method:: proc writeValue(const val: ?) throws Serialize ``val``, preceded by the character ``:``. .. method:: proc endMap() throws Ends serialization of the current map by writing the character ``}``. .. record:: jsonDeserializer A JSON format deserializer to be used by :record:`~IO.fileReader`. See :ref:`the serializers technote` for a general overview of Deserializers and their usage. Otherwise, please refer to :type:`jsonSerializer` for a description of the JSON serialization format. Individual methods on this type may clarify behavior specific to deserialization. Implements the ``deserializeType`` and ``deserializeValue`` methods which are called by a ``fileReader`` to deserialize a serialized representation of a type or value in JSON format. This deserializer supports reading class and record fields out-of-order by default. I.e., the fields of a JSON object do not need to match the declaration order in a Chapel type definition to be deserialized into that type. .. method:: proc ref deserializeType(reader: jsonReader, type readType): readType throws Deserialize type ``readType`` with ``reader``. Classes and records will be deserialized using an appropriate initializer, passing in ``reader`` and this Deserializer as arguments. If an initializer is unavailable, this method may invoke the class or record's ``deserialize`` method. Please see the :ref:`serializers technote` for more. Classes and records are expected to implement either the ``initDeserializable`` or ``readDeserializable`` interfaces (or both). Alternatively, types implementing the entire ``serializable`` interface are also accepted. :arg reader: The ``fileReader`` from which types are deserialized :arg readType: The type to be deserialized :returns: A value of type ``readType``. .. method:: proc ref deserializeValue(reader: jsonReader, ref val: ?readType): void throws Deserialize from ``reader`` directly into ``val``. Like :proc:`deserializeType`, but reads into an initialized value rather than creating a new value. For classes and records, this method will first attempt to invoke a ``deserialize`` method. If the ``deserialize`` method is unavailable, this method may fall back on invoking a suitable initializer and assigning the resulting value into ``val``.. Please see the :ref:`serializers technote` for more. Classes and records are expected to implement either the ``initDeserializable`` or ``readDeserializable`` interfaces (or both). Alternatively, types implementing the entire ``serializable`` interface are also accepted. :arg reader: The ``fileReader`` from which values are deserialized :arg val: The value into which this Deserializer will deserialize .. method:: proc startClass(reader: jsonReader, name: string) throws Start deserializing a class by reading the character ``{``. :arg reader: The ``fileReader`` to use when deserializing :arg name: The name of the class type :returns: A new :type:`AggregateDeserializer` .. method:: proc startRecord(reader: jsonReader, name: string) throws Start deserializing a record by reading the character ``{``. :arg reader: The ``fileReader`` to use when deserializing :arg name: The name of the record type :returns: A new :type:`AggregateDeserializer` .. record:: AggregateDeserializer Returned by ``startClass`` or ``startRecord`` to provide the API for deserializing classes or records. See ``jsonSerializer.AggregateSerializer`` for details of the JSON format for classes and records. .. method:: proc readField(name: string, type fieldType): fieldType throws Deserialize a field named ``name`` of type ``fieldType``. .. note:: The position of the underlying ``fileReader`` is undefined after a call to ``readField`` in order to support out-of-order reading. :returns: A deserialized value of type ``fieldType``. .. method:: proc readField(name: string, ref field) throws Deserialize a field named ``name`` in-place. .. note:: The position of the underlying ``fileReader`` is undefined after a call to ``readField`` in order to support out-of-order reading. .. method:: proc ref startClass(reader, name: string) Start deserializing a nested class inside the current class. See ``jsonSerializer.AggregateSerializer.startClass`` for details on inheritance on the JSON format. :returns: A new AggregateDeserializer .. method:: proc endClass() throws End deserialization of the current class by reading the character ``}``. .. method:: proc endRecord() throws End deserialization of the current record by reading the character ``}``. .. method:: proc startTuple(reader: jsonReader) throws Start deserializing a tuple by reading the character ``[``. :arg reader: The ``fileReader`` to use when deserializing :returns: A new :type:`ListDeserializer` .. method:: proc startList(reader: jsonReader) throws Start deserializing a list by reading the character ``[``. :arg reader: The ``fileReader`` to use when deserializing :returns: A new :type:`ListDeserializer` .. record:: ListDeserializer Returned by ``startTuple`` or ``startList`` to provide the API for deserializing tuples or lists. See ``jsonSerializer.ListSerializer`` for details of the JSON format for tuples and lists. .. method:: proc ref readElement(type eltType): eltType throws Deserialize and return an element. :returns: A deserialized value of type ``eltType``. .. method:: proc ref readElement(ref element) throws Deserialize ``element`` in-place. .. method:: proc endList() throws End deserialization of the current list by reading the character ``]``. .. method:: proc endTuple() throws End deserialization of the current tuple by reading the character ``]``. .. method:: proc hasMore(): bool throws :returns: Returns ``true`` if there are more elements to read. .. method:: proc startArray(reader: jsonReader) throws Start deserializing an array. :arg reader: The ``fileReader`` to use when deserializing :returns: A new :type:`ArrayDeserializer` .. record:: ArrayDeserializer Returned by ``startArray`` to provide the API for deserializing arrays. See ``jsonSerializer.ArraySerializer`` for details of the JSON format for arrays. .. method:: proc ref startDim() throws Inform the ``ArrayDeserializer`` to start deserializing a new dimension. .. method:: proc ref endDim() throws End deserialization of the current dimension. .. method:: proc ref readElement(type eltType): eltType throws Deserialize and return an element of the array. :returns: A deserialized value of type ``eltType``. .. method:: proc ref readElement(ref element) throws Deserialize ``element`` in-place as an element of the array. .. method:: proc endArray() throws End deserialization of the current array. .. method:: proc startMap(reader: jsonReader) throws Start deserializing a map by reading the character ``{``. :arg reader: The ``fileReader`` to use when deserializing :returns: A new :type:`MapDeserializer` .. record:: MapDeserializer Returned by ``startMap`` to provide the API for deserializing arrays. See ``jsonSerializer.MapSerializer`` for details of the JSON format for maps. .. method:: proc ref readKey(type keyType): keyType throws Deserialize and return a key of type ``keyType``. .. method:: proc ref readKey(ref key: ?t) throws Deserialize ``key`` in-place as a key of the map. .. method:: proc readValue(type valType): valType throws Deserialize and return a value of type ``valType``. .. method:: proc readValue(ref value) throws Deserialize ``value`` in-place as a value of the map. .. method:: proc endMap() throws End deserialization of the current map by reading the character ``}``. .. method:: proc hasMore(): bool throws :returns: Returns ``true`` if there are more elements to read. .. warning:: Behavior of 'hasMore' is undefined when called between ``readKey`` and ``readValue``.