Skip to main content

OpenAPI Serializers

The OpenApiSerializer class is used to convert POJOs to HTTP parts.

The class hierarchy for the builder of this serializer is:

Context.BuilderBeanContextable.BuilderBeanTraverseContext.BuilderSerializer.BuilderWriterSerializer.BuilderUonSerializer.BuilderOpenApiSerializer.Builder

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:

TypeFormatValid parameter types
string or emptybyte
binary
binary-spaced

byte[] (default)
InputStream
Reader - Read into String and then converted using String.getBytes()
Object - Converted to String and then converted using String.getBytes()
• Any POJO transformable to a byte[] via:

  • public byte[] toBytes() {...}
  • public byte[] toFoo() {...} (any method starting with "to")
  • Any POJO transformable via an ObjectSwap
date
date-time

Calendar (default)
Date
• Any POJO transformable to a Calendar via:

  • public Calendar toCalendar() {...}
  • public Calendar toFoo() {...} (any method starting with "to")
  • Any POJO transformable via an ObjectSwap
uon• Any Serializable POJO type
empty

String (default)
• Any POJO transformable to a String via:

  • public String toString() {...}
  • Any POJO transformable via an ObjectSwap
booleanempty

Boolean (default)
• boolean
String - Converted to a Boolean
• Any POJO transformable to a Boolean via:

  • public Boolean toBoolean() {...}
  • public Boolean toFoo() {...} (any method starting with "to")
  • Any POJO transformable via an ObjectSwap
integerint32

Integer (default)
• int
String - Converted to an Integer
• Any POJO transformable to an Integer via:

  • public Integer toInteger() {...}
  • public Integer toFoo() {...} (any method starting with "to")
  • Any POJO transformable via an ObjectSwap
int64

Long (default)
• long
String - Converted to a Long
• Any POJO transformable to a Long via:

  • public Long toLong() {...}
  • public Long toFoo() {...} (any method starting with "to")
  • Any POJO transformable via an ObjectSwap
numberfloat

Float (default)
• float
String - Converted to a Float
• Any POJO transformable to a Float via:

  • public Float toFloat() {...}
  • public Float toFoo() {...} (any method starting with "to")
  • Any POJO transformable via an ObjectSwap
double

Double (default)
• double
String - Converted to a Double
• Any POJO transformable to a Double via:

  • public Double toDouble() {...}
  • public Double toFoo() {...} (any method starting with "to")
  • Any POJO transformable via an ObjectSwap
arrayempty

• Arrays or Collections of any defaults on this list
• Any POJO transformable to arrays of the default types (e.g. Integer[], Boolean[][], etc...)
For example: public Boolean[][] toFoo() {...} (any method starting with "to")
• Any POJO transformable to arrays of the default types via an ObjectSwap

uon• Any Serializable POJO type
objectempty

Map<String,Object> (default)
• Beans with properties of anything on this list
• Any POJO transformable to a map via an ObjectSwap

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)
)
note
  • 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).