¿Cómo convertir mi JS Objeto FormData?

La razón por la que quiero hacer es esto, tengo un objeto que he construido a partir de los ~100 valores de campo de formulario.

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

Ahora me pide que agregue el archivo a cargar la funcionalidad a mi forma, que de-supuesto es imposible a través de JSON, así que estoy pensando en mudarse a FormData. Entonces, ¿hay alguna manera de que yo pueda convertir mi JS objeto FormData?

  • puedes compartir tu trabajo/progreso?
  • ¿y JSON.stringify()?
  • Que va a producir un JSON de texto en una cadena. Que no es un FormData objeto.
  • Sí se puede, que se puede anexar a los objetos formData.
  • puede que nos muestran lo que quieres decir con FormData? cualquier formato específico?
  • developer.mozilla.org/en-US/docs/Web/Guide/…
  • verificar github.com/foo123/serialiser.js para serialise complejo / anidada los campos del formulario para formData, objeto, json, codificados los datos (autor)

InformationsquelleAutor Kamran Ahmed | 2014-04-01

10 Comentarios

  1. 116

    Si usted tiene un objeto, usted puede crear fácilmente un objeto FormData y anexar los nombres y los valores de ese objeto formData.

    No ha publicado ningún código, así que es un ejemplo general;

    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
    });

    Hay más ejemplos en la documentación sobre MDN

    • Es más seguro utilizar el Objeto.las teclas() en lugar de la de-en bucle, como se puede obtener resultados inesperados, como el para-en itera sobre las propiedades heredadas así.
    • es habitual, objeto creado por el OP, por lo que no debería tener propiedades que no es propio, a menos que alguien cometió el error de generación de prototipos algo en el constructor del Objeto, en cuyo caso usted estaría en un mundo de problemas, y no es algo que debemos tener para proteger en contra.
    • De hecho, se considera una mejor práctica, especialmente si usted está dando una solución a alguien que usted no conoce el contexto y el entorno en el que se utiliza, una simple advertencia habría hecho el trabajo. Recuerde que las soluciones se da, ENTONCES, no son sólo para el OP, pero para miles de otros ojos buscando una solución, que no rompa su código.
    • es sólo la adición de los pares clave/valor para el objeto FormData, la adición de un prototipo de propiedad no romper nada, y el uso de Object.keys no es la respuesta, como usted no debería tener que conseguir las llaves como una matriz, luego iterar sobre las claves para obtener los valores, se debe utilizar un for..in bucle.
    • Claro que lo hará, usted no sabe lo que el servidor está a la espera de… de…en JS es problamtic, la solución no tiene que ser Objeto.las teclas(), podría ser hasOwnProperty(), pero debe haber al menos una advertencia.
    • Si su servidor se descompone cuando se recibe uno más par clave/valor en una petición POST, lo estás haciendo mal. Creo que la respuesta está muy bien, y no voy a cambiar el uso de Object.keys o hasOwnProperty() como el objeto está publicado en la pregunta y no necesita ninguna de esas. La razón por la que a veces se ve hasOwnProperty utiliza en plugins etc. es porque nunca se sabe lo que algunas personas podrían hacer para el Object constructor, pero la mayor parte de la gente no tiene que probar la heredan las propiedades de los objetos que ha creado, que es una señal de que usted está probablemente haciendo algo mal.
    • No estoy de acuerdo con algunos terceros libs cambio de prototipos nativos, y si te dan una respuesta se le debe advertir sobre los posibles riesgos. Pero no importa, esto no va a ninguna parte… p.s. stackoverflow.com/questions/684672/…
    • ¿tienes intención de construir aviones de paja siguiente, con la esperanza de que había de atraer a más aviones reales que va a caer comida del cielo? Es importante entender que porque una hasOwnProperty de verificación se utiliza, sólo digo que las cosas se considera la «mejor práctica» porque leer de alguien (adivinanzas, Crockford s) libro no llegar muy lejos, tratando de educar a un compañero Para miembros con más de 100 veces la reputación y 100 veces el número de respuestas que tiene no ayuda a su punto muy mucho. También, el nombre de un nueva tercera parte lib que los cambios en el prototipo? Que post es de una hora diferente…
    • Ambos chicos han perdido mi punto, y por alguna razón, en lugar de sólo puso muy emocional sobre toda la cosa (al menos adeneo mantenido fresco y profesional). No hubo ningún intento de educar a nadie (aunque creo que la idea no se puede aprender de alguien, incluso aunque haya «más de 100 veces la reputación y 100 veces el número de respuestas» es absurdo…especialmente cuando ASÍ se trata de aprender).
    • ¿Cuál sería el camino para convertir un complejo objeto json (que contiene objetos anidados y matrices) en un objeto FormData ?
    • cuál es la mejor manera de convertir FromData a un objeto json a enviar al servidor?
    • Si usted necesita JSON, usted debe crear JSON, no un objeto formData.
    • Creo que esto no va a funcionar si item[key] es un objeto o un array. Por favor, echa un vistazo a mi respuesta
    • Por supuesto que no trabajo con objetos anidados, uno tendría que recorrer de manera diferente dependiendo de la estructura de datos que uno tiene.
    • He aquí un enfoque más moderno, además de evitar la formación de bucles a través de y anexando prototipo propiedades: JSFiddle.

  2. 53

    Con ES6 y una más funcional enfoque de programación @adeneo la respuesta se parece a esto:

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

    Y el uso alternativo de .reduce() y la flecha-funciones:

    getFormData = object => Object.keys(object).reduce((formData, key) => {
        formData.append(key, object[key]);
        return formData;
    }, new FormData());
  3. 25

    Esta función agrega todos los datos de objeto FormData

    ES6 versión de @developer033:

    function buildFormData(formData, data, parentKey) {
      if (data && typeof data === 'object' && !(data instanceof Date) && !(data instanceof File)) {
        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)

    versión de jQuery:

    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);
  4. 7

    Tuve un escenario donde anidada JSON tenía que ser serializado en una forma lineal, mientras que el formulario de datos se construye, ya que esta es la manera de espera de servidor de valores. Así, escribí una pequeña función recursiva que se traduce en el JSON que es como este:

    {
       "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"
       }
    }

    Algo como esto:

    {
       "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"
    }

    El servidor aceptará los datos del formulario que está en este formato convertido.

    Aquí es la función:

    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;
    }

    Invocación:

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

    Estoy usando testJSON sólo para ver la convierte resultados, ya que yo no sería capaz de extraer el contenido de form_data. AJAX post de llamada:

            $.ajax({
                type: "POST",
                url: somePostURL,
                data: form_data,
                processData : false,
                contentType : false,
                success: function (data) {
                },
                error: function (e) {
                }
            });
    • Hola Raj, ¿cómo acerca de las matrices? Dicen que tiene más de 1 direcciones de facturación. ¿Cómo podría arreglar eso?
    • He encontrado la respuesta! Tu post es muy útil. Gracias!
  5. 7

    Las otras respuestas son incompletas para mí. Empecé desde @Vladimir Novopashin respuesta y modificado. Aquí están las cosas que necesitaba y el bug que he encontrado:

    • De apoyo para el archivo de
    • De apoyo para la matriz
    • Error: el Archivo dentro de complejo objeto que se necesita para ser añadido con .prop en lugar de [prop]. Por ejemplo, formData.append('photos[0][file]', file) no funciona en google chrome, mientras que
      formData.append('photos[0].file', file) trabajado
    • Ignorar algunas de sus propiedades, en mi objeto

    El siguiente código debería funcionar en IE11 y de hoja perenne de los navegadores.

    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;
    }
    • La única respuesta de apoyo de las matrices, objetos y archivos.
    • Hola, ¿por qué añadir el Archivo a la raíz? Es posible añadir a hijo?
    • Podría ser un malentendido, pero el método es recursivo así que, incluso si está escrito formData.append(root, data), no significa que se añade a la raíz.
    • Entiendo tu respuesta, por extraño que cuando me sale el resultado en el servidor, tengo una Colección única de los Archivos y de los datos. Pero puedo ver en un Archivo, el nombre da la información a la que el niño es conectado. Tal vez el problema .Net Core y cómo gestionar la carga de archivos. Gracias por tu respuesta.
  6. 3

    Lo siento, para una tarde en contestar, pero he tenido problemas con este Angular 2 actualmente no soporta la carga de archivos. Así, la manera de hacerlo fue el envío de un XMLHttpRequest con FormData. Así, he creado una función para hacerlo. Estoy usando Manuscrito. Para convertir a Javascript acaba de quitar los tipos de datos de la declaración.

    /**
    * 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);
    }
    }
    • Usted debe incluir la matriz de índices en lugar de un [] de propiedades de un objeto dentro de un array numérico para mantener intactas
  7. 2

    Trate de JSON.stringify función de la siguiente

    var postData = JSON.stringify(item);
    var formData = new FormData();
    formData.append("postData",postData );
    • Esta es la mejor manera de lograr esto.
    • su anexar el json que después de varias veces de error de depuración
    • No funciona con el Archivo y la Fecha de objetos.
  8. 1

    Manuscrito de la versión:

    static convertModelToFormData(model: any, form: FormData = null, namespace = ''): FormData {
    let formData = form || new FormData();
    for (let propertyName in model) {
    if (!model.hasOwnProperty(propertyName) || model[propertyName] == undefined) continue;
    let formKey = namespace ? `${namespace}[${propertyName}]` : propertyName;
    if (model[propertyName] instanceof Date) {        
    formData.append(formKey, this.dateTimeToString(model[propertyName]));
    }
    else if (model[propertyName] instanceof Array) {
    model[propertyName].forEach((element, index) => {
    if (typeof element != 'object')
    formData.append(`${formKey}[]`, element);
    else {
    const tempFormKey = `${formKey}[${index}]`;
    this.convertModelToFormData(element, formData, tempFormKey);
    }
    });
    }
    else if (typeof model[propertyName] === 'object' && !(model[propertyName] instanceof File)) {        
    this.convertModelToFormData(model[propertyName], formData, formKey);
    }
    else {        
    formData.append(formKey, model[propertyName].toString());
    }
    }
    return formData;
    }

    https://gist.github.com/Mds92/091828ea857cc556db2ca0f991fee9f6

  9. 0

    Este método de convertir un JS objeto a un objeto FormData :

    JS:

    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());
    }

Dejar respuesta

Please enter your comment!
Please enter your name here