Coder Social home page Coder Social logo

object-to-formdata's Introduction

object-to-formdata

Convenient JavaScript function that serializes Objects to FormData instances.

npm npm

Install

npm install object-to-formdata

Usage

NOTE: STARTING WITH VERSION 4.0.0, THE NAMED EXPORT HAS CHANGED!

NOTE: STARTING WITH VERSION 3.0.0, THERE IS NO DEFAULT EXPORT!

import { serialize } from 'object-to-formdata';

const object = {
  /**
   * key-value mapping
   * values can be primitives or objects
   */
};

const options = {
  /**
   * include array indices in FormData keys
   * defaults to false
   */
  indices: false,

  /**
   * treat null values like undefined values and ignore them
   * defaults to false
   */
  nullsAsUndefineds: false,

  /**
   * convert true or false to 1 or 0 respectively
   * defaults to false
   */
  booleansAsIntegers: false,

  /**
   * store arrays even if they're empty
   * defaults to false
   */
  allowEmptyArrays: false,

  /**
   * don't include array notation in FormData keys for any attributes except Files in arrays
   * defaults to false
   */
  noAttributesWithArrayNotation: false,

  /**
   * don't include array notation in FormData keys for Files in arrays
   * defaults to false
   */
  noFilesWithArrayNotation: false,

  /**
   * use dots instead of brackets for object notation in FormData keys
   * defaults to false
   */
  dotsForObjectNotation: false,
};

const formData = serialize(
  object,
  options, // optional
  existingFormData, // optional
  keyPrefix, // optional
);

console.log(formData);

object-to-formdata's People

Contributors

chrisshen93 avatar dependabot-preview[bot] avatar dependabot[bot] avatar jbuijgers avatar jerone avatar joelmuskwe avatar nkwwk avatar piranna avatar renovate[bot] avatar therealparmesh avatar zack-hable avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

object-to-formdata's Issues

Nested Blob

I've got an Object like that:

let obj = {
   table: 'food',
   id: this.food.id,
   media: [
     {url: "https://picsum.photos/400/400"},
     {image: Blob},
     {url: "https://picsum.photos/200/400"},
     ....
    ]
  };

Unfortunately that does not work. I get in the backend:

