1

A Program has a one-to-many relationship with Project. I'm looking for an ideal way to include all the projects in a program when I print the JSON response.

extern crate rocket_contrib;
#[macro_use]
extern crate serde;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate serde_json;

use rocket_contrib::Json;
use serde_json::Value;

mod schema {
    table! {
        projects (id) {
            id -> Int4,
            title -> Varchar,
            program_id -> Int4,
            is_archived -> Bool,
        }
    }

    table! {
        programs (id) {
            id -> Int4,
            title -> Varchar,
            is_archived -> Bool,
        }
    }
}

fn main() {
    let program = Program::get(id);
    let json_value = Json(json!({ "result": program }));
}

I looked into implementing custom serializing:

impl Serialize for Program {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
    }
}

But I do not have the db::Conn required to pull the projects in this function.

I'm looking for a response like:

{ 
    "id": 1,
    "is_archived": false,
    "title": "Program 1",
    "projects": [{
      "id": 2,
      "is_archived": false,
       "title": "Project 1"
    }]
}
  • 1
    I think you need to define a struct `ProgramWithProjects` or similar, representing the desired structure, including a field `projects: Vec`. You can fill the struct while you hold the database connection, and then serialize it to JSON. – Sven Marnach Oct 26 '18 at 19:36

1 Answers1

1

The practical answer is don't. Serialization of a value should not involve arbitrary database calls, it should only serialize. Create a struct to hold all the data:

#[derive(Serialize)]
struct ProgramAndProjects {
    #[serde(flatten)]
    program: Program,
    projects: Vec<Project>,
}

Then write a function that populates that struct by doing the required database queries and directly serialize the result.

This has a huge benefit of being wildly more testable, as well.


That being said, it is possible to do, but it's likely not worth it. You can stick a database connection into Program (or create a newtype with the connection and the Program) and then make use of the connection during serialization.

See also:

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366