Skip to content

Commit e36e8e7

Browse files
committed
added @OpenAPIName to remap parameter names
1 parent 9355457 commit e36e8e7

File tree

10 files changed

+39
-11
lines changed

10 files changed

+39
-11
lines changed

src/main/kotlin/com/papsign/ktor/openapigen/KTypeUtil.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.papsign.ktor.openapigen
22

3+
import com.papsign.ktor.openapigen.annotations.mapping.openAPIName
34
import java.lang.reflect.Field
45
import kotlin.reflect.*
56
import kotlin.reflect.full.createType
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.papsign.ktor.openapigen.annotations.mapping
2+
3+
import java.util.*
4+
import kotlin.reflect.KParameter
5+
import kotlin.reflect.full.findAnnotation
6+
7+
@Target(AnnotationTarget.VALUE_PARAMETER)
8+
annotation class OpenAPIName(val name: String)
9+
10+
private val cache = Collections.synchronizedMap(HashMap<KParameter, String?>())
11+
12+
val KParameter.openAPIName: String?
13+
get() = cache.getOrPut(this) { findAnnotation<OpenAPIName>()?.name ?: name }
14+
15+
fun <T> KParameter.remapOpenAPINames(map: Map<String, T>): Map<String, T> {
16+
val replace = this.openAPIName
17+
val actual = this.name
18+
return if (actual != null && replace != actual) map.mapKeys { (key, _) -> if (key == replace) actual else key } else map
19+
}

src/main/kotlin/com/papsign/ktor/openapigen/content/type/multipart/MultipartFormDataContentProvider.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.papsign.ktor.openapigen.content.type.multipart
22

