Skip to content
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

[Feature] Override the serializer for json #1706

Open
ShravanSunder opened this issue Nov 16, 2023 · 11 comments
Open

[Feature] Override the serializer for json #1706

ShravanSunder opened this issue Nov 16, 2023 · 11 comments
Labels
enhancement New feature or request.

Comments

@ShravanSunder
Copy link

ShravanSunder commented Nov 16, 2023

What is the feature you are proposing?

It would be great to be able to easily override the serializer in req/res of c.json. I would like to use superjson to make date handling easier.

@ShravanSunder ShravanSunder added the enhancement New feature or request. label Nov 16, 2023
@yusukebe
Copy link
Member

Hi @ShravanSunder

Honestly, I don't want to add more features to c.json(), even though the changes might not be big.

Instead, you can use c.render() and c.setRenderer():

https://hono.dev/api/context#render-setrenderer

@ShravanSunder
Copy link
Author

@yusukebe Just so that i understand well, i would set my custom renderer with setRender and use that? I think that's a good fallback. Would this also work with hono stacks?

@yusukebe
Copy link
Member

@ShravanSunder

Yes. You can write like the following though it will be a little bit verbose.

import { Hono } from 'hono'

const app = new Hono()

declare module 'hono' {
  interface ContextRenderer {
    (data: object): Response
  }
}

app.get('/api/*', async (c, next) => {
  c.setRenderer((data) => {
    return c.body(JSON.stringify(data, null, 4))
  })
  await next()
})

app.get('/api/foo', (c) => {
  return c.render({
    foo: 'bar',
  })
})

@ShravanSunder
Copy link
Author

@yusukebe thanks!

One more question, is this method also possible to use with https://hono.dev/concepts/stacks

@yusukebe
Copy link
Member

Ah, you want to use jsonT()?

@yusukebe
Copy link
Member

There might be someone using superjson for RPC, but I can't recall it now. Hmm.

@ShravanSunder
Copy link
Author

i think most specifically the handling of dates is the best thing out of superjson. Makes things uncomplicated

@jvhellemond
Copy link

FWIW: I'm going to try the same (using setRenderer() and render()) to be able to "support" Infinity and -Infinity in JSON.

@noahehall
Copy link

noahehall commented Nov 19, 2023

hmm i'm going to try this setrender pattern with msgpack

[update] worked perfectly, i'll test out the rpc stack in a bit

// @see https://github.com/honojs/hono/issues/1706
declare module "hono" {
  interface CRParams {
    data: Map<any, any>;
    as?: string;
    status: number;
  }
  interface ContextRenderer {
    (opts: CRParams): Response;
  }
}
players.get("*", async (c, next) => {
  c.setRenderer(({ data, as = "msgpack", status }) => {
    switch (as) {
      // case "typed":
      case "json":
        return c.json(toJson(data), status);
      case "string":
        return c.text(toJsonStringified(data), status);
      default:
        return new Response(encoder.encode(data, { extensionCodec }), {
          status,
          headers: {
            "Access-Control-Allow-Origin": "*",
            ...MSGPACK_HEADERS,
          },
        });
    }
  });
  await next();
});

players.get("/", async (c) => {
  // curl "localhost:3000/v1/players?as=json&pl=knoa&pl=nirvai"
  // curl "localhost:3000/v1/players?as=string&pl=knoa&pl=nirvai"
  // curl "localhost:3000/v1/players?pl=knoa&pl=nirvai"
  const { as, pl } = c.req.queries();
  return c.render({ as: as?.[0], data: await playersQuery.players(getBaseOpts({ names: pl })) });
});

@maou-shonen
Copy link

I also hope to see this feature.
Although c.render can work well,
I believe using c.json for handling JSON and c.render for handling other more complex things would be more intuitive.
It would also prevent me from accidentally using the wrong method in different repository

@musjj
Copy link

musjj commented Aug 31, 2024

I would love to see this too. AFAIK setRenderer() can be used to deserialize the data to a superjson string, but you still need to serialize it manually on the RPC client side right?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request.
Projects
None yet
Development

No branches or pull requests

6 participants