Next.js: getServerSideProps Fails to Serialize Date Object

Created on 22 May 2020  路  3Comments  路  Source: vercel/next.js

Bug report

Describe the bug

When passing a date over the getServerSideProps boundary, it fails to serialize the Date object. Dates are serializable, so they should be allowed through.

To Reproduce

Attempt to pass a date time through the API, like so

page/index.tsx

const Component = () => {
    return <div>Hello</div>
}

export const getServerSideProps = async (ctx) => {
    const d = new Date();
    return { props: { d } }
}

export default Component

Expected behavior

Serializing occurs just fine

Screenshots

See Stack Trace

System information

  • OS: [e.g. macOS, Windows]
  • Browser (if applies) [e.g. chrome, safari]
  • Version of Next.js: [e.g. 6.0.2]
  • Version of Node.js: [e.g. 10.10.0]

Additional context

While crude, to not have to write complex logic to determine serializability, you could replace the offending method with

const canSerialize = (obj) => {
    try {
        JSON.stringify(obj);
        return false;
    } catch (e) {
        return false;
    }
}

Stack Trade:

SerializableError: Error serializing `.user.lastLogin` returned from `getServerSideProps` in "/dashboard".
Reason: `object` ("[object Date]") cannot be serialized as JSON. Please only return JSON serializable data types.
    at isSerializable (/Users/jake/programming/Railway/frontend/node_modules/next/dist/lib/is-serializable-props.js:9:7)
    at /Users/jake/programming/Railway/frontend/node_modules/next/dist/lib/is-serializable-props.js:7:497
    at Array.every (<anonymous>)
    at isSerializable (/Users/jake/programming/Railway/frontend/node_modules/next/dist/lib/is-serializable-props.js:7:304)
    at /Users/jake/programming/Railway/frontend/node_modules/next/dist/lib/is-serializable-props.js:7:497
    at Array.every (<anonymous>)
    at isSerializable (/Users/jake/programming/Railway/frontend/node_modules/next/dist/lib/is-serializable-props.js:7:304)
    at Object.isSerializableProps (/Users/jake/programming/Railway/frontend/node_modules/next/dist/lib/is-serializable-props.js:9:219)
    at Object.renderToHTML (/Users/jake/programming/Railway/frontend/node_modules/next/dist/next-server/server/render.js:356:42)
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
    at async DevServer.renderToHTMLWithComponents (/Users/jake/programming/Railway/frontend/node_modules/next/dist/next-server/server/next-server.js:660:26)
    at async DevServer.renderToHTML (/Users/jake/programming/Railway/frontend/node_modules/next/dist/next-server/server/next-server.js:807:28)
    at async DevServer.renderToHTML (/Users/jake/programming/Railway/frontend/node_modules/next/dist/server/next-dev-server.js:22:539)
    at async DevServer.render (/Users/jake/programming/Railway/frontend/node_modules/next/dist/next-server/server/next-server.js:552:22)
    at async Object.fn (/Users/jake/programming/Railway/frontend/node_modules/next/dist/next-server/server/next-server.js:402:17)

Most helpful comment

You have to cast to String first.

function replacer(key, value) {
  if (typeof value === 'Date') {
    return value.toString();
  }
  return value;
}

result =  JSON.stringify(obj, replacer)

All 3 comments

You have to cast to String first.

function replacer(key, value) {
  if (typeof value === 'Date') {
    return value.toString();
  }
  return value;
}

result =  JSON.stringify(obj, replacer)

This check is necessary as we do not serialize props on the server for performance reasons. So, this check only runs in development and has you make things serializable with scalar types, meaning they'll match exact on the client.

I'm having this issue when fetching data from Contentful on posts that have links to each other.

Re: https://github.com/vercel/next.js/blob/86160a5190c50ea315c7ba91d77dfb51c42bc65f/packages/next/lib/is-serializable-props.ts#L41

Stringifying using safe-json-stringify and reparsing fixes, but I'm hoping there is a more performant solution.

import safeJsonStringify from 'safe-json-stringify';
...

export async function getServerSideProps({ params, preview = false }) {
  const rawData = await getSlugPageProps(params.slug, 'product-page', preview);
  const stringifiedData = safeJsonStringify(rawData);
  const data = JSON.parse(stringifiedData);

  return {
    props: {
      data
    }
  };
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

knipferrc picture knipferrc  路  3Comments

irrigator picture irrigator  路  3Comments

timneutkens picture timneutkens  路  3Comments

rauchg picture rauchg  路  3Comments

olifante picture olifante  路  3Comments