honojs / hono

Web framework built on Web Standards
https://hono.dev
MIT License
20.61k stars 601 forks source link

validator doesnt parse nested objects in formdata #3710

Open darklight9811 opened 1 day ago

darklight9811 commented 1 day ago

What version of Hono are you using?

4.6.12

What runtime/platform is your app running on? (with version if possible)

bun 1.1.37

What steps can reproduce the bug?

This is compliant with zod-form-data

// biome-ignore lint/suspicious/noExplicitAny: <explanation>
export function appendFormData(data: any, root: string, formData: FormData) {
    if (data instanceof File) return formData.append(root, data);
    if (Array.isArray(data)) {
        for (let i = 0; i < data.length; i++) {
            appendFormData(data[i], `${root}[${i}]`, formData);
        }

        return;
    }
    if (data instanceof Date) {
        return formData.append(root, data.toISOString());
    }
    if (typeof data === "object" && data) {
        for (const key in data) {
            // biome-ignore lint/suspicious/noPrototypeBuiltins: <explanation>
            if (data.hasOwnProperty(key)) {
                if (root === "") appendFormData(data[key], key, formData);
                else appendFormData(data[key], `${root}.${key}`, formData);
            }
        }

        return;
    }
    if (data !== null && typeof data !== "undefined")
        return formData.append(root, data);
}

export function objectToFormData(obj: unknown, rootName = "") {
    const formData = new FormData();

    appendFormData(obj, rootName, formData);

    return formData;
}

What is the expected behavior?

Have deep nested objects sent like this:

FormData {
   name: "Test",
   img: File (170.37 KB) {
     name: "Purple.png",
     type: "image/png"
   },
   "address.id": "dXJuOm1ieHBvaTpkNjUyMjUxOC04NDMzLTRlNzQtYjM5MS1iOGRkZDZlZDg4ZTA",
   "address.label": "Testaccio market, 00153 Rome, Italy",
   "address.coords[0]": 12.47373157,
   "address.coords[1]": 41.87758156,
}

To be parsed like this:

{
   name: "Test",
   img: File (170.37 KB) {
     name: "Purple.png",
     type: "image/png"
   },
   "address": {
      "id": "dXJuOm1ieHBvaTpkNjUyMjUxOC04NDMzLTRlNzQtYjM5MS1iOGRkZDZlZDg4ZTA",
      "label": "Testaccio market, 00153 Rome, Italy",
      "coords": [12.47373157, 41.87758156],
    }
}

What do you see instead?

{
   name: "Test",
   img: File (170.37 KB) {
     name: "Purple.png",
     type: "image/png"
   },
   "address.id": "dXJuOm1ieHBvaTpkNjUyMjUxOC04NDMzLTRlNzQtYjM5MS1iOGRkZDZlZDg4ZTA",
   "address.label": "Testaccio market, 00153 Rome, Italy",
   "address.coords[0]": "12.47373157",
   "address.coords[1]": "41.87758156",
}

Additional information

Also noticed the number got cast into string

yusukebe commented 22 hours ago

Hi @darklight9811

Do you think this is a bug or a feature request?

darklight9811 commented 21 hours ago

Hi @darklight9811

Do you think this is a bug or a feature request?

I think it fits both, since it's a limitation