260

How can I can convert my JS Object to FormData?

The reason why I want to do this is, I have an object that I constructed out of the ~100 form field values.

var item = {
   description: 'Some Item',
   price : '0.00',
   srate : '0.00',
   color : 'red',
   ...
   ...
}

Now I am asked to add the upload file functionality to my form which, of-course is impossible via JSON and so I am planning on moving to FormData. So is there any way that I can convert my JS object to FormData?

Kamran Ahmed
  • 11,809
  • 23
  • 69
  • 101

28 Answers28

279

If you have an object, you can easily create a FormData object and append the names and values from that object to formData.

You haven't posted any code, so it's a general example;

var form_data = new FormData();

for ( var key in item ) {
    form_data.append(key, item[key]);
}

$.ajax({
    url         : 'http://example.com/upload.php',
    data        : form_data,
    processData : false,
    contentType : false,
    type: 'POST'
}).done(function(data){
    // do stuff
});

There are more examples in the documentation on MDN

adeneo
  • 312,895
  • 29
  • 395
  • 388
  • 1
    It's safer to use Object.keys() instead of the for-in loop, as you might get unexpected results, as the for-in iterates on inherited properties as well. – Lior May 21 '14 at 10:17
  • 5
    @Lior - `item` is a regular object created by the OP, so it shouldn't have any properties that are not it's own, unless someone made the mistake of prototyping something onto the Object constructor, in which case you would be in a world of trouble, and it's not something we should have to protect against. – adeneo May 22 '14 at 04:07
  • 1
    Actually, it's considered a best practice, especially if you're giving a solution to someone which you don't know the context and the environment he uses, a simple warning would have done the job. Remember that the solutions you give on SO aren't just for the OP but for potentially thousands of other eyes looking for a solution, which won't break their code. – Lior May 22 '14 at 09:35
  • 3
    @Lior - it's just adding the key/value pairs to FormData, adding a prototyped property wont break anything, and using `Object.keys` is not the answer, as you shouldn't have to get the keys as an array, then iterate over the keys to get the values, you should be using a `for..in` loop. – adeneo May 22 '14 at 11:23
  • 2
    Of course it will, you don't know what the server is expecting... for...in in JS is problamtic, the solution doesn't have to be Object.keys(), it could be hasOwnProperty(), but it needs to be at least a warning. – Lior May 22 '14 at 12:36
  • 4
    @Lior - If your server breaks when it receives one more key/value pair in a POST request, you're doing it wrong. I think the answer is fine, and I'm not going to change it to use `Object.keys` or `hasOwnProperty()` as the object is posted in the question and shouldn't need any of those. The reason you sometimes see `hasOwnProperty` used in plugins etc. is because you never know what some people might do to the `Object` constructor, but for the most part people shouldn't have to test for inherited properties on objects they've created, that's a sign that you're probably doing something wrong. – adeneo May 22 '14 at 13:02
  • 2
    I don't agree some third party libs change native prototypes, and if you give an answer you should warn about potential pitfalls. But never mind, this isn't going anywhere... p.s. http://stackoverflow.com/questions/684672/loop-through-javascript-object – Lior May 22 '14 at 15:48
  • 3
    @BenjaminGruenbaum Both of you guys have missed my point, and for some reason you instead just got really emotional about the whole thing (at least adeneo kept it cool and professional). There was no attempt to educate anyone (although I think the idea you can't learn from someone even though you have "more than 100 times the reputation and 100 times the number of answers" is absurd...especially when SO is all about learning). – Lior May 26 '14 at 07:35
  • 4
    What would be the way to convert a complex json object (which contains nested objects and arrays) into a FormData object ? – yglodt Nov 30 '15 at 15:00
  • whats the best way to convert FromData to a json object to be send to the server? – SuperUberDuper Jun 04 '16 at 15:09
  • If you need JSON, you should create JSON, not a formData object. – adeneo Jun 04 '16 at 19:04
  • I think that this will not work if `item[key]` is an object or an array. Please take a look at my answer – Aleksandrus Sep 12 '16 at 02:55
  • 1
    Of course it won't work with nested objects, one would need to iterate differently depending on the data structure one has. – adeneo Sep 12 '16 at 07:18
  • @adeneo Here's a more modern approach, while also avoiding looping through and appending prototype properties: [JSFiddle](https://jsfiddle.net/dx967tkv/5/). – rmolinamir Apr 25 '19 at 01:28
  • @adeneo can you update this to use `fetch()` instead of jquery please? – Boris Verkhovskiy Dec 27 '19 at 17:30
160

With ES6 and a more functional programming approach @adeneo's answer could looks like this:

function getFormData(object) {
    const formData = new FormData();
    Object.keys(object).forEach(key => formData.append(key, object[key]));
    return formData;
}

And alternatively using .reduce() and arrow-functions:

const getFormData = object => Object.keys(object).reduce((formData, key) => {
    formData.append(key, object[key]);
    return formData;
}, new FormData());
agm1984
  • 15,500
  • 6
  • 89
  • 113
Jacob Lauritzen
  • 2,690
  • 1
  • 18
  • 17
103

This function adds all data from object to FormData

ES6 version from @developer033:

function buildFormData(formData, data, parentKey) {
  if (data && typeof data === 'object' && !(data instanceof Date) && !(data instanceof File) && !(data instanceof Blob)) {
    Object.keys(data).forEach(key => {
      buildFormData(formData, data[key], parentKey ? `${parentKey}[${key}]` : key);
    });
  } else {
    const value = data == null ? '' : data;

    formData.append(parentKey, value);
  }
}

function jsonToFormData(data) {
  const formData = new FormData();
  
  buildFormData(formData, data);
  
  return formData;
}

const my_data = {
  num: 1,
  falseBool: false,
  trueBool: true,
  empty: '',
  und: undefined,
  nullable: null,
  date: new Date(),
  name: 'str',
  another_object: {
    name: 'my_name',
    value: 'whatever'
  },
  array: [
    {
      key1: {
        name: 'key1'
      }
    }
  ]
};

jsonToFormData(my_data)

jQuery version:

function appendFormdata(FormData, data, name){
    name = name || '';
    if (typeof data === 'object'){
        $.each(data, function(index, value){
            if (name == ''){
                appendFormdata(FormData, value, index);
            } else {
                appendFormdata(FormData, value, name + '['+index+']');
            }
        })
    } else {
        FormData.append(name, data);
    }
}


var formData = new FormData(),
    your_object = {
        name: 'test object',
        another_object: {
            name: 'and other objects',
            value: 'whatever'
        }
    };
appendFormdata(formData, your_object); 
Vladimir Novopashin
  • 1,409
  • 2
  • 11
  • 16
32

The other answers were incomplete for me. I started from @Vladimir Novopashin answer and modified it. Here are the things, that I needed and bug I found:

  • Support for file
  • Support for array
  • Bug: File inside complex object needs to be added with .prop instead of [prop]. For example, formData.append('photos[0][file]', file) didn't work on google chrome, while formData.append('photos[0].file', file) worked
  • Ignore some properties in my object

The following code should work on IE11 and evergreen browsers.

function objectToFormData(obj, rootName, ignoreList) {
    var formData = new FormData();

    function appendFormData(data, root) {
        if (!ignore(root)) {
            root = root || '';
            if (data instanceof File) {
                formData.append(root, data);
            } else if (Array.isArray(data)) {
                for (var i = 0; i < data.length; i++) {
                    appendFormData(data[i], root + '[' + i + ']');
                }
            } else if (typeof data === 'object' && data) {
                for (var key in data) {
                    if (data.hasOwnProperty(key)) {
                        if (root === '') {
                            appendFormData(data[key], key);
                        } else {
                            appendFormData(data[key], root + '.' + key);
                        }
                    }
                }
            } else {
                if (data !== null && typeof data !== 'undefined') {
                    formData.append(root, data);
                }
            }
        }
    }

    function ignore(root){
        return Array.isArray(ignoreList)
            && ignoreList.some(function(x) { return x === root; });
    }

    appendFormData(obj, rootName);

    return formData;
}
Gudradain
  • 4,653
  • 2
  • 31
  • 40
  • 3
    The only answer supporting arrays, objects and files. – yakya Jul 04 '18 at 18:54
  • Hi, why do you add the File to the root? Is it possible to add it to child too? – Cedric Arnould Sep 26 '18 at 20:17
  • 1
    @CedricArnould It might be a misunderstanding but the method is recursive so even if it's written `formData.append(root, data)`, it doesn't mean that it's added to the root. – Gudradain Sep 26 '18 at 20:31
  • I understand your answer, strangely when I get the result in the server, I have a unique Collection of Files and the data. But I can see in a File the name give the information to which child it s connected. Maybe the problem comes from .Net Core and how it manage upload files. Thanks for your answer. – Cedric Arnould Sep 26 '18 at 22:03
  • 2
    i'm trying to use this but there is no usage example. the expected format of the ignoreList param would be pretty helpful. – jpro Jun 09 '20 at 19:43
  • There is a big difference between `photos[0][file]` and `photos[0].file`. In the case of `photos[0][file]`, `file` is a locally available variable that needs to be defined, and if that variable is a string (or number), that is used as the key for lookup. On the other hand, `photos[0].file` directly looks up the key `file` on `photos[0]`. That has nothing to do with browsers, it's just how the JavaScript syntax works. – ThaJay Oct 07 '21 at 09:44
  • `photos[0].file` and `photos[0]['file']` would be equivalent, but here the second example is obviously weird. `photos[0][file]` is dynamic, `photos[0].file` is static, `photos[0]['file']` is static with magic string. – ThaJay Oct 07 '21 at 09:54
  • 2
    some illustrations for this code (especially the parameters) would be very helpful. – shamaseen Jan 14 '22 at 19:12
32

Try JSON.stringify function as below

var postData = JSON.stringify(item);
var formData = new FormData();
formData.append("postData",postData );
Udayraj Khuman
  • 556
  • 2
  • 6
  • 11
13

function toFormData(o) {
  return Object.entries(o).reduce((d,e) => (d.append(...e),d), new FormData())
}

var object = {
  username: 'JohnDoe',
  file: new File(['foo'], 'foo.txt', {type: 'text/plain'})
}

fetch('https://httpbin.org/post', {
  method: 'POST',
  body: toFormData(object)
}).then(r => r.json()).then(console.log)
井上智文
  • 1,905
  • 17
  • 14
  • It's valid only if JSON is flatten to 1 level, otherwise the FormData would could use recursion. – Godô Apr 29 '22 at 16:54
10

I had a scenario where nested JSON had to be serialised in a linear fashion while form data is constructed, since this is how server expects values. So, I wrote a small recursive function which translates the JSON which is like this:

{
   "orderPrice":"11",
   "cardNumber":"************1234",
   "id":"8796191359018",
   "accountHolderName":"Raj Pawan",
   "expiryMonth":"02",
   "expiryYear":"2019",
   "issueNumber":null,
   "billingAddress":{
      "city":"Wonderland",
      "code":"8796682911767",
      "firstname":"Raj Pawan",
      "lastname":"Gumdal",
      "line1":"Addr Line 1",
      "line2":null,
      "state":"US-AS",
      "region":{
         "isocode":"US-AS"
      },
      "zip":"76767-6776"
   }
}

Into something like this:

{
   "orderPrice":"11",
   "cardNumber":"************1234",
   "id":"8796191359018",
   "accountHolderName":"Raj Pawan",
   "expiryMonth":"02",
   "expiryYear":"2019",
   "issueNumber":null,
   "billingAddress.city":"Wonderland",
   "billingAddress.code":"8796682911767",
   "billingAddress.firstname":"Raj Pawan",
   "billingAddress.lastname":"Gumdal",
   "billingAddress.line1":"Addr Line 1",
   "billingAddress.line2":null,
   "billingAddress.state":"US-AS",
   "billingAddress.region.isocode":"US-AS",
   "billingAddress.zip":"76767-6776"
}

The server would accept form data which is in this converted format.

Here is the function:

function jsonToFormData (inJSON, inTestJSON, inFormData, parentKey) {
    // http://stackoverflow.com/a/22783314/260665
    // Raj: Converts any nested JSON to formData.
    var form_data = inFormData || new FormData();
    var testJSON = inTestJSON || {};
    for ( var key in inJSON ) {
        // 1. If it is a recursion, then key has to be constructed like "parent.child" where parent JSON contains a child JSON
        // 2. Perform append data only if the value for key is not a JSON, recurse otherwise!
        var constructedKey = key;
        if (parentKey) {
            constructedKey = parentKey + "." + key;
        }

        var value = inJSON[key];
        if (value && value.constructor === {}.constructor) {
            // This is a JSON, we now need to recurse!
            jsonToFormData (value, testJSON, form_data, constructedKey);
        } else {
            form_data.append(constructedKey, inJSON[key]);
            testJSON[constructedKey] = inJSON[key];
        }
    }
    return form_data;
}

Invocation:

        var testJSON = {};
        var form_data = jsonToFormData (jsonForPost, testJSON);

I am using testJSON just to see the converted results since I would not be able to extract the contents of form_data. AJAX post call:

        $.ajax({
            type: "POST",
            url: somePostURL,
            data: form_data,
            processData : false,
            contentType : false,
            success: function (data) {
            },
            error: function (e) {
            }
        });
Raj Pawan Gumdal
  • 7,390
  • 10
  • 60
  • 92
10

You can simply use:

formData.append('item', JSON.stringify(item));
Ahsan Farooq
  • 819
  • 9
  • 10
7

2022 Update

Axios now supports automatic serialization of an object to FormData

Since version 0.27 Axios supports automatic object serialization to a FormData object if the request Content-Type header is set to multipart/form-data. Read more

Nested objects and files

Following solutions handles nested objects and arrays and files.

const buildFormData = (formData: FormData, data: FormVal, parentKey?: string) => {
    if (Array.isArray(data)) {
        data.forEach((el) => {
            buildFormData(formData, el, parentKey)
        })

    } else if (typeof data === "object" && !(data instanceof File)) {
        Object.keys(data).forEach((key) => {
            buildFormData(formData, (data as FormDataNest)[key], parentKey ? `${parentKey}.${key}` : key)
        })

    } else {
        if (isNil(data)) {
            return
        }

        let value = typeof data === "boolean" || typeof data === "number" ? data.toString() : data
        formData.append(parentKey as string, value)
    }
}

export const getFormData = (data: Record<string, FormDataNest>) => {
    const formData = new FormData()

    buildFormData(formData, data)

    return formData
}

Types

type FormDataPrimitive = string | Blob | number | boolean

interface FormDataNest {
  [x: string]: FormVal
}

type FormVal = FormDataNest | FormDataPrimitive
Ben Carp
  • 24,214
  • 9
  • 60
  • 72
  • 2
    I like the solution, but I'd recommend starting with `if (isNil(data)) return` because `typeof null === 'object'`. – Julian Oct 25 '20 at 20:47
  • 1
    wonderful solution, I'd recommend changing the Array part to: ```let obj: FormDataNest = {}; obj[index] = el; buildFormData(formData, obj, parentKey)``` as you need to append the index too in the array, not flatten it instead. – shamaseen Apr 20 '22 at 12:29
  • better add `FileList` to the `FormDataPrimitive` types. and change the `data` type in `getFormData` to `FromDataNest` – shamaseen Apr 20 '22 at 12:40
  • What is Axios? This thing I guess? https://axios-http.com/docs/intro Would be good to introduce it a bit in the answer since the question doesn't concern Axios. – foobarbecue Jan 02 '23 at 03:28
6

Here is a short and sweet solution using Object.entries() that will take care of even your nested objects.

// If this is the object you want to convert to FormData...
const item = {
    description: 'First item',
    price: 13,
    photo: File
};

const formData = new FormData();

Object.entries(item).forEach(([key, value]) => {
    formData.append(key, value);
});

// At this point, you can then pass formData to your handler method

Read more about Object.entries() over here - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries

Kingsley
  • 777
  • 1
  • 12
  • 35
5

Sorry for a late answer, but I was struggling with this as Angular 2 currently does not support file upload. So, the way to do it was sending a XMLHttpRequest with FormData. So, I created a function to do it. I'm using Typescript. To convert it to Javascript just remove data types declaration.

/**
     * Transforms the json data into form data.
     *
     * Example:
     *
     * Input:
     * 
     * fd = new FormData();
     * dob = {
     *  name: 'phone',
     *  photos: ['myphoto.jpg', 'myotherphoto.png'],
     *  price: '615.99',
     *  color: {
     *      front: 'red',
     *      back: 'blue'
     *  },
     *  buttons: ['power', 'volup', 'voldown'],
     *  cameras: [{
     *      name: 'front',
     *      res: '5Mpx'
     *  },{
     *      name: 'back',
     *      res: '10Mpx'
     *  }]
     * };
     * Say we want to replace 'myotherphoto.png'. We'll have this 'fob'.
     * fob = {
     *  photos: [null, <File object>]
     * };
     * Say we want to wrap the object (Rails way):
     * p = 'product';
     *
     * Output:
     *
     * 'fd' object updated. Now it will have these key-values "<key>, <value>":
     *
     * product[name], phone
     * product[photos][], myphoto.jpg
     * product[photos][], <File object>
     * product[color][front], red
     * product[color][back], blue
     * product[buttons][], power
     * product[buttons][], volup
     * product[buttons][], voldown
     * product[cameras][][name], front
     * product[cameras][][res], 5Mpx
     * product[cameras][][name], back
     * product[cameras][][res], 10Mpx
     * 
     * @param {FormData}  fd  FormData object where items will be appended to.
     * @param {Object}    dob Data object where items will be read from.
     * @param {Object =   null} fob File object where items will override dob's.
     * @param {string =   ''} p Prefix. Useful for wrapping objects and necessary for internal use (as this is a recursive method).
     */
    append(fd: FormData, dob: Object, fob: Object = null, p: string = ''){
        let apnd = this.append;

        function isObj(dob, fob, p){
            if(typeof dob == "object"){
                if(!!dob && dob.constructor === Array){
                    p += '[]';
                    for(let i = 0; i < dob.length; i++){
                        let aux_fob = !!fob ? fob[i] : fob;
                        isObj(dob[i], aux_fob, p);
                    }
                } else {
                    apnd(fd, dob, fob, p);
                }
            } else {
                let value = !!fob ? fob : dob;
                fd.append(p, value);
            }
        }

        for(let prop in dob){
            let aux_p = p == '' ? prop : `${p}[${prop}]`;
            let aux_fob = !!fob ? fob[prop] : fob;
            isObj(dob[prop], aux_fob, aux_p);
        }
    }
Aleksandrus
  • 1,589
  • 2
  • 19
  • 31
  • You must include array indexes instead of a `[]` for object properties inside a numeric array to stay intact – Vicary Oct 26 '16 at 19:06
3

Recursively

const toFormData = (f => f(f))(h => f => f(x => h(h)(f)(x)))(f => fd => pk => d => {
  if (d instanceof Object) {
    Object.keys(d).forEach(k => {
      const v = d[k] === null ? '' : d[k] === true ? 1 : d[k] === false ? 0 : d[k]
      if (pk) k = `${pk}[${k}]`
      if (v instanceof Object && !(v instanceof Date) && !(v instanceof File)) {
        return f(fd)(k)(v)
      } else {
        fd.append(k, v)
      }
    })
  }
  return fd
})(new FormData())()

let data = {
  name: 'John',
  age: 30,
  colors: ['red', 'green', 'blue'],
  children: [
    { name: 'Max', age: 3 },
    { name: 'Madonna', age: 10 }
  ]
}
console.log('data', data)
document.getElementById("data").insertAdjacentHTML('beforeend', JSON.stringify(data))

let formData = toFormData(data)

for (let key of formData.keys()) {
  console.log(key, formData.getAll(key).join(','))
  document.getElementById("item").insertAdjacentHTML('beforeend', `<li>${key} = ${formData.getAll(key).join(',')}</li>`)
}
<p id="data"></p>
<ul id="item"></ul>
vmartins
  • 322
  • 2
  • 6
2

Solution that will handle nested arrays and objects. Somebody may find it useful

             function add_form_data(form_data,key,item,arr){
                if(typeof(item)==='object' && item && item.constructor===Array){
                    for(var i=0;i<item.length;i++){
                        var item2=item[i];
                        var key2=key+'[' + i +']';
                        if(arr){
                            key2=key+'[' + key2 +']';
                        }
                        add_form_data(form_data,key2,item2,true);
                    }
                }else if(typeof(item)==='object' && item){
                    for ( var key2 in item ) {
                        var item2=item[key2];
                        if(arr){
                            key2=key+'[' + key2 +']';
                        }
                        add_form_data(form_data,key2,item2,arr);
                    }
                }else{
                    form_data.append(key,item);
                }
            }

Usage

            var form_data = new FormData();
            
            add_form_data(form_data,null,json_data);// provide json_data here
             
            var string_url_data=new URLSearchParams(form_data).toString();// if query string is needed
Joshy Francis
  • 340
  • 7
  • 13
1

In my case my object also had property which was array of files. Since they are binary they should be dealt differently - index doesn't need to be part of the key. So i modified @Vladimir Novopashin's and @developer033's answer:

export function convertToFormData(data, formData, parentKey) {
  if(data === null || data === undefined) return null;

  formData = formData || new FormData();

  if (typeof data === 'object' && !(data instanceof Date) && !(data instanceof File)) {
    Object.keys(data).forEach(key => 
      convertToFormData(data[key], formData, (!parentKey ? key : (data[key] instanceof File ? parentKey : `${parentKey}[${key}]`)))
    );
  } else {
    formData.append(parentKey, data);
  }

  return formData;
}
developer033
  • 24,267
  • 8
  • 82
  • 108
Elnoor
  • 3,401
  • 4
  • 24
  • 39
1

Maybe you're looking for this, a code that receive your javascript object, create a FormData object from it and then POST it to your server using new Fetch API:

    let myJsObj = {'someIndex': 'a value'};

    let datos = new FormData();
    for (let i in myJsObj){
        datos.append( i, myJsObj[i] );
    }

    fetch('your.php', {
        method: 'POST',
        body: datos
    }).then(response => response.json())
        .then(objson => {
            console.log('Success:', objson);
        })
        .catch((error) => {
            console.error('Error:', error);
        });
1

I might be a little late to the party but this is what I've created to convert a singular object to FormData.

function formData(formData, filesIgnore = []) {
  let data = new FormData();

  let files = filesIgnore;

  Object.entries(formData).forEach(([key, value]) => {
    if (typeof value === 'object' && !files.includes(key)) {
      data.append(key, JSON.stringify(value) || null);
    } else if (files.includes(key)) {
      data.append(key, value[0] || null);
    } else {
      data.append(key, value || null);
    }
  })

  return data;
}

How does it work? It will convert and return all properties expect File objects that you've set in the ignore list (2nd argument. If anyone could tell me a better way to determine this that would help!) into a json string using JSON.stringify. Then on your server you'll just need to convert it back into a JSON object.

Example:

let form = {
  first_name: 'John',
  last_name: 'Doe',
  details: {
    phone_number: 1234 5678 910,
    address: '123 Some Street',
  },
  profile_picture: [object FileList] // set by your form file input. Currently only support 1 file per property.
}

function submit() {
  let data = formData(form, ['profile_picture']);

  axios.post('/url', data).then(res => {
    console.log('object uploaded');
  })
}

I am still kinda new to Http requests and JavaScript so any feedback would be highly appreciated!

Gibbu
  • 41
  • 1
  • 6
1

Note: This answer doesn't answer the question directly, it gives illustrations and alternatives instead.

People usually use FormData to allow them to upload files, there are 3 ways to do that, I'll mention them in detail in this answer.

1. Get the data from the form directly

To do so, you need to have the name and the value attributes in each input, then you tell the FormData to get the values from the form DOM;

let formData = new FormData(data.target as HTMLFormElement)
  • Pros:
  1. you don't need to involve a JS solution to get the values.
  2. native support for nested data, arrays, etc ...
  • cons:
  1. you will need to make sure that all data needed are added as a value attribute on input DOMs

2. Converting data by JS
If you have the values stored in a variable then you can append them to the FormData using JS.

  • Pros:
  1. can be manipulated as needed
  2. you don't need to have value attributes in input DOMs
  • Cons:
  1. custom complex JS to append nested data to the FormData object
  2. you need to have the values stored in a variable

3. Upload files in a separate request

you can make a separate form for the file upload input.

  • Pros:
  1. you don't need to wait for uploads to submit
  2. you don't need to worry about appending all your data to the FormData object, you will only append the files.
  • Cons:
  1. you need to handle these uploads in the backend before creating the entity itself
  2. you need to handle deleting a file, both on front-end and back-end
shamaseen
  • 2,193
  • 2
  • 21
  • 35
1

Using jquery you can do this simply by $.param(obj) .

Example:

 const obj = {
   description: 'Some Item',
   price: '0.00',
   srate: '0.00',
   color: 'red'
}

const form_obj = $.param(obj);

$.ajax({
  url:"example.com",
  method:"POST",
  data:form_obj
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Alexandre Aimbiré
  • 1,494
  • 2
  • 14
  • 26
Aditya72
  • 79
  • 1
  • 7
0

This method convert a JS object to a FormData :

function convertToFormData(params) {
    return Object.entries(params)
        .reduce((acc, [key, value]) => {
            if (Array.isArray(value)) {
                value.forEach((v, k) => acc.append(`${key}[${k}]`, value));
            } else if (typeof value === 'object' && !(value instanceof File) && !(value instanceof Date)) {
                Object.entries(value).forEach((v, k) => acc.append(`${key}[${k}]`, value));
            } else {
                acc.append(key, value);
            }

            return acc;
        }, new FormData());
}
Monkey Monk
  • 984
  • 9
  • 19
  • Just fix the iteration nested object entries call: ```Object.entries(value).forEach((v, k) => acc.append(`${key}[${v[0]}]`, v[1]));``` – heber gentilin Jul 28 '20 at 17:46
0

You can simply install qs:

npm i qs

Simply import:

import qs from 'qs'

Pass object to qs.stringify():

var item = {
   description: 'Some Item',
   price : '0.00',
   srate : '0.00',
   color : 'red',
   ...
   ...
}

qs.stringify(item)
Balaj Khan
  • 2,490
  • 2
  • 17
  • 30
0

I used this for Post my object data as Form Data.

const encodeData = require('querystring');

const object = {type: 'Authorization', username: 'test', password: '123456'};

console.log(object);
console.log(encodeData.stringify(object));
Yunus ER
  • 1,999
  • 2
  • 9
  • 14
0

I reference this from Gudradain's answer. I edit it a little in Typescript format.

class UtilityService {
    private appendFormData(formData, data, rootName) {

        let root = rootName || '';
        if (data instanceof File) {
            formData.append(root, data);
        } else if (Array.isArray(data)) {
            for (var i = 0; i < data.length; i++) {
                this.appendFormData(formData, data[i], root + '[' + i + ']');
            }
        } else if (typeof data === 'object' && data) {
            for (var key in data) {
                if (data.hasOwnProperty(key)) {
                    if (root === '') {
                        this.appendFormData(formData, data[key], key);
                    } else {
                        this.appendFormData(formData, data[key], root + '.' + key);
                    }
                }
            }
        } else {
            if (data !== null && typeof data !== 'undefined') {
                formData.append(root, data);
            }
        }
    }

    getFormDataFromObj(data) {
        var formData = new FormData();

        this.appendFormData(formData, data, '');

        return formData;
    }
}

export let UtilityMan = new UtilityService();
Mikhael Pramodana
  • 143
  • 1
  • 1
  • 6
0

Simply this can be done :

var item: { some1: "ajbd" , some2: "dds".. }
let myFormData = new FormData();
      
       const abc = item.some1;
       const xyz = item.some2;

          myFormData.append('field1', abc);
          myFormData.append('field2', xyz);
    
    fetch('http:url', {
      method: 'POST',
      headers: {
        'Content-Type': false,
      },
      body: myFormData,
    }).
do promise ..
NoobCoder
  • 493
  • 8
  • 25
0

Here is a very simplistic TypeScript implementation based on answers from @Vladimir Novopashin and @developer033. TypeScript Playground

type Serializeable =
    | string
    | number
    | boolean
    | null
    | Date
    | File
    | { [x: string | number]: Serializeable }
    | Array<Serializeable>;

function serialize(
    data: Serializeable,
    parentKey = '',
    formData: FormData = new FormData()
): FormData {
    if ( typeof data === 'string') {
        formData.append(parentKey, data);
    } else if ( typeof data === 'number') {
        formData.append(parentKey, data.toString());
    } else if ( typeof data === 'boolean') {
        formData.append(parentKey, data ? 'true' : 'false');
    } else if (data === null) {
        formData.append(parentKey, 'null');
    } else if (data instanceof Date) {
        formData.append(parentKey, data.toISOString());
    } else if (data instanceof File) {
        formData.append(parentKey, data);
    } else {
        // Arrays and objects
        Object.entries(data).forEach((entry: [string | number, Serializeable]) => {
            const [key, value] = entry;
            serialize(value, parentKey ? `${parentKey}[${key}]` : key.toString(), formData);
        });
    }

    return formData;
}
h01001000
  • 261
  • 8
  • 20
0

If anyone doesn't want to write their own logic to do this, then there is a library object-to-formdata which solves all the above problems i.e. file, nested objects, etc. and I tried it, it works perfectly fine here is the example

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

    const dataObject = {
     name: "API testing",
     description: "This is to test the API",
     SubObject: {
       subObjectKey1: 3,
       subObjectKey2: 10
       },
     size: 1000,
     batch: 5
    }
    const formData = serialize(dataObject,{dotsForObjectNotation:true})

you can see the other options in the documentation.

0
  • Skip null and undefined values
  • Handles File and Array types
public static objectToFormData = (obj: any): FormData => {
    const formData: FormData = new FormData();

    // Recursive function to handle nested objects
    const appendFormData = (data: any, path: string = ''): void => {
      if ([null, undefined].includes(data)) {
        return;
      }

      if (Array.isArray(data)) {
        data.forEach((value: any, index: number) => {
          const newPath: string = `${path}[${index}]`;
          appendFormData(value, newPath);
        });
      } else if (data instanceof File) {
        formData.append(path, data);
      } else if (typeof data === 'object') {
        Object.entries(data).forEach(([key, value]: [string, any]) => {
          const newPath: string = path ? `${path}.${key}` : key;
          appendFormData(value, newPath);
        });
      } else {
        formData.append(path, String(data));
      }
    };

    appendFormData(obj);

    return formData;
  }
Paul EDANGE
  • 131
  • 1
  • 5
0

This works for Arrays, nested objects, Dates, anything:

https://www.npmjs.com/package/object-to-formdata

Just run npm i object-to-formdata -- save

const formData = serialize(object);

Do not implement it by yourself, apart from that, lot of answers are incomplete here, does not work for array eg.

speti43
  • 2,886
  • 1
  • 20
  • 23
-6

Try obj2fd => https://www.npmjs.com/package/obj2fd

import obj2fd from 'obj2fd'

let data = {a:1, b:2, c:{ca:1}};
let dataWithFormData = obj2fd(data);
//result => [a=>1, b=>2, c=>[ca=>1]]
silkyland
  • 67
  • 8