array:3 [
  "table" => "food"
  "id" => "1"
  "media" => array:2 [
     0 => array:1 [
        "url" => "https://picsum.photos/400/400"
        "image" => UploadedFile {#593} //it should be in 1 =>
         ]
    ]
]

Releases tag

Hi,

Thanks for your help on a good project!

Before releasing, could the releases be tagged so we have a way to go backward and fetch/see the old code base?

It also helps if one can add info with release notes.

Empty arrays pass [null] instead of []

I don't think this is the expected default behavior because it is not how axios typically handles submissions of empty arrays.

Perhaps there could be a prop to ignore empty arrays instead of passing them with a null value inside?

Currently I am working around this by using server-side middleware to convert [null] back to []

Wrong formatting in arrays, fix.

Hi, @therealparmesh I'm using object-to-formdata is very usefully.

Well I have the following example data to convert:

{
  "phones": [
   {
      "number": 9999999,
      "code": 52,
      "contact": "Maria"
   }
 ]
};

I convert the information and process it into php and the result of array is the follow:

[
    'phones' => [
        [
            'number' => '9991944318',
        ],
        [
            'code' => '52',
        ],
        [
            'contact' => 'Maria',
        ],
    ],
]

as you can see each item is within an array.

I solved this problem as follows:

function objectToFormData (obj, fd, pre) {
  fd = fd || new FormData()

  Object.keys(obj).forEach(function (prop) {
    var key = pre ? (pre + '[' + prop + ']') : prop

    if (isObject(obj[prop]) && !isArray(obj[prop]) && !isFile(obj[prop])) {
      objectToFormData(obj[prop], fd, key)
    } else if (isArray(obj[prop])) {

       // HERE.
       // I get the index from the array
      obj[prop].forEach(function (value, index) {

       // HERE.
       // I pass the index to makeArrayKey.
        var arrayKey = makeArrayKey(key, index)
        if (isObject(value) && !isFile(value)) {
          objectToFormData(value, fd, arrayKey)
        } else {
          fd.append(arrayKey, value)
        }
      })
    } else {
      fd.append(key, obj[prop])
    }
  })

// HERE.
// I receive the index as default "null".
function makeArrayKey (key, index = null) {
  if (key.length > 2 && key.lastIndexOf('[]') === key.length - 2) {
    console.log('aqui en solo key');
    return key
  } else {
    // HERE.
    // I valid the existence of the index to indicate that it 
    // is added within the same array.
    return index != null ? key + '['+index+']' : key + '[]';
  }
}

And then the result is the follow It's just like I expected.

[
    'phones' => [
        [
            'number' => '9991944318',
            'code' => '52',
            'contact' => 'Maria',
        ],
    ],
]

That's all. Thank you.

IE 11 support

Please consider transpiling into IE11 compatible bundle.
Thanks

es6 syntax in dist folder (e.g. arrow functions)

I'm using this in a vue-cli project and I noticed that I have es6 code in my transpiled output which looks like this:

const r=t=> void 0===t,i= t=> Array.isArray(t),o=t=>t&&"number"==typeof t.size&&"string"==typeof t.type&&"function"==typeof t.slice,a=(t,e,n,s)=>{if((e=e||{}).indices=!r(e.indices)&&e.indices,e.nullsAsUndefined=!r(e.nullsAsUndefined)&&e.nullsAsUndefined,n=n||new FormData,r(t))return n;if((t=>null===t)(t)) [...]

Because of the nullsAsUndefined I traced it back to this module.

Other dependencies get transpiled afaik or at least do not have es6 could in the compiled output. I don't know if this has something to do with how object-to-formdata is set up or how other projects do it, but somehow it should not output es6 code when using babel to polyfill/transpile things.

Is there something we can do to avoid this?

Date timezone

Hi, I may have found an issue related to timezones: the lib uses toISOString() internally to convert dates to strings, but this crops the timezone info by converting the date to UTC. This may be a problem when we need the timezone. I suggest adding an option to keep the timezone. As ISO8601 allows timezone data, this shouldn't break the API.

I can prepare a PR if you're ok with that?

Duplicate array suffix

When feeding in data where the array fields already have an array suffix ([]), like so:

let formData = objectToFormData({
	'foo[]': ["bar", "baz"]
});

console.log(JSON.stringify(Array.from(formData.entries())))

... this module produces the following (JSON-stringified) entries:

[
	["foo[][]", "bar"],
	["foo[][]", "baz"]
]

... whereas the output should be as follows:

[
	["foo[]", "bar"],
	["foo[]", "baz"]
]

The cause of this is line 25, which blindly adds a [] suffix without checking whether one already exists. The fix would be to first check whether the field name already ends with [].

EDIT: Fixed expected output.

Nested nested objects are being pushed up a level

Maybe I am doing something incorrectly but having an object like

obj = {
  prop1 : {
     prop2 : {
        prop3: value,
        prop4: value,
     }
  }
}

Will push the props2 up a level, it doesn't nest deeper than 1 level. It will become

obj = {
  prop1 : {
  },
  prop2 : {
     prop3: value,
     prop4: value,
  }
}

Any way around this behavior?

Microsoft Edge File object missing lastModified

In version 1.3.0 File objects are converted to FormData improperly in MS Edge.

Recently File checking has been changed to (in bd1b2c6):

 function isFile (value) {
-  return value instanceof File
+  return isBlob(value) &&
+      typeof value.lastModified === 'number' &&
+      typeof value.name === 'string'
 }

But in MS Edge File object doesn't have lastModified property https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/4155006/, instead it has lastModifiedDate of 'object' type.

Not supported the nested objects

I have tried to convert the nested object to formData with serialize

let object = { key1: "VALUE1", key2: { nestedKey1: "NESTED_VALUE1" } }

but it is not support this case ==(

Boolean transformed by string

Hi

With checkboxes, when I use object-to-formdata , it transformed the booleans by string.
Can It keeps boolean as boolean ?

Thanks,

isReactNativeBlob breaking nodejs without polyfill

Hello,

Until recently I could use serialize with my custom FromData instance within nodejs (from the "form-data" npm package) but with the introduction of isReactNativeBlob an error is thrown because it uses FormData directly.

Maybe it would be a solution to add an option to specify if we don't use React Native at all ? or pass the FormData constructor in options ?

Arrow functions + es5

I must profess my ignorance but I have a project where ie11 support is needed and this package is being used. I am wondering how I can get an es5 compatible version?

Another way of specifying the key of an object from an array

Hey!

Your solution is quite universal, but in my situation it does not work completely.
I am using Spring Boot on the server side and it expects the keys be like key[0].key
But unfortunately, this library parses json as key[0][key] and therefore the server cannot recognize data

Is it possible to introduce such an option?

My test case:
image
It must be like:
followedNiches[0].id: 2
followedNiches[1].id: 4
followedNiches[2].id: 5

And this is log of my server:
image

Or am I missing something?

BUG - Module Not Found via Webpack

Uncaught ReferenceError: module is not defined
    at Module../node_modules/object-to-formdata/dist/index.mjs (VM406 main.video-service.js:112066)
    at __webpack_require__ (VM406 main.video-service.js:726)

To solve this issue, put your src/index.js at the root dir (i.e. outside of /src)

When bundled via webpack and probably gulp too these errors occur.

Issue with empty arrays

I am having an issue on converting an object that has an empty array in value. For ex,

let data = {
'some-key' : []
};

On, converting this to form data what I get at the backend is [null]. Please see to it as I am using validation at the backend which fails. Either it should return null or an empty []

FormData is not defined. Dependency missing?

Looks like dependency to form-data is missing:

ReferenceError: FormData is not defined
at isFormData (D:\AFTERWORK\PROJ\JavaScript\SaldosPaymentTest\node_modules\object-to-formdata\index.js:42:27)
at objectToFormData (D:\AFTERWORK\PROJ\JavaScript\SaldosPaymentTest\node_modules\object-to-formdata\index.js:46:7)
at sendToSaldos (D:\AFTERWORK\PROJ\JavaScript\SaldosPaymentTest\index.js:33:37)

Unexpected Result For Array of Object

Using [email protected] from npm.

input:

{
    name: 'bob',
    cart: [
        { name: 'book', qty: 1 },
        { name: 'pencil', qty: 2 }
    ],
};

expected result:

name: bob
cart[0][name]: book
cart[0][qty]: 1
cart[1][name]: pencil
cart[1][qty]: 2
array:2 [
  "name" => "bob"
  "cart" => array:2 [
    0 => array:2 [
      "name" => "book"
      "qty" => "1"
    ]
    1 => array:2 [
      "name" => "pencil"
      "qty" => "2"
    ]
  ]
]

actual result:

name: bob
cart[][name]: book
cart[][qty]: 1
cart[][name]: pencil
cart[][qty]: 2
array:2 [
  "name" => "bob"
  "cart" => array:4 [
    0 => array:1 [
      "name" => "book"
    ]
    1 => array:1 [
      "qty" => "1"
    ]
    2 => array:1 [
      "name" => "pencil"
    ]
    3 => array:1 [
      "qty" => "2"
    ]
  ]
]

UnhandledPromiseRejectionWarning: ReferenceError: FormData is not defined

When I use it in code

    const d = {
      from: 'HQ',
      recipients_is_delayed: [
        {
          address: 'someAddress',
          name: 'some name',
        },
      ],
      recipients: [
        {
          address: 'someAddress',
          name: 'some name',
        },
      ],
      blind_copies: [
        {
          address: 'someAddress',
          name: 'some name',
        },
      ],
      subject: `Анонимный отзыв`,
      body: `тут текст`,
    };
    
    const formData = objectToFormData(d);
    
    callApiFetch(
      {
        url: `https://someUrl`,
        body: formData,
      },
      false,
    );

returns ReferenceError: FormData is not defined at isFormData (/path/node_modules/object-to-formdata/index.js:42:27)

adding line on top of the /object-to-formdata/index.js file
const FormData = require('form-data');
solved problem.

Feature request: Boolean value handling

New option would be nice that lets you specify to convert boolean values to 0 and 1 respectively as opposed to string values "true" and "false". Right now the automatic conversion to string values is not compatible with Laravel's built in validation system which accepts string "0" and "1" / 0 or 1 or boolean true / false. You do want to maintain strict type checking in JS code so using 0 and 1 is not a good idea. The best option at the moment is to just convert the boolean values before running the final object thru this script.

i think easy way

        var JSONToFormData = function (_obj) {
        var fd = new FormData();
        var walked = [];
        var stack = [{obj: _obj, stack: ''}];
        while (stack.length > 0)
        {
            var item = stack.pop();
            var obj = item.obj;
            for (var property in obj) {
                if (obj.hasOwnProperty(property)) {
                    if (typeof obj[property] == "object") {
                        var alreadyFound = false;
                        for (var i = 0; i < walked.length; i++)
                        {
                            if (walked[i] === obj[property])
                            {
                                alreadyFound = true;
                                break;
                            }
                        }
                        if (!alreadyFound)
                        {
                            walked.push(obj[property]);
                            stack.push({obj: obj[property], stack: item.stack + '[' + property + "]"});
                        }

                    } else
                    {
                        var kk = item.stack + '[' + property + ']';
                        var vv = obj[property];
                        kk = kk.replace("[", "");
                        kk = kk.replace("]", "");
                        fd.append(kk, vv);
                    }
                }
            }
        }

        return fd;
    };

Issue with date time format

I have a complex object containing an array of objects, files, multiple files, and also date type. With axios, the date can serialize correctly, but I have issues with an object and multiple files because the format from the backend is accepted the brackets formatting. So I feel helpful with this package, but I have an issue with the date type, idk why.
Here is my payload request for the date type:
document_date: 2022-11-15T18:11:01.000Z

Bad formatting

I'm having issues about formating...
I'm formatting and sending to the server this

someOtherProperties...
hasDays: [
  someOthersProperties
  routine_day: [
    image: File
    routine_day_exercises: []
    status: 1
    title: string
  ]
]

But if i log on the server i'm getting

someOtherProperties...
hasDays: [
  someOthersProperties
  routine_day: [
    image: File
    ],
  routine_day: [
      status: 1
    ],
  routine_day: [
      title: string
    ],
  ]
]

I guess it has something to do with recursivity...

Feature: allowEmptyArrays with null

Hey bro thanks for cool lib
Can you add new props emptyArrays to null;
My backend can handle empty arrays if it's null.
Example:
I have multiselect
I removed all props, and backend wait from me format like this:

{
  ...
  custom_multiselect: null
  ...
}
Снимок экрана 2023-09-18 в 14 15 21

Null value when posted in .NET Core

Just to mention in case someone runs into this.

When posting a file in a nested object to a controller, it is always null, it just happens with types of IFormFile, seems like the issue is the key in the formdata.

Instead of setting the key to obj[nested] it should go like obj.nested. I changed the key const to const key = pre ? pre + "." + prop : prop; and it worked fine. Like I said, all the other props worked fine, just the files are the one who always post null.

how to overcome the key name changes in json []

const options = {
indices: true,
};
const obj={
oid:1,
members:{
'roles': [],
'members':['cvcv']
}
}

const formData1 = objectToFormData(
obj,options
);

below is the key set of form data
[members[members][0], oid]
required
[members, oid]

Backward compatibility

Not cool.. Previous version had second parameter "postData", and now it is config.. Luckily, found it, but broke my code in production since CI pulled later version which was actually incompatible. You should've added version 2 to indicate breaking changes..

Jest SyntaxError: Unexpected token 'export'

Occurred when running test

FAIL  src/components/xxx
  ● Test suite failed to run

    Jest encountered an unexpected token

    This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.

    By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".

    Here's what you can do:
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/en/configuration.html
SyntaxError: Unexpected token 'export'

2.2.0: "This expression is not callable"

Since upgrade to 2.2.0 my typescript compiler gives me this error:

292:24 This expression is not callable.
  Type 'typeof import(".../node_modules/object-to-formdata/index")' has no call signatures.
    291 |
  > 292 |     const serialized = objectToFormData(params)

I imported it like this:

import objectToFormData from "object-to-formdata"

It still works, but the typescript error is there. Typescript 3.7.3.

Multiple Files in ASP.NET Core

This is either an bug of a different implementation, but converting an array of File objects doesn't work in ASP.NET Core.

For example:

var model = {
	battlePlans: [new File(), new File()]
};
const formData = objectToFormData(model);
console.log(formData);

// Currently returns:
// battlePlans[]: (binary)
// battlePlans[]: (binary)

But apparently ASP.NET Core expects the following:

var model = {
	battlePlans: [new File(), new File()]
};
const formData = objectToFormData(model);
console.log(formData);

// Expected to return:
// battlePlans: (binary)
// battlePlans: (binary)

Note the missing [].

The only reference from Microsoft saying that it should be done like this, is in the following section:
image
The note reference to the following code example:

var formData = new FormData();
for (var file in files) {
  formData.append("battlePlans", file, file.name);
}

MDN on the other side shows an example where they use the brackets, saying that this is the way to be compatible with PHP:

formData.append('userpic[]', myFileInput.files[0], 'chris1.jpg');
formData.append('userpic[]', myFileInput.files[1], 'chris2.jpg');

WHATWG is not specific about this.

This appears to be a problem only for an array of File objects. Other types work just fine with current implementation.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.