EitherNet
EitherNet copied to clipboard
[FEATURE] Support declarative error model binding
Description
At @tonalfitness, we use microservices. Many endpoints across different services use HTTP error codes with meaningful bodies. Turns out the body for a given status code might be totally different for two endpoints. Because of that, the advice provided here doesn't really work for us because the status code itself is not enough to know what type to return.
Here's what would be great:
interface MyApi {
@DecodeErrorBody
@POST("/some/path")
suspend fun someEndpoint(): ApiResult<SuccessModel, GenericErrorModel>
}
sealed class GenericErrorModel {
@HttpError(400, 403)
@JsonClass(generateAdapter = true)
data class SpecificErrorModel1(
@Json(name = "intProperty") val intProperty: Int,
) : GenericErrorModel()
@HttpError(500)
@JsonClass(generateAdapter = true)
data class SpecificErrorModel2(
@Json(name = "stringArrayProperty") val stringProperty: String,
@Json(name = "booleanProperty") val booleanProperty: Boolean,
) : GenericErrorModel()
}
The approach above is possible by extracting the response type inside a custom converter factory and then checking for a potential sealed error type. The actual response status code could be matched against annotated subtypes to figure out what model to deserialize the response to.
Correctness—like forgetting to annotate a subtype, or having more than one subtype bound to the same status code—could be enforced at compile time if either code generation or reflection is used (with a lint rule in this case).
Not sure if this is a too specific use case of if it's something that also makes sense to a broader audience that uses EitherNet.
Requirements (place an x
in each of the [ ]
)
- [x] I've read and understood the Contributing guidelines and have done my best effort to follow them.
- [x] I've read and agree to the Code of Conduct.
- [x] I've searched for any related issues and avoided creating a duplicate issue.