Json manipulation with poem-openapi crate

Hi,

I am testing poem crate to create a API.
I just want to have a post request with a json as parameter that resend this json (just to manipulate the data structure).
This json can be formatted like this for example :

{
  "name": "Tom",
  "datas": [
    {
      "intrument": "Piano",
    },
    {
      "sport": "Danse",
      "date" : "2024-01-01",
    },
etc...
  ] 
}

As you can see, datas can contains data of different type. I was thinking to use Enum for that.
But, it is not possible to use Enum with json value the same way we use the struct.

I am looking Serialize, Deserialize. But I am very confused...

This is my only two files to test this crate :

Cargo.toml

name = "TestPoem"
version = "0.1.0"
edition = "2021"

[dependencies]
poem = "3"
poem-openapi = { version = "5", features = ["swagger-ui"] }
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }

and main.rs

use poem::{listener::TcpListener, Route, Server};
use poem_openapi::{OpenApi, payload::Json, Object, ApiResponse, OpenApiService};

#[tokio::main]
async fn main() {
    let endpoints: TestAPI = TestAPI;
    let api_service = OpenApiService::new(endpoints, "Test", "1.0").server("http://localhost:8080");
    let ui = api_service.swagger_ui();
    let app = Route::new().nest("/", api_service).nest("/docs", ui);

    Server::new(TcpListener::bind("127.0.0.1:8080"))
        .run(app)
        .await;
}

pub struct TestAPI;

#[OpenApi]
impl TestAPI {
    #[oai(path = "/test", method = "post")]
    async fn add_test(&self, test:Json<Test>) -> TestResponse {
        TestResponse::Ok(test)

    }
}

/// Possible response of API.
#[derive(ApiResponse)]
enum TestResponse {
    #[oai(status = 200)]
    Ok(Json<Test>),
    #[oai(status = 400)]
    NotFound,
}

#[derive(Object)]
struct Instrument {
    instrument: String,
}

#[derive(Object)]
struct Sport {
    sport: String,
    date: String,
}

//enum Data {
//    SPORT(Sport),
//    INSTRUMENT(Instrument),
//}
#[derive(Object)]
struct Test {
    name: String,
//    datas: Vec<Data>,
}

After command :

cargo run

We can use the following url to test value that we send to the api.

http://localhost:8080/docs

How can we model this kind of json without enum or in another way ?
Serialize, Deserialize must be used ?
Is it possible to just get a string and transform it after in json format ?

I think you model your data using a Union.

1 Like

Thank you very much.