33
import com.papsign.ktor.openapigen.*
4+
import com.papsign.ktor.openapigen.annotations.mapping.openAPIName
45
import com.papsign.ktor.openapigen.content.type.BodyParser
56
import com.papsign.ktor.openapigen.content.type.ContentTypeProvider
67
import com.papsign.ktor.openapigen.exceptions.assertContent
@@ -87,7 +88,7 @@ object MultipartFormDataContentProvider : BodyParser, OpenAPIGenModuleExtension
8788
}
8889
val ctor = clazz.primaryConstructor!!
8990
return ctor.callBy(ctor.parameters.associateWith {
90-
val raw = objectMap[it.name]
91+
val raw = objectMap[it.openAPIName]
9192
if ((raw == null || (raw !is InputStream && streamTypes.contains(it.type))) && it.type.isMarkedNullable) {
9293
null
9394
} else {
@@ -97,7 +98,7 @@ object MultipartFormDataContentProvider : BodyParser, OpenAPIGenModuleExtension
9798
val cvt = conversionsByType[it.type] ?: error("Unhandled Type ${it.type}")
9899
when (raw) {
99100
null -> {
100-
cvt.default ?: error("No provided value for field ${it.name}")
101+
cvt.default ?: error("No provided value for field ${it.openAPIName}")
101102
}
102103
is String -> {
103104
cvt.parser(raw)

src/main/kotlin/com/papsign/ktor/openapigen/model/DataModel.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.papsign.ktor.openapigen.model
22

3+
import com.papsign.ktor.openapigen.annotations.mapping.openAPIName
34
import kotlin.reflect.KProperty1
45
import kotlin.reflect.full.memberProperties
56

src/main/kotlin/com/papsign/ktor/openapigen/model/security/FlowsModel.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.papsign.ktor.openapigen.model.security
22

3+
import com.papsign.ktor.openapigen.annotations.mapping.openAPIName
34
import com.papsign.ktor.openapigen.model.DataModel
45
import com.papsign.ktor.openapigen.model.Described
56
import java.util.*

src/main/kotlin/com/papsign/ktor/openapigen/parameters/handlers/ModularParameterHander.kt renamed to src/main/kotlin/com/papsign/ktor/openapigen/parameters/handlers/ModularParameterHandler.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.papsign.ktor.openapigen.parameters.handlers
22

33
import com.papsign.ktor.openapigen.OpenAPIGen
4+
import com.papsign.ktor.openapigen.annotations.mapping.remapOpenAPINames
5+
import com.papsign.ktor.openapigen.annotations.mapping.openAPIName
46
import com.papsign.ktor.openapigen.annotations.parameters.HeaderParam
57
import com.papsign.ktor.openapigen.annotations.parameters.PathParam
68
import com.papsign.ktor.openapigen.annotations.parameters.QueryParam
@@ -20,19 +22,19 @@ import kotlin.reflect.KParameter
2022
import kotlin.reflect.full.findAnnotation
2123
import kotlin.reflect.full.withNullability
2224

23-
class ModularParameterHander<T>(val parsers: Map<KParameter, Builder<*>>, val constructor: KFunction<T>) :
25+
class ModularParameterHandler<T>(val parsers: Map<KParameter, Builder<*>>, val constructor: KFunction<T>) :
2426
ParameterHandler<T> {
2527

2628
override fun parse(parameters: Parameters, headers: Headers): T {
27-
return constructor.callBy(parsers.mapValues { it.value.build(it.key.name!!, parameters.toMap() + headers.toMap()) })
29+
return constructor.callBy(parsers.mapValues { it.value.build(it.key.name.toString(), it.key.remapOpenAPINames(parameters.toMap() + headers.toMap())) })
2830
}
2931

3032
override fun getParameters(apiGen: OpenAPIGen, provider: ModuleProvider<*>): List<ParameterModel<*>> {
3133
val schemaBuilder = provider.ofClass<FinalSchemaBuilderProviderModule>().last().provide(apiGen, provider)
3234

3335
fun createParam(param: KParameter, `in`: ParameterLocation, config: (ParameterModel<*>) -> Unit): ParameterModel<*> {
3436
return ParameterModel<Any>(
35-
param.name.toString(),
37+
param.openAPIName.toString(),
3638
`in`,
3739
!param.type.isMarkedNullable
3840
).also {

src/main/kotlin/com/papsign/ktor/openapigen/parameters/parsers/builders/query/deepobject/ObjectDeepBuilder.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.papsign.ktor.openapigen.parameters.parsers.builders.query.deepobject
22

3+
import com.papsign.ktor.openapigen.annotations.mapping.openAPIName
34
import com.papsign.ktor.openapigen.parameters.QueryParamStyle
45
import com.papsign.ktor.openapigen.parameters.parsers.builders.Builder
56
import com.papsign.ktor.openapigen.parameters.parsers.builders.BuilderSelector
@@ -32,7 +33,7 @@ class ObjectDeepBuilder(val type: KType) : DeepBuilder {
3233

3334
override fun build(key: String, parameters: Map<String, List<String>>): Any? {
3435
return try {
35-
constructor.callBy(builderMap.mapValues { it.value.build("$key[${it.key.name}]", parameters) })
36+
constructor.callBy(builderMap.mapValues { it.value.build("$key[${it.key.openAPIName}]", parameters) })
3637
} catch (e: InvocationTargetException) {
3738
null
3839
}

src/main/kotlin/com/papsign/ktor/openapigen/parameters/parsers/converters/object/ObjectConverter.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.papsign.ktor.openapigen.parameters.parsers.converters.`object`
22

3+
import com.papsign.ktor.openapigen.annotations.mapping.openAPIName
34
import com.papsign.ktor.openapigen.parameters.parsers.converters.Converter
45
import com.papsign.ktor.openapigen.parameters.parsers.converters.ConverterSelector
56
import com.papsign.ktor.openapigen.parameters.parsers.converters.primitive.PrimitiveConverterFactory
@@ -30,7 +31,7 @@ class ObjectConverter(type: KType): MappedConverter {
3031
}
3132

3233
override fun convert(map: Map<String, String>): Any? {
33-
return try { constructor.callBy(builderMap.mapValues { (key, value) -> map[key.name]?.let { value.convert(it) } }) } catch (e: InvocationTargetException) { null }
34+
return try { constructor.callBy(builderMap.mapValues { (key, value) -> map[key.openAPIName]?.let { value.convert(it) } }) } catch (e: InvocationTargetException) { null }
3435
}
3536

3637
companion object: ConverterSelector {

src/main/kotlin/com/papsign/ktor/openapigen/parameters/util/Util.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package com.papsign.ktor.openapigen.parameters.util
33
import com.papsign.ktor.openapigen.annotations.parameters.HeaderParam
44
import com.papsign.ktor.openapigen.annotations.parameters.PathParam
55
import com.papsign.ktor.openapigen.annotations.parameters.QueryParam
6-
import com.papsign.ktor.openapigen.parameters.handlers.ModularParameterHander
6+
import com.papsign.ktor.openapigen.parameters.handlers.ModularParameterHandler
77
import com.papsign.ktor.openapigen.parameters.handlers.ParameterHandler
88
import com.papsign.ktor.openapigen.parameters.handlers.UnitParameterHandler
99
import com.papsign.ktor.openapigen.parameters.parsers.builders.Builder
@@ -24,7 +24,7 @@ inline fun <reified T : Any> buildParameterHandler(): ParameterHandler<T> {
2424
param.findAnnotation<QueryParam>()?.let { a -> a.style.factory.buildBuilderForced(type, a.explode) } ?:
2525
error("Parameters must be annotated with @PathParam or @QueryParam")
2626
}
27-
return ModularParameterHander(
27+
return ModularParameterHandler(
2828
parsers,
2929
constructor
3030
)

src/test/kotlin/TestServer.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import com.papsign.ktor.openapigen.OpenAPIGen
1212
import com.papsign.ktor.openapigen.annotations.Path
1313
import com.papsign.ktor.openapigen.annotations.Request
1414
import com.papsign.ktor.openapigen.annotations.Response
15+
import com.papsign.ktor.openapigen.annotations.mapping.OpenAPIName
1516
import com.papsign.ktor.openapigen.annotations.parameters.HeaderParam
1617
import com.papsign.ktor.openapigen.annotations.parameters.PathParam
1718
import com.papsign.ktor.openapigen.annotations.type.`object`.example.ExampleProvider
@@ -154,7 +155,7 @@ object TestServer {
154155
info("Header Param Endpoint", "This is a Header Param Endpoint"),
155156
example = NameGreetingResponse("Hi, openapi!")
156157
) { params ->
157-
respond(NameGreetingResponse("Hi, ${params.`X-Name`}!"))
158+
respond(NameGreetingResponse("Hi, ${params.name}!"))
158159
}
159160
}
160161

@@ -223,7 +224,7 @@ object TestServer {
223224
@Response("A String Response")
224225
data class StringResponse(val str: String)
225226

226-
data class NameParam(@HeaderParam("A simple Header Param") val `X-Name`: String)
227+
data class NameParam(@HeaderParam("A simple Header Param") @OpenAPIName("X-NAME") val name: String)
227228

228229
@Response("A Response for header param example")
229230
data class NameGreetingResponse(val str: String)

0 commit comments

Comments
 (0)