Common Kotlin Target Features
The following features are supported by all Kotlin code generation targets.
Generated Types
Scalars
RAML built-in scalar types are mapped according to the following table.
RAML Type | Kotlin Type |
---|---|
any | Any |
boolean | Boolean |
number / integer | Numerics |
string | String |
date-only | java.time.LocalDate |
time-only | java.time.LocalTime |
datetime-only | java.time.LocalDateTime |
datetime | java.time.OffsetDateTime |
file | ByteArray |
nil | Unit |
Numerics
RAML number
and integer
types are mapped to one of Kotlins's numeric types based on the format
facet.
Format | Kotlin Type |
---|---|
int |
Int |
int8 |
Byte |
int16 |
Short |
int32 |
Int |
int64 |
Long |
long |
Long |
float |
Float |
double |
Double |
Objects
For each RAML type that is an object
or where the root of the inheritance tree is an object
a Kotlin class or interface is generated.
Model Classes
When the generation of model implementations is enabled (Implement Model Classes - Type Generation Option) a POJO class is generated for each required type that supports copying, equals/hashcode, toString, etc.
Example Class Generation
RAML Type Definition
%RAML 1.0
title: Test API
types:
Item:
type: object
properties:
name: String
value: integer
Generated Kotlin Class
public class Item(
public val name: String,
public val value: Int,
) {
public fun copy(
name: String? = null,
value: Int?? = null,
) = Test(name ?: this.name, value ?: this.value)
public override fun hashCode(): Int {
var result = 1
result = 31 * result + name.hashCode()
result = 31 * result + value.hashCode()
return result
}
public override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as Test
if (name != other.name) return false
if (value != other.value) return false
return true
}
public override fun toString() = ""${'"'}
|Test(name='${'$'}name',
| value='${'$'}value
""${'"'}.trimMargin()
}
Why not data classes?
The generator currently does not gnerate Kotlin data classes to ensure easy support for generating type hierarchies. Similar features to those of data classes are generated for each class.
Model Interfaces
When the generation of model implementations is disabled (Implement Model Classes - Type Generation Option) interfaces are generated for each required types.
Example Interface Generation
RAML Type Definition
%RAML 1.0
title: Test API
types:
Item:
type: object
properties:
name: String
value: integer
Generated Kotlin Interface
public interface Item {
public val name: String
public val value: Int
}
Simple Objects
RAML types that are "simple" objects (where no properties
facet is defined) are mapped to Kotlin maps (i.e. Map<String, Any>
). They are generated inline and no type aliases are generated.
Example Simple Object Generation
RAML Type Definition
%RAML 1.0
title: Test API
types:
Container:
map: object
Generated Kotlin Class (simplified)
public class Container(
public val map: Map<String, Any>
)
Pattern Objects
RAML types that only contain pattern properties (i.e. property names defined by regular expressions) are mapped to Kotlin maps with the key as a string and the value as the type specified in the pattern (e.g. Map<String: Int>
). They are generated inline and no type aliases are generated.
Example Pattern Object Generation
RAML Type Definition
%RAML 1.0
title: Test API
types:
MapOfInts:
type: object
//: integer
Container:
map: MapOfInts
Generated Kotlin Class (simplified)
public class Container(
public val map: Map<String, Int>
)
Jackson Annotations
The generator defaults to adding Jackson JSON serialization annotations to the generated classes and interfaces. This enables advanced JSON features (e.g. polymorphism, explicit naming, etc.) to be supported without editing the generated types or registering mixins.
Example Jackson Annotations Generation (Explicit Names)
RAML Type Definition
%RAML 1.0
title: Test API
types:
Item:
type: object
properties:
simple-name: string
value: integer
Generated Kotlin Class
public class Item(
@JacksonProperty("simple-name")
public val simpleName: String
public val value: Int
)
Example Jackson Annotations Generation (Polymorphism)
RAML Type Definition
%RAML 1.0
title: Test API
types:
Device:
type: object
discriminator: type
properties:
type: string
name: string
Phone:
type: Device
discriminatorValue: phone
properties:
hasGPS: boolean
Tablet:
type: Device
discriminatorValue: tablet
properties:
isKeyboardAttached: boolean
Generated Kotlin Classes
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.EXISTING_PROPERTY,
property = "type"
)
@JsonSubTypes(value = [
JsonSubTypes.Type(name = "phone", value = Phone::class),
JsonSubTypes.Type(name = "tablet", value = Tablet::class)
])
public abstract class Device(
public val name: String
) {
public abstract val type: String
}
public class Phone(
name: String,
public val hasGPS: Boolean,
) : Device(name) {
val type: String get() = "phone"
}
public class Tablet(
type: String,
public val isKeyboardAttached: Boolean,
) : Device() {
val type: String get() = "tablet"
}
Note
The generation of Jackson annotations can be disabled via the Jackson Annotations - Type Generation Option.
Danger
Disabling Jackson will most likely require a custom (de)serialization implementation to support the full feature set.
Bean Validation Constraints
The generator defaults to adding Bean Validation Constraints to validate instance data as they are serialized/deserialized.
Example Validation Constraints Generation
RAML Type Definition
%RAML 1.0
title: Test API
types:
Item:
type: object
properties:
id:
type: string
pattern: [a-zA-Z0-9]+
value:
type: integer
minimum: 5
maximum: 10
Generated Kotlin Class
public class Item(
@Pattern("[a-zA-Z0-9]+")
public val id: String,
@Min(5) @Max(10)
public val value: Int,
)
Note
The generation of validation constraints can be disabled via the Validation Constraints - Type Generation Option
Arrays
RAML array types are mapped to Kotlin's List
type. They are generated inline and no type aliases are generated.
Example Array Generation
RAML Type Definition
%RAML 1.0
title: Test API
types:
Item:
type: string
Items:
type: array
items: Item
Container:
items: Items
Generated Kotlin Class (simplified)
public class Container(
public val items: List<String>
)
Unions
RAML union types are mapped to the "nearest common ancestor" of all individual types in the union, if one exists, in all other cases the union is mapped to Kotlin's Any
type.
Example Union Generation (Common Aancestor)
RAML Type Definition
%RAML 1.0
title: Test API
types:
Device:
type: object
discriminator: type
properties:
type: string
name: string
Phone:
type: Device
discriminatorValue: phone
properties:
hasGPS: boolean
Tablet:
type: Device
discriminatorValue: tablet
properties:
isKeyboardAttached: boolean
UnionOfAllDevices:
type: (Phone | Tablet)
Container:
type: object
properties:
device: UnionOfAllDevices
- Inline union of types with a common ancestor.
Generated Kotlin Class (simplified)
public class Container(
public val device: Device
)
Generated Problem Types
For each problem defined & referenced using Sunday's problem annotations, a Kotlin Exception
class is generated. Generating exceptions allows servers to throw a specific problem and clients to catch specific problems.
Custom properties can be defined for problem types and they are added as simple Kotlin properties on the generated exception class.
Example Problem Generation
RAML Type Definition
%RAML 1.0
title: Test API
uses:
sunday: https://outfoxx.github.io/sunday-generator/sunday.raml
types:
(sunday.problemTypes):
invalid_id:
status: 400
title: Invalid Id
detail: The id contains one or more invalid characters
custom:
offendingId: string
Generated Problem Exception Class
public class InvalidIdProblem(
@JsonProperty(value = "offending_id")
public val offendingId: String,
instance: URI? = null,
cause: ThrowableProblem? = null
) : AbstractThrowableProblem(TYPE_URI, "Invalid Id", Status.BAD_REQUEST,
"The id contains one or more invalid characters.", instance, cause) {
public override fun getCause(): Exceptional? = super.cause
public companion object {
public const val TYPE: String = "http://example.com/invalid_id"
public val TYPE_URI: URI = URI(TYPE)
}
}
Generator Options
In addition to the options supported by all code generations targets, this target also supports the following options:
- Default Package Name
-
Specifies the default Kotlin package name for model types and service types.
CLI Option Gradle Plugin Properties Type Default -pkg
pkgName
string None - Default Model Package Name
-
Specifies the default Kotlin package name for model types.
CLI Option Gradle Plugin Properties Type Default -model-pkg
modelPkgName
string None Note
If not specified the value specified in
-pkg
is used. - Default Service Package Name
-
Specifies the default Kotlin package name for service types.
CLI Option Gradle Plugin Properties Type Default -service-pkg
servicePkgName
string None Note
If not specified the value specified in
-pkg
is used.
- Type Generation Options
-
Enable/Disable Kotlin type generation options.
Supported Options
- Implement Model Classes
- Enables or Disables implementation of model classes
- Jackson Annotations
- Enables or Disables generation of Jackson annotations
- Validation Constraints
- Enables or Disables generation of bean validation annotations
CLI Option Gradle Plugin Properties Type Default -disable implement-model
disableModelImplementations
boolean enabled -disable jackson-annotations
disableJacksonAnnotations
boolean enabled -disable validation-constraints
disableValidationConstraints
boolean enabled