OpenAPI Serializers
The OpenApiSerializer class is used to convert POJOs to HTTP parts.
The class hierarchy for the builder of this serializer is:
Refer to the builder javadocs for configurable settings.
Later we'll describe how to use HTTP-Part annotations to define OpenAPI schemas for serialization and parsing of HTTP parts.
The following example is a preview showing an HTTP body defined as pipe-delimited list of comma-delimited numbers (e.g.
"1,2,3|4,5,6|7,8,9"
):
@RestPost("/2dLongArray")
public void post2dLongArray(
@Content(
schema=@Schema(
type="array",
collectionFormat="pipes",
items=@Items(
type="array",
collectionFormat="csv",
items=@SubItems(
type="integer",
format="int64",
minimum="0",
maximum="100"
minLength=1,
maxLength=10
)
)
minLength=1,
maxLength=10
)
)
Long[][] body
) {...}
// Alternate shortened format.
@RestPost("/2dLongArray")
public void post2dLongArray(
@Content(
schema=@Schema(
t="array",
cf="pipes",
i=@Items(
t="array",
cf="csv",
i=@SubItems(
t="integer",
f="int64",
min="0",
max="100"
minl=1,
maxl=10
)
)
minl=1,
maxl=10
)
)
Long[][] body
) {...}
Under-the-covers, this gets converted to the following schema object:
HttpPartSchema schema = HttpPartSchema.create()
.items(
HttpPartSchema.create()
.type("array")
.collectionFormat("pipes")
.items(
HttpPartSchema.create()
.type("array")
.collectionFormat("csv")
.items(
HttpPartSchema.create()
.type("integer")
.format("int64")
.minimum(0)
.maximum(100)
.minLength(1)
.maxLength(10)
)
)
)
.build();
Various convenience methods exist for shortening this code.
import static org.apache.juneau.http.HttpPartSchema.*;
HttpPartSchema schema = tArrayPipes(
tArrayCsv(
tInt64().minimum(0).maximum(100).minLength(1).maxLength(10)
)
).build();
The following code shows how the schema above can be used to create our pipe+csv list of numbers:
// Our POJO being serialized.
Long[][] input = ....
// Convert POJO to a string.
try {
String httpPart = OpenApi.of(schema, input);
} catch (SchemaValidationException e) {
// Oops, one of the restrictions were not met.
}
As a general rule, any POJO convertible to the intermediate type for the type/format
of the schema can be serialized
using the OpenAPI serializer.
Here are the rules of POJO types allowed for various type/format combinations:
Type | Format | Valid parameter types |
---|---|---|
string or empty | byte binary binary-spaced | •
|
date date-time | • Calendar (default)
| |
uon | • Any Serializable POJO type | |
empty | • String (default)
| |
boolean | empty | • Boolean (default)
|
integer | int32 | • Integer (default)
|
int64 | • Long (default)
| |
number | float | • Float (default)
|
double | • Double (default)
| |
array | empty | • Arrays or |
uon | • Any Serializable POJO type | |
object | empty | • |
uon | • Any Serializable POJO type |
For arrays, an example of "Any POJO transformable to arrays of the default types" is:
// Sample POJO class convertable to a Long[][].
public class MyPojo {
// toX method used by serializer.
public Long[][] to2dLongs() {...}
}
In the example above, our POJO class can be used to create our pipe-delimited list of comma-delimited numbers:
// Our POJO being serialized.
MyPojo input = ....
// Convert POJO to a string.
try {
String httpPart = OpenApi.of(schema, input);
} catch (SchemaValidationException e) {
// Oops, one of the restrictions were not met.
}
The object
type is not officially part of the OpenAPI standard.
However, Juneau supports serializing Maps
and beans to HTTP parts using UON notation.
The following shows an example of a bean with several properties of various types.
public class MyBean {
private static byte[] FOOB = "foo".getBytes();
public String f1 = "foo";
public byte[] f2 = FOOB;
public byte[] f3 = FOOB;
public byte[] f4 = FOOB;
public Calendar f5 = parseIsoCalendar("2012-12-21T12:34:56Z");
public String f6 = "foo";
public int f7 = 1;
public Long f8 = 2l;
public float f9 = 1.0;
public Double f10 = 1.0;
public Boolean f11 = true;
public Object fExtra = "1";
}
We define the following schema:
import static org.apache.juneau.httppart.HttpPartSchema.*;
HttpPartSchema schema = tObject()
.prop("f1", tString())
.prop("f2", tByte())
.prop("f3", tBinary())
.prop("f4", tBinarySpaced())
.prop("f5", tDateTime())
.prop("f6", tUon())
.prop("f7", tInteger())
.prop("f8", tInt64())
.prop("f9", tNumber())
.prop("f10", tDouble())
.prop("f11", tBoolean())
.ap(tInteger())
.build();
Then we serialize our bean:
String httpPart = OpenApi.of(schema, new MyBean());
The results of this serialization is shown below:
(
f1=foo,
f2=Zm9v,
f3=666F6F,
f4='66 6F 6F',
f5=2012-12-21T12:34:56Z,
f6=foo,
f7=1,
f8=2,
f9=1.0,
f10=1.0,
f11=true,
fExtra=1
)
The following is an example of a bean with various array property types:
public class MyBean {
private static byte[] FOOB = "foo".getBytes();
public String[] f1 = {"a,b",null},
public byte[][] f2 = new byte[][]{FOOB,null},
public byte[][] f3 = new byte[][]{FOOB,null},
public byte[][] f4 = new byte[][]{FOOB,null},
public Calendar[] f5 = new Calendar[]{parseIsoCalendar("2012-12-21T12:34:56Z"),null},
public String[] f6 = {"a","b",null},
public int[] f7 = new int[]{1,2,null},
public Integer[] f8 = new Integer[]{3,4,null},
public float[] f9 = new float[]{1f,2f,null},
public Float[] f10 = new Float[]{3f,4f,null},
public Boolean[] f11 = new Boolean[]{true,false,null},
public Object[] fExtra = new Object[]{1,"2",null};
}
For this bean, we define the following schema:
import static org.apache.juneau.httppart.HttpPartSchema.*;
HttpPartSchema schema = tObject()
.prop("f1", tArray(tString()))
.prop("f2", tArray(tByte()))
.prop("f3", tArray(tBinary()))
.prop("f4", tArray(tBinarySpaced()))
.prop("f5", tArray(tDateTime()))
.prop("f6", tArray(tUon()))
.prop("f7", tArray(tInteger()))
.prop("f8", tArray(tInt64()))
.prop("f9", tArray(tNumber()))
.prop("f10", tArray(tDouble()))
.prop("f11", tArray(tBoolean()))
.ap(tArray(tInteger()))
.build();
Serializing this bean produces the following output:
(
f1=@('a,b',null),
f2=@(Zm9v,null),
f4=@(2012-12-21T12:34:56Z,null),
f5=@(666F6F,null),
f6=@('66 6F 6F',null),
f7=@(a,b,null),
f8=@(1,2,null),
f9=@(3,4,null),
f10=@(1.0,2.0,null),
f11=@(3.0,4.0,null),
f12=@(true,false,null),
fExtra=@(1,2,null)
)
- Array properties can also use CSV/SSV/PIPES for array notation.
- Various notations can be mixed throughout.
- Schemas and POJOs can be defined arbitrarily deep.
- Schemas are optional. They can be skipped or partially defined.
We make our best attempt to convert the input to the matching type.
However, you will get SerializeExceptions
if you attempt an impossible conversion. (e.g. trying to serialize the
string "foo"
as a boolean).