Andrew O'Hara
12/16/2021, 8:49 PMmap
on a BiDiLensSpec
to convert between a DTO and a domain model, but I don't if or how I can use that to help here. I want the lens to be backed by an enum so that the openapi spec shows the options; simply validating a string isn't good enough.
enum class MyEnumDto(val value: String) {
A("aaaa"),
B("bbbb"),
C("cccc")
}
val lens: BiDiLens<HttpMessage, MyEnumDto> = Header
.mapWithNewMeta(StringBiDiMappings.enum<MyEnumDto>(), ParamMeta.EnumParam(MyEnumDto::class))
.defaulted("my-enum", MyEnumDto.A)
@Test
fun `parse enum lens`() {
val request = Request(Method.GET, "/").header("my-enum", "bbbb")
lens(request) shouldBe MyEnumDto.B
/*
header 'my-enum' must be string
Caused by: java.lang.IllegalArgumentException: No enum constant com.cacmloud.config.camcapi.api.legacy.LegacyLensesTest.MyEnumDto.bbbb
at java.base/java.lang.Enum.valueOf(Enum.java:273)
at com.cacmloud.config.camcapi.api.legacy.LegacyLensesTest$MyEnumDto.valueOf(LegacyLensesTest.kt)
at com.cacmloud.config.camcapi.api.legacy.LegacyLensesTest$special$$inlined$enum$1.invoke(BiDiMapping.kt:87)
at com.cacmloud.config.camcapi.api.legacy.LegacyLensesTest$special$$inlined$enum$1.invoke(BiDiMapping.kt:87)
at org.http4k.lens.BiDiMapping.asOut(BiDiMapping.kt:47)
at org.http4k.lens.LensSpecKt$mapWithNewMeta$1.invoke(lensSpec.kt:249)
at org.http4k.lens.LensGet$map$1.invoke(lensSpec.kt:270)
at org.http4k.lens.LensGet$map$1.invoke(lensSpec.kt:19)
at org.http4k.lens.LensGet$invoke$1.invoke(lensSpec.kt:17)
at org.http4k.lens.LensGet$invoke$1.invoke(lensSpec.kt:17)
at org.http4k.lens.BiDiLensSpec$defaulted$2.invoke(lensSpec.kt:165)
at org.http4k.lens.Lens.invoke(lens.kt:15)
... 109 more
*/
}
@Test
fun `write enum lens`() {
val request = Request(Method.GET, "/")
.with(lens of MyEnumDto.C)
request.shouldHaveHeader("my-enum", "cccc")
/*
Header "my-enum": expected:<"cccc"> but was:<"C">
Expected :"cccc"
Actual :"C"
*/
}
s4nchez
12/16/2021, 9:00 PMimport org.http4k.core.Method
import org.http4k.core.Request
import org.http4k.lens.Header
enum class MyEnumDto(val value: String) {
A("aaaa"),
B("bbbb"),
C("cccc");
companion object {
fun fromValue(v: String) =
values().find { it.value == v } ?: error("Invalid value: $v")
}
}
val lens = Header.map(MyEnumDto.Companion::fromValue, MyEnumDto::value)
.required("my-enum")
val request = Request(Method.GET, "/").header("my-enum", "bbbb")
println(lens(request)) //B
Andrew O'Hara
12/16/2021, 9:15 PMHeader.enum()
doesn't seem to actually work, unlike for Query
or Path
.Andrew O'Hara
12/16/2021, 10:35 PMAccept
header options to replicate a legacy API, but I can just get that to slot in perfectly by copying and adapting the ConfigurableJackson.autobody
, and then adding the different returning
lenses to my contract meta.