按照ktor
的文档中配置ContentNegotiation
,使用call.receive()
默认只支持application/json
,可以编写自定义的转换器并注册以支持其它的Content-Type
1、编写转换器
class FormUrlEncodedConverter(private val objectMapper: ObjectMapper) : ContentConverter {
override suspend fun serialize(
contentType: ContentType,
charset: Charset,
typeInfo: TypeInfo,
value: Any?
): OutgoingContent {
return OutputStreamContent(
{
val jsonNode = objectMapper.readTree(objectMapper.writeValueAsString(value))
val sb = StringBuilder()
jsonNode.fieldNames().forEach {
sb.append(it).append(jsonNode.get(it)).append("&")
}
objectMapper.writeValue(this, sb.removeSuffix("&").toString())
},
contentType.withCharsetIfNeeded(charset)
)
}
override suspend fun deserialize(charset: Charset, typeInfo: TypeInfo, content: ByteReadChannel): Any? {
try {
return withContext(Dispatchers.IO) {
val reader = content.toInputStream().reader(charset)
val body = reader.readText()
val objectNode = objectMapper.createObjectNode()
body.split("&").forEach {
val arr = it.split("=")
val k = arr[0]
val v = URLDecoder.decode(arr[1], "utf-8")
objectNode.put(k, v)
}
objectMapper.treeToValue(objectNode, objectMapper.constructType(typeInfo.reifiedType))
}
} catch (deserializeFailure: Exception) {
val convertException = JsonConvertException("Illegal json parameter found", deserializeFailure)
when (deserializeFailure) {
is JsonParseException -> throw convertException
is JsonMappingException -> throw convertException
else -> throw deserializeFailure
}
}
}
}
2、注册
install(ContentNegotiation) {
val mapper = ObjectMapper()
mapper.apply {
setDefaultPrettyPrinter(
DefaultPrettyPrinter().apply {
indentArraysWith(DefaultPrettyPrinter.FixedSpaceIndenter.instance)
indentObjectsWith(DefaultIndenter(" ", "\n"))
}
)
}
mapper.registerKotlinModule()
register(ContentType.Application.Json, JacksonConverter(mapper, true))
register(ContentType.Application.FormUrlEncoded, FormUrlEncodedConverter(mapper))
}
Comments NOTHING