pocketbase/pocketbase

Pocketbase automatically changes an array with one item to a string/number in field type of JSON

MobinAskari opened this issue · 6 comments

I have two fields that are of type JSON. When I'm trying to update these two fields using the SDK, I provide an array like ["test"] to one of them and another array like [1] to the other, however, Pocketbase automatically changes these two to "test" and 1 in the fields.

I tried all of type of combinations when sending the payload, but Pocketbase keeps doing this weird behavior.

{
 ...user,
 field1: [...user.field1] or user.field1 or even not changing it (when I'm updating another field and not this field),
}

// The payload which is provided to the `update` function looks like this:
{
    "collectionId": "7lmk1rmp06mkzzc",
    "collectionName": "admins",
    "created": "2023-12-13 10:20:26.196Z",
    "email": "test@g.c",
    "emailVisibility": true,
    "id": "mqdthq5c4c26lwz",
    "profile_picture": "screenshot_53_6UzefuZ0ff.png",
    "field1": [
        "test"
    ],
    "field2": [
        1
    ],
    "updated": "2024-01-14 08:36:00.137Z",
    "username": "test",
    "verified": true
}

Not sure if it matters but I can easily change the fields to an array with only one item in the admin UI, without Pocketbase converting it to a string/number.

Update: I also tried providing an array with two items or more, yet Pocketbase only puts the first item of the array in field

Pocketbase version: 0.20.0
Pocketbase JS SDK version: "^0.20.2"

I'm not able to reproduce it with the following code:

const data = await pb.collection("test").create({
    field: [1]
})

If you are still not able to resolve it, please create a minimal reproducible repo or at least provide a more detailed code sample illustrating the problem.

Edit: To help with the debugging, you can also try to inspect the sent request payload in the browser's Inspect tool > Network tab.

Oh, I think I know why this may happen.

This is probably caused by the json -> multipart/form-data conversion, eg. if you are submitting a Blob/File as part of the JSON object.

I'll move the issue to the JS SDK and will try to investigate it sometime later today.

I'm not able to reproduce it with the following code:

const data = await pb.collection("test").create({
    field: [1]
})

If you are still not able to resolve it, please create a minimal reproducible repo or at least provide a more detailed code sample illustrating the problem.

I have this issue when updating a record.

The record schema:

{
        "id": "7lmk1rmp06mkzzc",
        "name": "admins",
        "type": "auth",
        "system": false,
        "schema": [
            {
                "system": false,
                "id": "fpcbxgqa",
                "name": "telegram_names",
                "type": "json",
                "required": true,
                "presentable": false,
                "unique": false,
                "options": {
                    "maxSize": 2000000
                }
            },
            {
                "system": false,
                "id": "xh1lmhww",
                "name": "telegram_number_ids",
                "type": "json",
                "required": true,
                "presentable": false,
                "unique": false,
                "options": {
                    "maxSize": 20000000
                }
            },
            {
                "system": false,
                "id": "vbrbyqtg",
                "name": "profile_picture",
                "type": "file",
                "required": false,
                "presentable": false,
                "unique": false,
                "options": {
                    "mimeTypes": [
                        "image/jpeg",
                        "image/png",
                        "image/svg+xml",
                        "image/gif",
                        "image/webp"
                    ],
                    "thumbs": [],
                    "maxSelect": 1,
                    "maxSize": 5242880,
                    "protected": false
                }
            }
        ],
        "indexes": [],
        "listRule": "",
        "viewRule": "",
        "createRule": null,
        "updateRule": "",
        "deleteRule": null,
        "options": {
            "allowEmailAuth": true,
            "allowOAuth2Auth": false,
            "allowUsernameAuth": true,
            "exceptEmailDomains": null,
            "manageRule": null,
            "minPasswordLength": 8,
            "onlyEmailDomains": null,
            "onlyVerified": false,
            "requireEmail": false
        }
    },

SDK code (I'm not even updating those field yet PB changes them from an array to a primitive:

const updatedUser = {
  ...user,
  profile_picture: profilePicture.item(0)
};

const res = await database
.collection("admins")
.update(updatedUser .id, updatedUser);

even if I do something like this and provide/override the field with an array that contains multiple new items, PB still changes the first items of the original array to a primitive value:

const updatedUser = {
  ...user,
  telegram_names: ["1", "2", "3"],
  profile_picture: profilePicture.item(0)
};

As mentioned earlier, the problem is casued by the JSON -> multipart/form-data serialization.

This serialization happens automatically behind the scene when you are submitting a Blob/File (in your case I guess that is profilePicture.item(0)) as plain object value.

Usually in the past we required users to construct their own FormData but for convenience we added support for the existing fallback (see File upload).

Because the SDK doesn't know anything about the field types the serialization is a little more difficult (I also seems to have left a comment about this in https://github.com/pocketbase/js-sdk/blob/master/src/Client.ts#L468).

As a workaround for now you can call JSON.stringify(yourJSONData) as json value or manually construct your own FormData object.

I'm not sure if this can be resolved (at least not without hacky server-side workarounds) but you can subscribe to pocketbase/js-sdk#274.

@MobinAskari A partial and temporary workaround was implemented in JS SDK v0.20.3.

A proper fix will be available with PocketBase v0.21.0.

@MobinAskari A partial and temporary workaround was implemented in JS SDK v0.20.3.

A proper fix will be available with PocketBase v0.21.0.

Thank you 🙏