seeing a very strange behavior in ktor ```route("/...
# ktor
f
seeing a very strange behavior in ktor
Copy code
route("/v1/interactions/taps") {
         post {
               val req = call.receive<AddTapRequest>()
where
Copy code
data class AddTapRequest(val recipientId: Long, val tapType: Int)
if called with
Copy code
POST v1/interactions/taps { "tapType":1 }
ie no recipient (it's a required attribute) rather than failing the request, Ktor just pretends like the caller sent recipientId 0
t
How is your json instance configured
f
thanks for the reply, not sure what you mean by "json instance"? are you referring to if the server has content negotiation and if so what it's configured with?
t
yes
f
Copy code
install(ContentNegotiation) {
         fooJackson()
      }
where
Copy code
fun Configuration.fooJackson(block: ObjectMapper.() -> Unit = {}) {
   jackson {
      standardFooJacksonMapperConfig()
      block()
   }
}

fun ObjectMapper.standardFooJacksonMapperConfig() {
   configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
   configure(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS, false)
   configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE, true)
   configure(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS, false)
   configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, true)
   configure(SerializationFeature.WRITE_ENUMS_USING_INDEX, false)
   registerModule(JavaTimeModule())
}
f
is it us who have disabled that or is that off by default? because it seems odd that ktor out of the box would not blow up on incomplete requests
t
Ktor is "just" delegating to the serialization library you're using
without it Ktor doesn't even know what json is
f
mm I'll have to spin up a fresh jackson ktor server and see what the default is highly doubt it allows requests like this out the box, smells to me like something we've borked but if jackson does allow such requests through out of the box, that's arguably insane
i mean certainly me personally i'd expect incomplete requests to fail by default, not the other way around lol
t
In the linked docs "Feature is disabled by default, so that no exception is thrown for missing creator property values, unless they are explicitly marked as
required
."
But I haven't used Jackson before
f
🤦
t
So you also could annotate the property with JsonProperty and mark as required
f
yeah looks like that's what's needed if it's not enabled by default
thanks everyone, much appreciate the replies
t
I've been using kotlinx serialization and it's been working well without too many footguns
Like your expectation about the fields being required, Jackson is a Java library/codebase so non-nullable types isn't a thing
f
I'm pretty sure if you use DropWizard + Jackson in Java it does fail incomplete requests but that might be because DropWizard have configured it sanely out of the box than, rather than Jackson working as expected out of the box
t
I've never used DropWizard but looking at it briefly it seems like an opinionated framework. Ktor is very much non-opinionated and tries to delegate as much as it can to other libraries. There are tradeoffs between them for sure, but from my experience Ktor tried to minimize its footprint in the project using it
From dropwizard docs: "Jersey maps the request entity to any single, unbound parameter. In this case, because the resource is annotated with
@Consumes(MediaType.APPLICATION_JSON)
, it uses the Dropwizard-provided Jackson support which, in addition to parsing the JSON and mapping it to an instance of
Notification
, also runs that instance through Dropwizard’s Constraining Entities."
So they are using the
@NonNull
annotation that kotlin exposes to java callers
f
by all means I do prefer lighter weight frameworks like Ktor the further away from Spring the better basically lol