[id='rest_data_formats']
= Data Formats and the REST API
{brandname} caches store data in formats that you can define with a
https://en.wikipedia.org/wiki/Media_type[MediaType].

See the link:{encoding_docs}[Cache Encoding and Marshalling] for more information about MediaTypes and encoding data with {brandname}.

The following example configures the storage format for entries:

[source,xml,options="nowrap",subs=attributes+]
----
include::xml/encoding_keys_values.xml[]
----

If you do not configure a MediaType, {brandname} defaults to
`application/octet-stream` for both keys and values. However, if the cache is
indexed, {brandname} defaults to `application/x-protostream`.

[id='rest_server_data_format_support']
== Supported Formats
You can write and read data in different formats and {brandname} can convert
between those formats when required.

The following "standard" formats are interchangeable:

* `application/x-java-object`
* `application/octet-stream`
* `application/x-www-form-urlencoded`
* `text/plain`

You can also convert the preceding data formats into the following formats:

* `application/xml`
* `application/json`
* `application/x-jboss-marshalling`
* `application/x-protostream`
* `application/x-java-serialized`

{brandname} also lets you convert between `application/x-protostream` and `application/json`.

All calls to the REST API can provide headers describing the content written or
the required format of the content when reading. {brandname} supports the
standard HTTP/1.1 headers "Content-Type" and "Accept" that are applied for
values, plus the "Key-Content-Type" with similar effect for keys.

[id='rest_accept']
== Accept Headers
The {brandname} REST endpoint is compliant with the link:https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html[RFC-2616] Accept
header and negotiates the correct MediaType based on the conversions supported.

For example, send the following header when reading data:

[source,options=nowrap]
----
Accept: text/plain;q=0.7, application/json;q=0.8, */*;q=0.6
----

The preceding header causes {brandname} to first return content in JSON format
(higher priority 0.8). If it is not possible to convert the storage format
to JSON, {brandname} attempts the next format of `text/plain` (second highest
priority 0.7). Finally, {brandname} falls back to _*/*_, which picks a suitable
format based on the cache configuration.

[id='rest_encoded_names']
== Names with Special Characters
The creation of any REST resource requires a name that is part of the URL,
and in case this name contains any special characters as defined in
link:https://tools.ietf.org/html/rfc3986#section-2.2[Section 2.2 of the RFC 3986 spec], it is necessary to encode it with the link:https://en.wikipedia.org/wiki/Percent-encoding[Percent encoding] mechanism.

[id='rest_key_content_type']
== Key-Content-Type Headers

Most REST API calls have the Key included in the URL. {brandname} assumes the
Key is a _java.lang.String_ when handling those calls, but you can use a
specific header _Key-Content-Type_ for keys in different formats.

.Key-Content-Type Header Examples

* Specifying a byte[] Key as a Base64 string:

API call:

   `PUT /my-cache/AQIDBDM=`

Headers:

`Key-Content-Type: application/octet-stream`

* Specifying a byte[] Key as a hexadecimal string:

API call:

`GET /my-cache/0x01CA03042F`

Headers:

[source,options=nowrap]
----
Key-Content-Type: application/octet-stream; encoding=hex
----

* Specifying a double Key:

API call:

`POST /my-cache/3.141456`

Headers:

[source,options=nowrap]
----
Key-Content-Type: application/x-java-object;type=java.lang.Double
----

The _type_ parameter for `application/x-java-object` is restricted to:

* Primitive wrapper types
* java.lang.String
* Bytes, making `application/x-java-object;type=Bytes` equivalent to `application/octet-stream;encoding=hex`.

[id='rest_json_proto_conversion']
== JSON/Protostream Conversion
When caches are indexed, or specifically configured to store _application/x-protostream`, you can send and receive JSON documents that are automatically converted to and from Protobuf.

You must register a Protobuf schema for the conversion to work.

To register protobuf schemas via REST, invoke a POST or PUT in the `____protobuf_metadata_` cache as in the following example:

[source,bash]
----
curl -u user:password -X POST --data-binary @./schema.proto http://127.0.0.1:11222/rest/v2/caches/___protobuf_metadata/schema.proto
----

When writing JSON documents, a special field *__type_* must be present in the document to identity the Protobuf _Message_  that corresponds to the document.

Person.proto
[source,protobuf,options="nowrap",subs=attributes+,role="primary"]
----
message Person  {
  required string name = 1;
  required int32 age = 2;
}
----

Person.json
[source,json,options="nowrap",subs=attributes+,role="secondary"]
----
{
   "_type": "Person",
   "name": "user1",
   "age": 32
}
----
