Cada vez que quiero PUBLICAR una matriz de objetos JSON con jQuery to Rails, tengo este problema. Si clasifico la matriz, puedo ver que jQuery está haciendo su trabajo correctamente:
"shared_items"=>"[{\"entity_id\":\"253\",\"position\":1},{\"entity_id\":\"823\",\"position\":2}]"
Pero si solo envío la matriz como los datos de la llamada AJAX, obtengo:
"shared_items"=>{"0"=>{"entity_id"=>"253", "position"=>"1"}, "1"=>{"entity_id"=>"823", "position"=>"2"}}
Mientras que si solo envío una matriz simple, funciona:
"shared_items"=>["entity_253"]
¿Por qué Rails está cambiando la matriz a ese extraño hash? La única razón por la que me viene a la mente es que Rails no puede entender correctamente el contenido porque no hay ningún tipo aquí (¿hay alguna forma de configurarlo en la llamada de jQuery?):
Processing by SharedListsController#create as
¡Gracias!
Actualización:
estoy enviando los datos como una matriz, no una cadena, y la matriz se crea dinámicamente usando la .push()
función. Probado con $.post
y $.ajax
, mismo resultado.
Content-Type
de la solicitud enapplication/json
, sino que estaba enviando los datos como lo haría un formulario html. Es difícil pensar tan lejos. Rails funcionaba bien, después de queContent-Type
se estableció el valor correcto y los datos que se enviaban eran JSON válidos.contentType: 'application/json'
Pregunta un poco vieja, pero luché con esto yo mismo hoy, y aquí está la respuesta que se me ocurrió: creo que esto es un poco culpa de jQuery, pero que solo está haciendo lo que es natural para él. Sin embargo, tengo una solución.
Dada la siguiente llamada ajax de jQuery:
Los valores que publicará jQuery se verán así (si miras la Solicitud en tu Firebug-of-choice) te darán datos de formulario que se parecen a:
Si CGI.unencode obtendrá
Creo que esto se debe a que jQuery piensa que esas claves en su JSON son nombres de elementos de formulario, y que debería tratarlas como si tuviera un campo llamado "usuario [nombre]".
Entonces entran en su aplicación Rails, Rails ve los corchetes y construye un hash para contener la clave más interna del nombre del campo (el "1" que jQuery agregó "amablemente").
De todos modos, evité este comportamiento construyendo mi llamada ajax de la siguiente manera;
Lo que obliga a jQuery a pensar que este JSON es un valor que desea pasar, por completo, y no un objeto Javascript que debe tomar y convertir todas las claves en nombres de campo de formulario.
Sin embargo, eso significa que las cosas son un poco diferentes en el lado de Rails, porque necesitas decodificar explícitamente el JSON en params [: data].
Pero eso esta bien:
TL; DR: Entonces, la solución es: en el parámetro de datos de su llamada jQuery.ajax (), hágalo
{"data": JSON.stringify(my_object) }
explícitamente, en lugar de alimentar la matriz JSON en jQuery (donde adivina erróneamente lo que quiere hacer con ella.fuente
Me acabo de encontrar con este problema con Rails 4. Para responder explícitamente a su pregunta ("¿Por qué Rails cambia la matriz a ese hash extraño?"), Consulte la sección 4.1 de la guía Rails sobre controladores de acción :
El problema es que jQuery formatea la solicitud con índices de matriz explícitos, en lugar de corchetes vacíos. Entonces, por ejemplo, en lugar de enviar
shared_items[]=1&shared_items[]=2
, envíashared_items[0]=1&shared_items[1]=2
. Carriles ve los índices de matriz e interpreta como claves hash en lugar de índices de matriz, convirtiendo la solicitud en un hash Rubí raro:{ shared_items: { '0' => '1', '1' => '2' } }
.Si no tiene el control del cliente, puede solucionar este problema en el lado del servidor convirtiendo el hash en una matriz. Así es como lo hice:
fuente
El siguiente método podría ser útil si usa parámetros fuertes
fuente
¿Ha considerado hacerlo
parsed_json = ActiveSupport::JSON.decode(your_json_string)
? Si está enviando cosas al revés, puede usarlo.to_json
para serializar los datos.fuente
¿Está tratando de convertir la cadena JSON en una acción de controlador Rails?
No estoy seguro de qué está haciendo Rails con el hash, pero puede solucionar el problema y tener más suerte creando un objeto Javascript / JSON (en lugar de una cadena JSON) y enviándolo como parámetro de datos para su Ajax. llamada.
Si quisiera enviar esto a través de ajax, entonces haría algo como esto:
Tenga en cuenta que con el fragmento de ajax anterior, jQuery hará una suposición inteligente sobre el tipo de datos, aunque generalmente es bueno especificarlo explícitamente.
De cualquier manera, en la acción de su controlador, puede obtener el objeto JSON que pasó con el hash params, es decir
Por ejemplo, esta acción le escupirá su objeto json:
fuente
Utilice la gema rack-jquery-params (descargo de responsabilidad: soy el autor). Soluciona el problema de que las matrices se conviertan en hashes con claves enteras.
fuente