Serialization
The Serialization
module provides type-safe JSON serialization for OpenAPI data types in RxInferServer.jl, with special focus on handling multi-dimensional arrays and probability distributions.
RxInferServer.Serialization.JSONSerialization
— TypeJSONSerialization(; kwargs...)
Type-safe JSON serializer for OpenAPI data types with configurable multi-dimensional array handling.
Keywords
mdarray_repr
: Multi-dimensional array representation format, seeRxInferServer.Serialization.MultiDimensionalArrayRepr
mdarray_data
: Multi-dimensional array data encoding format, seeRxInferServer.Serialization.MultiDimensionalArrayData
Supported Types
The serialization supports standard OpenAPI data types as defined in the OpenAPI specification:
string
(including dates and files)number
integer
boolean
array
(corresponds toAbstractVector
for Julia)object
(corresponds toAbstractDict
for Julia)distribution
(corresponds toDistribution
from RxInfer.jl)
Multi-dimensional Array Serialization
OpenAPI specification does not natively support multi-dimensional arrays. To handle this limitation while ensuring compatibility across different programming languages (which may use different array layouts), RxInferServer implements a customizable serialization strategy through two key preferences:
- Array representation format (
RxInferServer.Serialization.MultiDimensionalArrayRepr
) - Array data encoding (
RxInferServer.Serialization.MultiDimensionalArrayData
)
Example: Matrix Serialization Challenge
Consider serializing a 2x2 matrix:
A = [1 2; 3 4]
2×2 Matrix{Int64}:
1 2
3 4
A naive approach might serialize this as:
encoded_A = Dict(
"shape" => size(A),
"data" => collect(Iterators.flatten(A))
)
Dict{String, Any} with 2 entries:
"shape" => (2, 2)
"data" => [1, 3, 2, 4]
While this works fine in Julia:
decoded_A = reshape(encoded_A["data"], encoded_A["shape"]...)
2×2 Matrix{Int64}:
1 2
3 4
It, however, does not work in python:
>>> import numpy as np
>>> np.reshape([ 1, 3, 2, 4 ], shape = (2, 2))
array([[1, 3],
[2, 4]])
You can see that the data is not correctly reshaped in python. Elements 2
and 3
are swapped. If we would send this data to a python SDK client, the data would be incorrect. This is due to the different array layout conventions (row-major in Python/NumPy vs column-major in Julia). RxInferServer does not assume a particular layout for multi-dimensional arrays, so it leaves it to the user to configure the serialization preferences.
Serialization Preferences
RxInferServer provides two key preferences to control how multi-dimensional arrays are serialized:
Array Data Encoding (
RxInferServer.Serialization.MultiDimensionalArrayData
): Determines how the array data itself is transformed for serialization. For example, theArrayOfArrays
option encodes multi-dimensional arrays as nested arrays with row-major ordering to ensure cross-language compatibility.Array Representation Format (
RxInferServer.Serialization.MultiDimensionalArrayRepr
): Controls the structure of the serialized output, offering several options ranging from a fully-specified dictionary with type, encoding, shape, and data fields to a minimal representation with just the data itself.
These preferences can be configured when creating a RxInferServer.Serialization.JSONSerialization
instance, allowing you to balance between explicit metadata and compact representation based on your specific needs. Read the Request Preferences section for more information on how to set these preferences in the request headers.
Multi-dimensional Array Representation Format
RxInferServer.Serialization.MultiDimensionalArrayRepr
— ModuleSpecifies the JSON representation format for multi-dimensional arrays. Is supposed to be used as a namespace for the MultiDimensionalArrayRepr
enum.
See also: RxInferServer.Serialization.MultiDimensionalArrayData
RxInferServer.Serialization.MultiDimensionalArrayRepr.Dict
— ConstantRepresents the multi-dimensional array as a dictionary with the following keys:
type
set to"mdarray"
encoding
set to to a selected transformation of the array, e.g."array_of_arrays"
shape
set to the size of the arraydata
set to the encoded array itself as defined by the transformation
julia> import RxInferServer.Serialization: MultiDimensionalArrayData, MultiDimensionalArrayRepr, JSONSerialization, to_json
julia> s = JSONSerialization(mdarray_repr = MultiDimensionalArrayRepr.Dict, mdarray_data = MultiDimensionalArrayData.ArrayOfArrays);
julia> to_json(s, [1 2; 3 4])
"{\"type\":\"mdarray\",\"encoding\":\"array_of_arrays\",\"shape\":[2,2],\"data\":[[1,2],[3,4]]}"
RxInferServer.Serialization.MultiDimensionalArrayRepr.DictTypeAndShape
— ConstantSame as RxInferServer.Serialization.MultiDimensionalArrayRepr.Dict
, but excludes the encoding
key, leaving only the type
, shape
and data
keys.
julia> import RxInferServer.Serialization: MultiDimensionalArrayData, MultiDimensionalArrayRepr, JSONSerialization, to_json
julia> s = JSONSerialization(mdarray_repr = MultiDimensionalArrayRepr.DictTypeAndShape, mdarray_data = MultiDimensionalArrayData.ArrayOfArrays);
julia> to_json(s, [1 2; 3 4])
"{\"type\":\"mdarray\",\"shape\":[2,2],\"data\":[[1,2],[3,4]]}"
RxInferServer.Serialization.MultiDimensionalArrayRepr.DictShape
— ConstantSame as RxInferServer.Serialization.MultiDimensionalArrayRepr.Dict
, but excludes the encoding
and type
keys, leaving only the shape
and data
keys.
julia> import RxInferServer.Serialization: MultiDimensionalArrayData, MultiDimensionalArrayRepr, JSONSerialization, to_json
julia> s = JSONSerialization(mdarray_repr = MultiDimensionalArrayRepr.DictShape, mdarray_data = MultiDimensionalArrayData.ArrayOfArrays);
julia> to_json(s, [1 2; 3 4])
"{\"shape\":[2,2],\"data\":[[1,2],[3,4]]}"
RxInferServer.Serialization.MultiDimensionalArrayRepr.Data
— ConstantCompact representation of the multi-dimensional array as returned from the transformation.
julia> import RxInferServer.Serialization: MultiDimensionalArrayData, MultiDimensionalArrayRepr, JSONSerialization, to_json
julia> s = JSONSerialization(mdarray_repr = MultiDimensionalArrayRepr.Data, mdarray_data = MultiDimensionalArrayData.ArrayOfArrays);
julia> to_json(s, [1 2; 3 4])
"[[1,2],[3,4]]"
RxInferServer.Serialization.MultiDimensionalArrayRepr.Unknown
— ConstantUnknown representation format. Used to indicate that the representation format is not known or cannot be parsed from the request.
Multi-dimensional Array Data Encoding
RxInferServer.Serialization.MultiDimensionalArrayData
— ModuleA module that specifies the encoding format for multi-dimensional array data. Is supposed to be used as a namespace for the MultiDimensionalArrayData
enum.
See also: RxInferServer.Serialization.MultiDimensionalArrayRepr
RxInferServer.Serialization.MultiDimensionalArrayData.ArrayOfArrays
— ConstantEncodes the data of multi-dimensional arrays as nested arrays of arrays with row-major ordering.
julia> import RxInferServer.Serialization: MultiDimensionalArrayData, JSONSerialization, to_json
julia> s = JSONSerialization(mdarray_data = MultiDimensionalArrayData.ArrayOfArrays);
julia> to_json(s, [1 2; 3 4])
"{\"type\":\"mdarray\",\"encoding\":\"array_of_arrays\",\"shape\":[2,2],\"data\":[[1,2],[3,4]]}"
julia> to_json(s, [1 3; 2 4])
"{\"type\":\"mdarray\",\"encoding\":\"array_of_arrays\",\"shape\":[2,2],\"data\":[[1,3],[2,4]]}"
Julia uses column-major ordering for multi-dimensional arrays, but this setting explicitly uses row-major ordering.
RxInferServer.Serialization.MultiDimensionalArrayData.ReshapeColumnMajor
— ConstantEncodes the data of multi-dimensional arrays as a flattened array using column-major ordering.
julia> import RxInferServer.Serialization: MultiDimensionalArrayData, JSONSerialization, to_json
julia> s = JSONSerialization(mdarray_data = MultiDimensionalArrayData.ReshapeColumnMajor);
julia> to_json(s, [1 2; 3 4])
"{\"type\":\"mdarray\",\"encoding\":\"reshape_column_major\",\"shape\":[2,2],\"data\":[1,3,2,4]}"
julia> to_json(s, [1 3; 2 4])
"{\"type\":\"mdarray\",\"encoding\":\"reshape_column_major\",\"shape\":[2,2],\"data\":[1,2,3,4]}"
Julia uses column-major ordering for multi-dimensional arrays, so this encoding preserves the natural ordering of elements in memory.
RxInferServer.Serialization.MultiDimensionalArrayData.ReshapeRowMajor
— ConstantEncodes the data of multi-dimensional arrays as a flattened array using row-major ordering.
julia> import RxInferServer.Serialization: MultiDimensionalArrayData, JSONSerialization, to_json
julia> s = JSONSerialization(mdarray_data = MultiDimensionalArrayData.ReshapeRowMajor);
julia> to_json(s, [1 2; 3 4])
"{\"type\":\"mdarray\",\"encoding\":\"reshape_row_major\",\"shape\":[2,2],\"data\":[1,2,3,4]}"
julia> to_json(s, [1 3; 2 4])
"{\"type\":\"mdarray\",\"encoding\":\"reshape_row_major\",\"shape\":[2,2],\"data\":[1,3,2,4]}"
This encoding traverses the array in row-major order, which is different from Julia's native column-major storage, but is compatible with numpy.ndarray
memory layout.
RxInferServer.Serialization.MultiDimensionalArrayData.Diagonal
— ConstantEncodes the data of multi-dimensional arrays as a single array containing only the diagonal elements of the parent array.
julia> import RxInferServer.Serialization: MultiDimensionalArrayData, JSONSerialization, to_json
julia> s = JSONSerialization(mdarray_data = MultiDimensionalArrayData.Diagonal);
julia> to_json(s, [1 2; 3 4])
"{\"type\":\"mdarray\",\"encoding\":\"diagonal\",\"shape\":[2,2],\"data\":[1,4]}"
RxInferServer.Serialization.MultiDimensionalArrayData.None
— ConstantRemoves the multi-dimensional array data from the response entirely.
julia> import RxInferServer.Serialization: MultiDimensionalArrayData, JSONSerialization, to_json
julia> s = JSONSerialization(mdarray_data = MultiDimensionalArrayData.None);
julia> to_json(s, [1 2; 3 4])
"{\"type\":\"mdarray\",\"encoding\":\"none\",\"shape\":[2,2],\"data\":null}"
Use RxInferServer.Serialization.MultiDimensionalArrayRepr.Data
to remove everything.
RxInferServer.Serialization.MultiDimensionalArrayData.Unknown
— ConstantUnknown encoding format. Used to indicate that the encoding format is not known or cannot be parsed from the request.
Distribution Serialization
RxInferServer provides robust serialization support for probability distributions from RxInfer.jl, enabling seamless communication between the server and clients in different programming languages. This functionality is particularly important when working with statistical models that rely on various distribution types. The serialization system offers flexible options to control how distributions are represented in JSON, allowing you to choose between detailed representations that include type information and compact formats that focus solely on the distribution parameters.
Serialization Preferences
RxInferServer provides customizable serialization for probability distributions from RxInfer.jl. Similar to multi-dimensional arrays, the serialization strategy is controlled through two key preferences:
Distribution Data Encoding (
RxInferServer.Serialization.DistributionsData
): Determines how the distribution parameters are encoded. For example, theNamedParams
option encodes parameters with their semantic names (e.g.,μ
for mean), while theParams
option uses a simple array of values.Distribution Representation Format (
RxInferServer.Serialization.DistributionsRepr
): Controls the structure of the serialized output, offering several options ranging from a fully-specified dictionary with type, encoding, tag, and data fields to a minimal representation with just the data itself.
These preferences can be configured when creating a RxInferServer.Serialization.JSONSerialization
instance, allowing you to balance between explicit metadata and compact representation based on your specific needs. Read the Request Preferences section for more information on how to set these preferences in the request headers.
Distribution Representation Format
RxInferServer.Serialization.DistributionsRepr
— ModuleSpecifies the JSON representation format for distributions. Is supposed to be used as a namespace for the DistributionsRepr
enum.
RxInferServer.Serialization.DistributionsRepr.Dict
— ConstantRepresents the distribution as a dictionary with the following keys:
type
set to the distribution type (e.g."Distribution{Univariate, Continuous}"
)encoding
set to the selected encoding format (e.g."named_params"
)tag
set to the specific distribution tag (e.g."NormalMeanVariance"
)data
set to the encoded distribution parameters
julia> import RxInferServer.Serialization: DistributionsData, DistributionsRepr, JSONSerialization, to_json
julia> using RxInfer
julia> s = JSONSerialization(distributions_repr = DistributionsRepr.Dict, distributions_data = DistributionsData.NamedParams);
julia> to_json(s, NormalMeanVariance(1.0, 2.0))
"{\"encoding\":\"named_params\",\"type\":\"Distribution{Univariate, Continuous}\",\"tag\":\"NormalMeanVariance\",\"data\":{\"μ\":1.0,\"v\":2.0}}"
RxInferServer.Serialization.DistributionsRepr.DictTypeAndTag
— ConstantSame as RxInferServer.Serialization.DistributionsRepr.Dict
, but excludes the encoding
key, leaving only the type
, tag
and data
keys.
julia> import RxInferServer.Serialization: DistributionsData, DistributionsRepr, JSONSerialization, to_json
julia> using RxInfer
julia> s = JSONSerialization(distributions_repr = DistributionsRepr.DictTypeAndTag, distributions_data = DistributionsData.NamedParams);
julia> to_json(s, NormalMeanVariance(1.0, 2.0))
"{\"type\":\"Distribution{Univariate, Continuous}\",\"tag\":\"NormalMeanVariance\",\"data\":{\"μ\":1.0,\"v\":2.0}}"
RxInferServer.Serialization.DistributionsRepr.DictTag
— ConstantSame as RxInferServer.Serialization.DistributionsRepr.Dict
, but excludes the encoding
and type
keys, leaving only the tag
and data
keys.
julia> import RxInferServer.Serialization: DistributionsData, DistributionsRepr, JSONSerialization, to_json
julia> using RxInfer
julia> s = JSONSerialization(distributions_repr = DistributionsRepr.DictTag, distributions_data = DistributionsData.NamedParams);
julia> to_json(s, NormalMeanVariance(1.0, 2.0))
"{\"tag\":\"NormalMeanVariance\",\"data\":{\"μ\":1.0,\"v\":2.0}}"
RxInferServer.Serialization.DistributionsRepr.Data
— ConstantCompact representation of the distribution data as returned from the encoding.
julia> import RxInferServer.Serialization: DistributionsData, DistributionsRepr, JSONSerialization, to_json
julia> using RxInfer
julia> s = JSONSerialization(distributions_repr = DistributionsRepr.Data, distributions_data = DistributionsData.NamedParams);
julia> to_json(s, NormalMeanVariance(1.0, 2.0))
"{\"μ\":1.0,\"v\":2.0}"
RxInferServer.Serialization.DistributionsRepr.Unknown
— ConstantUnknown representation format. Used to indicate that the representation format is not known or cannot be parsed from the request.
Distribution Data Encoding
RxInferServer.Serialization.DistributionsData
— ModuleA module that specifies the encoding format for distribution data. Is supposed to be used as a namespace for the DistributionsData
enum.
RxInferServer.Serialization.DistributionsData.NamedParams
— ConstantEncodes the data of distributions as a dictionary with named parameters.
julia> import RxInferServer.Serialization: DistributionsData, JSONSerialization, to_json
julia> using RxInfer
julia> s = JSONSerialization(distributions_data = DistributionsData.NamedParams);
julia> to_json(s, NormalMeanVariance(1.0, 2.0))
"{\"encoding\":\"named_params\",\"type\":\"Distribution{Univariate, Continuous}\",\"tag\":\"NormalMeanVariance\",\"data\":{\"μ\":1.0,\"v\":2.0}}"
This encoding preserves the semantic meaning of each parameter by using its name as a key in the dictionary.
RxInferServer.Serialization.DistributionsData.Params
— ConstantEncodes the data of distributions as an array of parameters in their natural order.
julia> import RxInferServer.Serialization: DistributionsData, JSONSerialization, to_json
julia> using RxInfer
julia> s = JSONSerialization(distributions_data = DistributionsData.Params);
julia> to_json(s, NormalMeanVariance(1.0, 2.0))
"{\"encoding\":\"params\",\"type\":\"Distribution{Univariate, Continuous}\",\"tag\":\"NormalMeanVariance\",\"data\":[1.0,2.0]}"
This encoding is more compact but requires knowledge of the parameter order for each distribution type.
RxInferServer.Serialization.DistributionsData.MeanCov
— ConstantAlways encodes distributions with mean and covariance parameters, converting from other parameterizations as needed.
julia> import RxInferServer.Serialization: DistributionsData, JSONSerialization, to_json
julia> using RxInfer
julia> s = JSONSerialization(distributions_data = DistributionsData.MeanCov);
julia> to_json(s, NormalMeanVariance(1.0, 2.0))
"{\"encoding\":\"mean_cov\",\"type\":\"Distribution{Univariate, Continuous}\",\"tag\":\"NormalMeanVariance\",\"data\":{\"mean\":1.0,\"cov\":2.0}}"
julia> to_json(s, NormalMeanPrecision(1.0, 0.5))
"{\"encoding\":\"mean_cov\",\"type\":\"Distribution{Univariate, Continuous}\",\"tag\":\"NormalMeanPrecision\",\"data\":{\"mean\":1.0,\"cov\":2.0}}"
This encoding ensures consistent parameterization across different distribution types, making it easier for clients to work with the data.
RxInferServer.Serialization.DistributionsData.None
— ConstantRemoves the distribution data from the response entirely.
julia> import RxInferServer.Serialization: DistributionsData, JSONSerialization, to_json
julia> using RxInfer
julia> s = JSONSerialization(distributions_data = DistributionsData.None);
julia> to_json(s, NormalMeanVariance(1.0, 2.0))
"{\"encoding\":\"none\",\"type\":\"Distribution{Univariate, Continuous}\",\"tag\":\"NormalMeanVariance\",\"data\":null}"
Use RxInferServer.Serialization.DistributionsRepr.Data
to remove everything.
RxInferServer.Serialization.DistributionsData.Unknown
— ConstantUnknown encoding format. Used to indicate that the encoding format is not known or cannot be parsed from the request.
API Reference
RxInferServer.Serialization.to_json
— Functionto_json([io::IO], [serialization::JSONSerialization], value)
Serialize value
to JSON using the specified serialization strategy.
Returns a string if io
is not provided.
RxInferServer.Serialization.from_json
— Functionfrom_json(string)
Parse a JSON string into Julia data structures.
julia> import RxInferServer.Serialization: JSONSerialization, MultiDimensionalArrayRepr, MultiDimensionalArrayData, to_json, from_json
julia> s = JSONSerialization(mdarray_repr = MultiDimensionalArrayRepr.Dict, mdarray_data = MultiDimensionalArrayData.ArrayOfArrays);
julia> from_json(to_json(s, [1 2; 3 4]))
Dict{String, Any} with 4 entries:
"shape" => Any[2, 2]
"encoding" => "array_of_arrays"
"data" => Any[Any[1, 2], Any[3, 4]]
"type" => "mdarray"
Note: No post-processing is performed on the deserialized value.
RxInferServer.Serialization.UnsupportedPreferenceError
— TypeUnsupportedPreferenceError(option, options)
Error thrown when an unknown options
value is used for a given set of options
.