Convert JS Object to form data

前端 未结 18 1877
孤街浪徒
孤街浪徒 2020-11-29 17:22

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 valu

相关标签:
18条回答
  • 2020-11-29 17:37

    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)
    
    0 讨论(0)
  • 2020-11-29 17:37

    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!

    0 讨论(0)
  • 2020-11-29 17:38

    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]
          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>

    0 讨论(0)
  • 2020-11-29 17:39

    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);
            }
        }
    
    0 讨论(0)
  • 2020-11-29 17:40

    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;
    }
    
    0 讨论(0)
  • 2020-11-29 17:47

    Try JSON.stringify function as below

    var postData = JSON.stringify(item);
    var formData = new FormData();
    formData.append("postData",postData );
    
    0 讨论(0)
提交回复
热议问题