Skip to content

Instantly share code, notes, and snippets.

@sillvva
Created August 24, 2022 01:34
Show Gist options
  • 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[])
: []
};
};
@duducpp
Copy link

duducpp commented Jul 2, 2024

You can also parse neasted arrays:

function parseObjectPrimitives(obj: Record<string, any>): any {
  return Object.fromEntries(
    Object.entries(obj).map(([k, v]) => {
      if (Array.isArray(v)) return [k, v.map(parseObjectPrimitives)]; // <== HERE
      if (typeof v === "object") return [k, parseObjectPrimitives(v)];
      if (/^[0-9]+$/i.test(v) && !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];
    })
  );
}

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