Naming convention for models used to (de)serialize request and responses of a REST API

Viewed 768

I need to create in a REST API client some classes to handle the (de)serialization of the data and I'm not use how to name the classes in a meaningful way.

For example, with the following API

GET  /User
POST /Message

I thought of using this structure:

package com.example.model

import kotlinx.serialization.Serializable

object User {
    @Serializable
    data class Response(
        val username: String,
        val fullName: String
    )
}

object Message {
    @Serializable
    data class Request(
        val title: String,
        val message: String
    )
    @Serializable
    data class Response(
        val status: Int
    )
}

But than I don't know how to handle something like this (let's assume that all the request and response have a different structure):

GET    /User
POST   /Message
DELETE /Message

I thought of something like this:

object UserGet { ... }
object MessagePost { ... }
object MessageDelete { ... }

But then I don't know how to deal with this:

GET    /User
GET    /User/{userId}
GET    /User/{userId}/AllMessages
POST   /Message
DELETE /Message

Is there a convention for this use case? How is this usually handled on the server side?

1 Answers

You can keep your class names, just add methods to them that correspond to supported request methods.

package com.example.model

import kotlinx.serialization.Serializable

object User {
    @Serializable
    data class Request( // either you or your routing library should parse incoming urls to deserialize this
        val user_id: String
    )
    @Serializable
    data class Response(
        val username: String,
        val fullName: String
    )
    fun get(req: Request): Response {
    } // GET /User/{user_id}
}

object Message {
    @Serializable
    data class Request(
        val title: String,
        val message: String
    )
    @Serializable
    data class Response(
        val status: Int
    )
    fun create(req: Request): Response {
    } // POST /Message
    fun delete(req: Request): Response {
    } // DELETE /Message
}

GET /user - you need to define behavior for this. I can't see what this would do in your system at the moment.

GET /user/{user_id}/AllMessages - this effectively maps onto a different set of resources. A new class may be in order. I would also recommend a more canonical name like GET /user/{user_id}/messages. That way, you could supply parameters for pagination using a querystring ?limit=1000&offset=900

object UserMessages {
    @Serializable
    data class Request(
        val user_id: String,
        val limit: Int,
        val offset: Int
    )
    @Serializable
    data class Message(
        val message_id: String,
        val text: String
    )
    @Serializable
    data class Response(
        val messages: Array<Message>
    )
    fun get(req: Request): Response {
    } // GET /user/{user_id}/messages
}
Related