Latest news and developments from Devso, including progress updates on the development of Test Track (https://test-track.com), Docuarmoury (https://docuarmoury.com) and future projects
Chris Board
Aug 17, 2022 • 4 min readPhoto by Safar Safarov / Unsplash
I recently started working on NextJS (second attempt, I tried it once before but didn't like it - I did a post on IndieHackers about my experience). I thought I must have missed something as NextJS is so popular and see so many people saying how good it is, so I decided to give another try - and so far so good. Except for one issue, with NextJS and PrismaJS returning Date objects not being able to be serialized as JSON.
If you aren't aware Prisma is an ORM to perform CRUD operations on various databases. For my project I am using MySQL. I ran into a problem where a table model in Prisma has a DateTime
field and when I return this in the getStaticProps
I receive an error such as below.
Error From NextJS
As you see in the above, there is an issue when I return posts from Prisma due to createdAt not being seralizable.
Currently, my code in getStaticProps is as follows
export const getStaticProps = async () => {
try
{
const posts = await prismaClient.posts.findMany({
include: {
author: true
}
});
return {
props: {
posts: posts
},
revalidate: 60
}
}
catch (err)
{
return {
props: {
err: err.toString()
}
}
}
}
And my model of posts and users (where author is being included) is below:
model users {
userId Int @id @default(autoincrement())
registeredAt DateTime @default(now())
firstName String @db.VarChar(250)
lastName String @db.VarChar(250)
email String @db.VarChar(250)
password String @db.VarChar(250)
isActive String @default("1") @db.Char(1)
posts posts[]
}
model posts {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
title String @db.VarChar(255)
content String @db.MediumText
slug String @db.VarChar(255)
published Boolean @default(false)
author users @relation(fields: [authorId], references: [userId])
authorId Int
}
As you can see, both posts and users have a DateTime field which will cause this error.
I couldn't find a specific way of fixing it properly, the only suggestion was to use Int and put in an epoch time, but then you can use the database auto timestamp when the record is created/updated.
Therefore I created this method to take the Prisma and convert the Date object into a valid date/time string as below:
export function sanitisePrismaObject (data: any) {
if (Array.isArray(data))
{
for (let i = 0; i < data.length; i++)
{
const keys = Object.keys(data[i]);
keys.forEach(key => {
if (data[i][key] instanceof Date)
{
data[i][key] = convertDateObjectToString(data[i][key]);
}
else if (typeof data[i][key] === "object")
{
sanitisePrismaObject(data[i][key]);
}
})
}
}
else
{
const keys = Object.keys(data);
keys.forEach(key => {
if (data[key] instanceof Date)
{
data[key] = convertDateObjectToString(data[key]);
}
else if (typeof data[key] === typeof Object)
{
sanitisePrismaObject(data[key]);
}
});
}
}
My convertDateObjectToString
is as simple as follows and can be changed for your needs
export function convertDateObjectToString(dateTimeString: Date)
{
const year = dateTimeString.getFullYear();
const month = (dateTimeString.getMonth()+1).toString()
.padStart(2, "0");
const day = dateTimeString.getDate().toString()
.padStart(2, "0");
const hours = dateTimeString.getHours().toString()
.padStart(2, "0");
const minutes = dateTimeString.getMinutes().toString()
.padStart(2, "0");
const seconds = dateTimeString.getSeconds().toString()
.padStart(2, "0");
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
It looks a little horrible above, but its just returning a string of each of the date/month/year and hours/minute components of the date and padding them out to be 2 digits in length.
Then in my getStaticProps I just call await sanitisePrismaObject(posts)
and the date is fixed, full example of the getStaticProps
is below
export const getStaticProps = async () => {
try
{
const posts = await prismaClient.posts.findMany({
include: {
author: true
}
});
await sanitisePrismaObject(posts);
return {
props: {
posts: posts
},
revalidate: 60
}
}
catch (err)
{
return {
props: {
err: err.toString()
}
}
}
}
If you have a better fix than this, then let me know in the comments below.
Chris Board
Are you a developer or involved in Quality Assurance Testing or User Acceptance Testing, you might be interested in Test Track
A simple and affordable test planning and management solution.
Developed by Devso