Skip to content

Commit f76b88b

Browse files
committed
jackson 3 support (#364)
1 parent 0cdd9f8 commit f76b88b

11 files changed

Lines changed: 161 additions & 6 deletions

File tree

openapi-processor-core/src/main/kotlin/io/openapiprocessor/core/converter/ApiOptions.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ class ApiOptions: MappingSettings {
6565
*/
6666
var beanValidationFormat: String? = null
6767

68+
/**
69+
* Bean Validation format: com.fasterxml.jackson (v2) or tools.jackson (v3)
70+
*/
71+
var jacksonFormat: String = "2"
72+
6873
/**
6974
* enable/disable generation of Javadoc comments based on the `description` OpenAPI property.
7075
*

openapi-processor-core/src/main/kotlin/io/openapiprocessor/core/writer/java/DataTypeWriterBase.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ abstract class DataTypeWriterBase(
4343
protected val apiOptions: ApiOptions,
4444
protected val identifier: Identifier,
4545
protected val generatedWriter: GeneratedWriter,
46-
protected val validationAnnotations: BeanValidationFactory = BeanValidationFactory(apiOptions),
46+
protected val validationAnnotations: BeanValidationFactory,
47+
protected val jacksonAnnotations: JacksonAnnotations,
4748
protected val javadocFactory: JavaDocFactory
4849
): DataTypeWriter {
4950
protected val annotationWriter = AnnotationWriter()
@@ -323,7 +324,7 @@ abstract class DataTypeWriterBase(
323324
val target = getTarget(propData.propDataType)
324325

325326
if (requiresJsonPropertyAnnotation(propData)) {
326-
imports.add("com.fasterxml.jackson.annotation.JsonProperty")
327+
imports.addAll(jacksonAnnotations.getJsonProperty().imports)
327328
}
328329

329330
if (apiOptions.beanValidation) {

openapi-processor-core/src/main/kotlin/io/openapiprocessor/core/writer/java/DataTypeWriterPojo.kt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,16 @@ class DataTypeWriterPojo(
2323
identifier: Identifier,
2424
generatedWriter: GeneratedWriter,
2525
validationAnnotations: BeanValidationFactory = BeanValidationFactory(apiOptions),
26+
jacksonAnnotations: JacksonAnnotations = JacksonAnnotations(apiOptions),
2627
javadocFactory: JavaDocFactory = JavaDocFactory(identifier)
27-
) : DataTypeWriterBase(apiOptions, identifier, generatedWriter, validationAnnotations, javadocFactory) {
28-
28+
) : DataTypeWriterBase(
29+
apiOptions,
30+
identifier,
31+
generatedWriter,
32+
validationAnnotations,
33+
jacksonAnnotations,
34+
javadocFactory
35+
) {
2936
override fun write(target: Writer, dataType: ModelDataType) {
3037
val propsData = collectPropertiesData(dataType)
3138
writeFileHeader(target, dataType, propsData)

openapi-processor-core/src/main/kotlin/io/openapiprocessor/core/writer/java/DataTypeWriterRecord.kt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,16 @@ class DataTypeWriterRecord(
2020
identifier: Identifier,
2121
generatedWriter: GeneratedWriter,
2222
validationAnnotations: BeanValidationFactory = BeanValidationFactory(apiOptions),
23+
jacksonAnnotations: JacksonAnnotations = JacksonAnnotations(apiOptions),
2324
javadocFactory: JavaDocFactory = JavaDocFactory(identifier)
24-
) : DataTypeWriterBase(apiOptions, identifier, generatedWriter, validationAnnotations, javadocFactory) {
25-
25+
) : DataTypeWriterBase(
26+
apiOptions,
27+
identifier,
28+
generatedWriter,
29+
validationAnnotations,
30+
jacksonAnnotations,
31+
javadocFactory
32+
) {
2633
override fun write(target: Writer, dataType: ModelDataType) {
2734
val propsData = collectPropertiesData(dataType)
2835
writeFileHeader(target, dataType, propsData)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/*
2+
* Copyright 2026 https://github.com/openapi-processor/openapi-processor-base
3+
* PDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.openapiprocessor.core.writer.java
7+
8+
enum class JacksonFormat(val pkg: String) {
9+
V2("com.fasterxml.jackson"),
10+
V3("tools.jackson")
11+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright 2026 https://github.com/openapi-processor/openapi-processor-base
3+
* PDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.openapiprocessor.core.writer.java
7+
8+
import io.openapiprocessor.core.converter.ApiOptions
9+
import io.openapiprocessor.core.model.Annotation
10+
11+
class JacksonAnnotations(apiOptions: ApiOptions) {
12+
private val jsonProperty: Annotation
13+
private val jsonCreator: Annotation
14+
private val jsonValue: Annotation
15+
16+
init {
17+
when (getJacksonFormat(apiOptions)) {
18+
JacksonFormat.V2 -> {
19+
jsonProperty = Annotation("com.fasterxml.jackson.annotation.JsonProperty")
20+
jsonCreator = Annotation("com.fasterxml.jackson.annotation.JsonCreator")
21+
jsonValue = Annotation("com.fasterxml.jackson.annotation.JsonValue")
22+
}
23+
JacksonFormat.V3 -> {
24+
jsonProperty = Annotation("tools.jackson.annotation.JsonProperty")
25+
jsonCreator = Annotation("tools.jackson.annotation.JsonCreator")
26+
jsonValue = Annotation("tools.jackson.annotation.JsonValue")
27+
}
28+
}
29+
}
30+
31+
fun getJsonProperty(): Annotation = jsonProperty
32+
fun getJsonCreator(): Annotation = jsonCreator
33+
fun getJsonValue(): Annotation = jsonValue
34+
35+
private fun getJacksonFormat(options: ApiOptions): JacksonFormat {
36+
return when (options.jacksonFormat) {
37+
"2" -> JacksonFormat.V2
38+
"3" -> JacksonFormat.V3
39+
else -> JacksonFormat.V2
40+
}
41+
}
42+
}

openapi-processor-core/src/test/groovy/io/openapiprocessor/core/writer/java/DataTypeWriterSpec.groovy

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class DataTypeWriterSpec extends Specification {
2727
identifier,
2828
generatedWriter,
2929
new BeanValidationFactory(options),
30+
new JacksonAnnotations(options),
3031
new JavaDocFactory(identifier))
3132
def target = new StringWriter ()
3233

openapi-processor-core/src/test/kotlin/io/openapiprocessor/core/writer/java/DataTypeWriterPojoSpec.kt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import io.kotest.matchers.collections.shouldContain
1111
import io.kotest.matchers.equals.shouldBeEqual
1212
import io.kotest.matchers.shouldBe
1313
import io.kotest.matchers.string.shouldContain
14+
import io.mockk.mockk
15+
import io.mockk.verify
1416
import io.openapiprocessor.core.converter.ApiOptions
1517
import io.openapiprocessor.core.converter.JsonPropertyAnnotationMode
1618
import io.openapiprocessor.core.converter.mapping.*
@@ -862,4 +864,24 @@ class DataTypeWriterPojoSpec: StringSpec({
862864
|
863865
""".trimMargin()
864866
}
867+
868+
"looks up jackson annotations" {
869+
val jackson = mockk<JacksonAnnotations>(relaxed = true)
870+
871+
val writer = DataTypeWriterPojo(
872+
options,
873+
identifier,
874+
generatedWriter,
875+
BeanValidationFactory(options),
876+
jacksonAnnotations = jackson)
877+
878+
val dataType = ObjectDataType("Foo", "pkg", linkedMapOf(
879+
Pair("foo", propertyDataTypeString())
880+
), DataTypeConstraints(required = listOf("foo")), false)
881+
882+
writer.write(target, dataType)
883+
884+
verify { jackson.getJsonProperty() }
885+
}
886+
865887
})

openapi-processor-core/src/test/kotlin/io/openapiprocessor/core/writer/java/DataTypeWriterRecordSpec.kt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import io.kotest.matchers.shouldBe
1414
import io.kotest.matchers.string.shouldContain
1515
import io.kotest.matchers.string.shouldNotContain
1616
import io.kotest.matchers.string.shouldStartWith
17+
import io.mockk.mockk
18+
import io.mockk.verify
1719
import io.openapiprocessor.core.converter.ApiOptions
1820
import io.openapiprocessor.core.converter.JsonPropertyAnnotationMode
1921
import io.openapiprocessor.core.converter.mapping.Annotation
@@ -568,5 +570,24 @@ class DataTypeWriterRecordSpec: StringSpec({
568570
val imports = extractImports(target)
569571
imports shouldNotContain "import some.Annotation;"
570572
}
573+
574+
"looks up jackson annotations" {
575+
val jackson = mockk<JacksonAnnotations>(relaxed = true)
576+
577+
val writer = DataTypeWriterRecord(
578+
options,
579+
identifier,
580+
generatedWriter,
581+
BeanValidationFactory(options),
582+
jacksonAnnotations = jackson)
583+
584+
val dataType = ObjectDataType("Foo", "pkg", linkedMapOf(
585+
Pair("foo", propertyDataTypeString())
586+
), DataTypeConstraints(required = listOf("foo")), false)
587+
588+
writer.write(target, dataType)
589+
590+
verify { jackson.getJsonProperty() }
591+
}
571592
})
572593

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright 2026 https://github.com/openapi-processor/openapi-processor-base
3+
* PDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.openapiprocessor.core.writer.java
7+
8+
import io.kotest.core.spec.style.StringSpec
9+
import io.kotest.matchers.collections.shouldContainExactly
10+
import io.openapiprocessor.core.converter.ApiOptions
11+
12+
class JacksonAnnotationsSpec: StringSpec({
13+
14+
"provides jackson 2 annotations" {
15+
val options = ApiOptions()
16+
options.jacksonFormat = "2"
17+
18+
val jackson = JacksonAnnotations(options)
19+
20+
jackson.getJsonProperty().imports shouldContainExactly setOf("com.fasterxml.jackson.annotation.JsonProperty")
21+
jackson.getJsonCreator().imports shouldContainExactly setOf("com.fasterxml.jackson.annotation.JsonCreator")
22+
jackson.getJsonValue().imports shouldContainExactly setOf("com.fasterxml.jackson.annotation.JsonValue")
23+
}
24+
25+
"provides jackson 3 annotations" {
26+
val options = ApiOptions()
27+
options.jacksonFormat = "3"
28+
29+
val jackson = JacksonAnnotations(options)
30+
31+
jackson.getJsonProperty().imports shouldContainExactly setOf("tools.jackson.annotation.JsonProperty")
32+
jackson.getJsonCreator().imports shouldContainExactly setOf("tools.jackson.annotation.JsonCreator")
33+
jackson.getJsonValue().imports shouldContainExactly setOf("tools.jackson.annotation.JsonValue")
34+
}
35+
})

0 commit comments

Comments
 (0)