{8.2.0-updated} OpenAPI Serializers

The {@link oaj.oapi.OpenApiSerializer} class is used to convert POJOs to HTTP parts.

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"):

@RestMethod(method="POST", path="/2dLongArray") public void post2dLongArray( @Body( 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. @RestMethod(method="POST", path="/2dLongArray") public void post2dLongArray( @Body( 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.

HttpPartSchema schema = HttpPartSchema.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 = .... // The serializer to use. HttpPartSerializer serializer = OpenApiSerializer.DEFAULT; // Convert POJO to a string. try { String httpPart = serializer.serialize(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 empty byte
binary
binary-spaced
  • byte[] (default)
  • {@link java.io.InputStream}
  • {@link java.io.Reader} - Read into String and then converted using {@link java.lang.String#getBytes()}.
  • {@link java.lang.Object} - Converted to String and then converted using {@link java.lang.String#getBytes()}.
  • Any POJO transformable to a byte[] via the following methods:
    • public byte[] toBytes() {...}
    • public byte[] toFoo() {...} (any method name starting with "to")
  • Any POJO transformable to a byte[] via a {@link oaj.transform.PojoSwap}.
date
date-time
  • {@link java.util.Calendar} (default)
  • {@link java.util.Date}
  • Any POJO transformable to a {@link java.util.Calendar} via the following methods:
    • public Calendar toCalendar() {...}
    • public Calendar toFoo() {...} (any method name starting with "to")
  • Any POJO transformable to a {@link java.util.Calendar} via a {@link oaj.transform.PojoSwap}.
uon
  • Any {@doc PojoCategories Serializable POJO} type.
empty
  • {@link java.lang.String} (default)
  • Any POJO transformable to a {@link java.lang.String} via the following methods:
    • public String toString() {...}
  • Any POJO transformable to a {@link java.lang.String} via a {@link oaj.transform.PojoSwap}.
boolean empty
  • {@link java.lang.Boolean} (default)
  • boolean
  • {@link java.lang.String} - Converted to a {@link java.lang.Boolean}.
  • Any POJO transformable to a {@link java.lang.Boolean} via the following methods:
    • public Boolean toBoolean() {...}
    • public Boolean toFoo() {...} (any method name starting with "to")
  • Any POJO transformable to a {@link java.lang.Boolean} via a {@link oaj.transform.PojoSwap}.
integer int32
  • {@link java.lang.Integer} (default)
  • int
  • {@link java.lang.String} - Converted to an {@link java.lang.String}.
  • Any POJO transformable to an {@link java.lang.Integer} via the following methods:
    • public Integer toInteger() {...}
    • public Integer toFoo() {...} (any method name starting with "to")
  • Any POJO transformable to an {@link java.lang.Integer} via a {@link oaj.transform.PojoSwap}.
int64
  • {@link java.lang.Long} (default)
  • long
  • {@link java.lang.String} - Converted to a {@link java.lang.Long}.
  • Any POJO transformable to a {@link java.lang.Long} via the following methods:
    • public Long toLong() {...}
    • public Long toFoo() {...} (any method name starting with "to")
  • Any POJO transformable to a {@link java.lang.Long} via a {@link oaj.transform.PojoSwap}.
number float
  • {@link java.lang.Float} (default)
  • float
  • {@link java.lang.String} - Converted to a {@link java.lang.Float}.
  • Any POJO transformable to a {@link java.lang.Float} via the following methods:
    • public Float toFloat() {...}
    • public Float toFoo() {...} (any method name starting with "to")
  • Any POJO transformable to a {@link java.lang.Float} via a {@link oaj.transform.PojoSwap}.
double
  • {@link java.lang.Double} (default)
  • double
  • {@link java.lang.String} - Converted to a {@link java.lang.Double}.
  • Any POJO transformable to a {@link java.lang.Double} via the following methods:
    • public Double toDouble() {...}
    • public Double toFoo() {...} (any method name starting with "to")
  • Any POJO transformable to a {@link java.lang.Double} via a {@link oaj.transform.PojoSwap}.
array empty
  • 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 name starting with "to")
  • Any POJO transformable to arrays of the default types via a {@link oaj.transform.PojoSwap}
uon
  • Any {@doc PojoCategories Serializable POJO} type.
object empty
  • Map<String,Object> (default)
  • Beans with properties of anything on this list.
  • Any POJO transformable to a map via a {@link oaj.transform.PojoSwap}
uon
  • Any {@doc PojoCategories 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 = .... // The serializer to use. HttpPartSerializer serializer = OpenApiSerializer.DEFAULT; // Convert POJO to a string. try { String httpPart = serializer.serialize(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:

HttpPartSerializer serializer = OpenApiSerializer.DEFAULT; String httpPart = serializer.serialize(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) )