r/webdev•
jake_robins

Best Practices for generating nested JSON responses with SQL and a data API

Hey all! I wanted to kick off a bit of a discussion on creating nested JSON responses for an API.

I'd like to produce a nested response to an API request. Let's imagine something like this from `/api/books/:id`

{
"id": 1,
"title": "How to make a pie",
"author": {
"id": 2,
"name": "Jim Jimson"
}
}

My main question is, what's the best way to produce this data from our relational database?

Option 1 - Query Level

We could build a single SQL query that makes this, and the API end point could just pass along the response.

SELECT
  books.id,
  books.title,
  (SELECT row_to_json(a) FROM ( 
    SELECT 
        authors.id,
        authors.name
      FROM authors
      WHERE authors.id = books.id
  ) a ) as author
  FROM books
  WHERE books.id = $1

(aside - is this the best way to nest through SQL?)

const book = await client.query(QUERY, [ id ] )
res.json(book)

Pros:

  • Let's the database handle the data and does it in a single query
  • Endpoint performance is fast

Cons:

  • The shape of a response is kinda sorta business logic so maybe it doesn't belong at the database level?
  • Typing is thrown out the window using the JSON function
  • Depending on the nesting complexity, performance of query could suffer and hog a connection

Option 2 - API Level

We could keep the queries separate and simple, and assemble them in the API

SELECT 
  id,
  title,
  author_id
FROM books WHERE id = $1

SELECT
  id,
  name
FROM authors WHERE id = $1

const book = await client.query(BOOKQUERY, [ id ] )
const author = await client.query(AUTHORQUERY, [ book.author_id ])
delete book.author_id
res.json({...book, author })

Pros:

  • Easy queries to maintain
  • Individual queries are fast
  • Better type safety

Cons:

  • Endpoint performance and maintainability suffer by some amount
  • May require more management of DB connections/clients, using transactions or otherwise, and async management (Promise.all, etc)

Option 3: Something else?

Any better ideas?

Posted Oct 3, 2024, 5:07 PM UTC

1551
Loading comments…