-
Notifications
You must be signed in to change notification settings - Fork 27.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
getServerSideProps cannot be serialized as JSON. Please only return JSON serializable data types #11993
Comments
I'm having the same problem with a custom interface TimeslotInterface {
from: Date;
to: Date;
}
class Timeslot implements TimeslotInterface {
public constructor(public from: Date, public to: Date) {}
public toString(): string {
return this.from.toLocaleTimeString() + ' - ' + this.to.toLocaleTimeString();
}
} Same as above,
Any suggestions? |
Update: while it makes sense that passing an public toJSON(): TimeslotInterface {
return { from: this.from, to: this.to };
}
public static fromJSON(timeslot: TimeslotInterface): Timeslot {
return new Timeslot(new Date(timeslot.from), new Date(timeslot.to));
} Still doesn't work. |
I have the exact same problem with mongoose. I thought it was because of the ObjectId format, but even if I "stringify" the _id property before it gets sent to getServerSideProps() I get the same error. I've also had the idea to use JSON.parse(JSON.stringify(data)) and it works. But it's a silly solution if you ask me... |
Newbie here to NextJS. It seems strange, especially since querying directly from a PostgreSQL db (via Prisma) usually brings up For now, doing what @jeromemeichelbeck recommends by parsing results through a converter: const dateStripped = obj => {
let newObj = {}
Object.keys(obj).forEach(key => {
let value = obj[key]
if (value !== null) {
// If array, loop...
if (Array.isArray(value)) {
value = value.map(item => dateStripped(item))
}
// ...if property is date/time, stringify/parse...
else if (typeof value === 'object' && typeof value.getMonth === 'function') {
value = JSON.parse(JSON.stringify(value))
}
// ...and if a deep object, loop.
else if (typeof value === 'object') {
value = dateStripped(value)
}
}
newObj[key] = value
})
return newObj
} |
Hi Folks. I think this was a red herring. I'm using the mysql2 library and I did not realize that it is doing some magic conversions behind the scenes to convert dates and some other mysql types to native javascript objects that cannot be serialized without conversion. JSON.stingify() attempts to convert these automatically but it appears Next.JS is using a different serialization method that does not do this conversion. Now that I know more about what's going on I think the approach the Next.JS team is taking is the correct one. It's better to be explicit and give the developer full control than to do magical conversions that may or may not be surprising. Maybe the Next.JS folks could add a "strict" configuration that allows people to opt in to the JSON.stringify() behavior? For those of you still dealing with this you can continue with the I'm closing this issue now as it appears to be working as designed and is not a bug. If someone wants to open a feature request go for it. |
The main reasoning behind this limitation is that with We need to serialize the result of getStaticProps/getServerSideProps because it has to be sent to the browser to do hydration. So we basically went with a strict checking mechanism (only runs in development) in order to prevent this from happening. We can potentially add an option to bypass in the future if there's enough need for it 👍 |
Thank you for the answer. |
@timneutkens @chrisbrantley I came across this recently while working on Next.js support for Amplify JS. This throws an error (relevant code): // pages/index.tsx
export async function getServerSideProps(context) {
const posts = await DataStore.query(Post);
// [Post {...}, Post {...}, ...]
return {
props: {
posts
},
};
} Whereas our // pages/api/posts.tsx
export default async (req: NextApiRequest, res: NextApiResponse) => {
try {
const posts = await DataStore.query(Post);
return res.status(200).json(posts)
} catch (error) {
console.error(error)
return res.status(500).json({ error })
}
} I understand the undesirable impact of using Example: https://codesandbox.io/s/httpsgithubcomzeitnextjsissues11993-sumki?file=/pages/index.js:405-681 |
+1 for an option to bypass. I've disabled all type casting in mysql2 but the objects returned are still of type Given that the primary use case of this feature is to fetch data from some data store and shove it into props, I think this will become quite a pain. Even if it was just a warning and not a hard error it could still be helpful in development. |
In API routes it's expected that you're casting the values to JSON and they're JSON client-side. With getStaticProps/getServerSideProps that is not the case and caused really tricky to debug hydration issues (we've seen these in production Next.js applications). As said I'm not opposed to adding an explicit option to bypass but the default behavior prevents production issues down the line. |
@timneutkens We're on the same page. My proposal is to automatically handle serialization via I'll open a PR for it, since code > words. |
Alright, check out #12156 👀 |
@warcraft14115 I have a PR to fix it, but there were some rogue file-size tests that got it out of date. I'll have to get #12156 passing again and approved (I don't think anyone has looked at it yet). |
Any news on the PR? |
For people using mongoose, I solved it using the Credit to this post in StackOverflow |
if anyone works with axios, the object returned from the api call is in data field, so if all the response of the axios is passed,
|
if anyone here is getting this warning with mongo, you need to supress the _id field bc json does not support hex https://stackoverflow.com/a/52250461/1426788 |
I had the same issue today with objects returned from a This can be resolved without converting the result to json and back again by either using object assign or the spread operator. So instead of Hope this helps! |
Mongo + Next:
|
i am getting data from firestore. faced the same issue because of timestamp in my response. i converted the result from firestore into a string with JSON.stringify() and then again from my props parsed it. working fine |
I stumbled across a similar problem and got it working with by using the |
Same here! const res = JSON.parse(
JSON.stringify(
someObject,
//I had a problem with a bigint value - and heres the solution for it too
(key, value) => (typeof value === "bigint"
? value.toString()
: value)
)
); |
@timneutkens I don't get why this issue is closed. It seems quite a lot of people are still stumbling upon this and there is demand for a better solution. A warning in development mode seems to be sufficient to help users track down hydration errors and it wouldn't require everyone to use hacks to serialize dates and such. |
the _id and _v0 are object types. So according to MongoDB docs, we need to call a toString() method on these properties to get string values |
Hopefully this helps someone struggling like me with the issue.
|
Superjson worked for me |
Yes I also use JSON.parse(JSON.stringify(result) to solve this problem |
This is my solution for Prisma. Maybe this is a better way to show what the problem is. export const getServerSideProps: GetServerSideProps<PostProps> = async () => {
const posts = await prisma.post.findMany();
return {
props: {
posts: posts.map((post: post) => ({
...post,
created_at: post.updated_at.toISOString(),
updated_at: post.updated_at.toISOString(),
deleted_at: post.deleted_at === null ? post.deleted_at : post.deleted_at.toISOString(),
} as unknown as post)),
}
};
}; |
This is solution https://github.com/blitz-js/superjson#using-with-nextjs |
Next.js insists on not having explicit undefineds in page data: vercel/next.js#11993 So we filter them out (just leaving the undefined props out). This change moves the filtering trick to a single one, less visible place.
Next.js insists on not having explicit undefineds in page data: vercel/next.js#11993 So we filter them out (just leaving the undefined props out). This change moves the filtering trick to a single one, less visible place.
Next.js insists on not having explicit undefineds in page data: vercel/next.js#11993 So we filter them out (just leaving the undefined props out). This change moves the filtering trick to a single one, less visible place.
This issue has been automatically locked due to no recent activity. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you. |
For those landing here from Google, good news – this is no longer an issue with the Next.js App Router + React Server Components. From the docs:
async function getData() {
const res = await fetch('https://api.example.com/...');
// The return value is *not* serialized
// You can return Date, Map, Set, etc.
return res.json();
}
export default async function Page() {
const name = await getData();
return '...';
} Source: https://beta.nextjs.org/docs/configuring/typescript#end-to-end-type-safety |
Edit from @leerob: See updated answer: #11993 (comment)
Bug report
Describe the bug
I'm returning a row set from MySQL (using the mysql2 library) in my getServerSideProps. Getting the following error:
SerializableError: Error serializing
.data[0]returned from
getServerSidePropsin "/reports/[report]/[start]/[end]". Reason:
object("[object Object]") cannot be serialized as JSON. Please only return JSON serializable data types.
But calling
JSON.stringify(data)
works just fine.If I do a
JSON.parse(JSON.stringify(data))
it works just fine, but that seems very odd.To Reproduce
mysql2
librarygetServerSideProps
Expected behavior
I expect the data to be serialized without an error since
JSON.stringify()
works just fine.Additional context
Appears others are having this problem: https://stackoverflow.com/questions/61188494/getserversideprops-and-mysql-rowdatapacket
The text was updated successfully, but these errors were encountered: