Skip to content

Instantly share code, notes, and snippets.

@sillvva
Created August 24, 2022 01:34
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sillvva/aa3c32c21355d43d06f3943f9e520690 to your computer and use it in GitHub Desktop.
Save sillvva/aa3c32c21355d43d06f3943f9e520690 to your computer and use it in GitHub Desktop.
Query String Parser with Zod
import qs from "qs";
import { ZodSchema } from "zod";
const parseObjectPrimitives = (obj: Record<string, any>): any => {
return Object.fromEntries(
Object.entries(obj).map(([k, v]) => {
if (typeof v === "object") return [k, parseObjectPrimitives(v)];
if (!isNaN(parseFloat(v))) return [k, parseFloat(v)];
if (v === "true") return [k, true];
if (v === "false") return [k, false];
if (typeof v === "string") return [k, v];
return [k, null];
})
);
};
export const qsParse = <T>(queryString: string | Record<string, any>, schema: ZodSchema<T>) => {
const parsed =
typeof queryString === "string"
? qs.parse(queryString, {
ignoreQueryPrefix: true
})
: queryString;
const zResult = schema.safeParse(parseObjectPrimitives(parsed));
return {
data: zResult.success ? zResult.data : ({} as T),
errors: !zResult.success
? zResult.error.issues.map(i => `${i.path.join(".")}: ${i.message}`).reduce((acc, v) => (acc.includes(v) ? acc : [...acc, v]), [] as string[])
: []
};
};
@devhero
Copy link

devhero commented Jan 4, 2024

to not lose alphanumeric during parseFloat conversion, I add a number regex check:

/^[0-9]+$/i.test(v)

So the function parseObjectPrimitives:

const parseObjectPrimitives = (obj: Record<string, any>): any => {
  return Object.fromEntries(
    Object.entries(obj).map(([k, v]) => {
      if (typeof v === "object") return [k, parseObjectPrimitives(v)];
      if (/^[0-9]+$/i.test(v) && !isNaN(parseFloat(v))) return [k, parseFloat(v)]; // <== HERE
      if (v === "true") return [k, true];
      if (v === "false") return [k, false];
      if (typeof v === "string") return [k, v];
      return [k, null];
    })
  );
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment