Como enviar JSON em vez de uma string de consulta com $ .ajax?

172

Alguém pode explicar de uma maneira fácil como fazer o jQuery enviar JSON real em vez de uma string de consulta?

$.ajax({
    url      : url,
    dataType : 'json', // I was pretty sure this would do the trick
    data     : data,
    type     : 'POST',
    complete : callback // etc
});

De fato, isso converterá seu JSON cuidadosamente preparado em uma string de consulta. Uma das coisas irritantes é que qualquer um array: []no seu objeto será convertido array[]: [], provavelmente por causa das limitações da picada da consulta.

Redsandro
fonte
7
O dataTypenão tem influência sobre como os dados são enviados. Apenas especifica que tipo de dados você espera que retorne pela chamada. Se você deseja indicar ao servidor qual é o tipo de dados que você está especificando na datapropriedade, você precisa configurá-la contentTypesemelhante acontentType: "application/json"
Não,
Obrigado por esclarecer. Mas, nesse caso, por que preciso especificar o tipo de resposta do lado do cliente se o servidor está fornecendo um cabeçalho de tipo de conteúdo na resposta?
Redsandro
2
Você não precisa especificá-lo; por padrão, o jQuery tentará adivinhar com base no tipo MIME da resposta. Entretanto, ao especificá-lo, você está dizendo explicitamente ao jQuery que tipo de servidor você espera e o jQuery tentará converter a resposta em um objeto desse tipo. Não especificar e deixar o jQuery adivinhar pode resultar na conversão do jQuery para um formato inesperado, mesmo que você tenha enviado o JSON do servidor. Verifique a documentação para obter mais detalhes sobre o dataType: api.jquery.com/jQuery.ajax
Nope
Possível duplicata do Jquery Ajax Postando json para webservice
Madura Pradeep

Respostas:

256

Você precisa usar JSON.stringifypara serializar seu objeto primeiro para JSON e, em seguida, especificar o contentTypepara que seu servidor entenda que é JSON. Isso deve fazer o truque:

$.ajax({
    url: url,
    type: "POST",
    data: JSON.stringify(data),
    contentType: "application/json",
    complete: callback
});

Observe que o JSONobjeto está disponível nativamente em navegadores que suportam JavaScript 1.7 / ECMAScript 5 ou posterior. Se você precisar de suporte legado, poderá usar o json2 .

mekwall
fonte
14
Isso não vai funcionar, você está desaparecido contentType: 'application/json'.
precisa saber é o seguinte
@Ohgodwhy Oh yeah. Isso foi um pouco rápido demais;)
mekwall 2/12/12
1
Obrigado. Eu pensei que o dataType resolvesse isso, mas entendi isso de trás para a frente. Alguma opinião sobre a especificação de charset no tipo de conteúdo, como Bergi fez na outra resposta?
Redsandro 2/10/12
5
@Redsandro Isso não deve ser necessário. De acordo com a documentação do jQuery:POST data will always be transmitted to the server using UTF-8 charset, per the W3C XMLHTTPRequest standard
mekwall 3/12/12
1
@ shorif2000 melhor tarde do que nunca ... o problema é que, em $_POSTno php você só pode ver application/x-www-form-urlencoded, se você quiser ler json dados que você deve fazer file_get_contents("php://input")e, talvez, em seguida, umjson_decode()
santiago Arizti
28

Não, a dataTypeopção é para analisar os dados recebidos.

Para postar JSON, você precisará stringify-lo sozinho via JSON.stringifye definir a processDataopção de false.

$.ajax({
    url: url,
    type: "POST",
    data: JSON.stringify(data),
    processData: false,
    contentType: "application/json; charset=UTF-8",
    complete: callback
});

Observe que nem todos os navegadores suportam o JSONobjeto e, embora o jQuery o tenha .parseJSON, ele não possui um stringificador incluído; você precisará de outra biblioteca de polyfill.

Bergi
fonte
4
Definir processDatacomo falsenão é necessário, pois JSON.stringifyjá retorna uma sequência.
mekwall
@MarcusEkwall: Afaik ainda seria encodeURIComponenteditado, não seria?
Bergi 2/10/12
OK, pode não ser necessário, mas você realmente acha que isso faria a solicitação falhar?
Bergi 2/10/12
Não deve fazê-lo falhar, considerando que já é uma string.
Kevin B
1
@Redsandro: Sim, está fazendo um "palpite inteligente". No entanto, o motivo do parâmetro não é (apenas) que as pessoas desejam torná-lo rigoroso, mas mais que eles não definem tipos MIME apropriados nas respostas do servidor.
Bergi 2/10/12
5

Embora eu conheça muitas arquiteturas, como o ASP.NET MVC, têm funcionalidade incorporada para lidar com JSON.stringify como o contentType, minha situação é um pouco diferente; talvez isso possa ajudar alguém no futuro. Eu sei que teria me poupado horas!

Como minhas solicitações http estão sendo tratadas por uma API CGI da IBM (ambiente AS400) em um subdomínio diferente, essas solicitações são de origem cruzada, daí o jsonp. Na verdade, eu envio meu ajax via objeto (s) javascript. Aqui está um exemplo do meu ajax POST:

 var data = {USER : localProfile,  
        INSTANCE : "HTHACKNEY",  
        PAGE : $('select[name="PAGE"]').val(), 
        TITLE : $("input[name='TITLE']").val(), 
        HTML : html,
        STARTDATE : $("input[name='STARTDATE']").val(), 
        ENDDATE : $("input[name='ENDDATE']").val(),
        ARCHIVE : $("input[name='ARCHIVE']").val(), 
        ACTIVE : $("input[name='ACTIVE']").val(), 
        URGENT : $("input[name='URGENT']").val(), 
        AUTHLST :  authStr};
        //console.log(data);
       $.ajax({
            type: "POST",
           url:   "http://www.domian.com/webservicepgm?callback=?",
           data:  data,
           dataType:'jsonp'
       }).
       done(function(data){
         //handle data.WHATEVER
       });
yardpenalty.com
fonte
2
Obrigado por adicionar mais conhecimento a esta pergunta! A resposta satisfatória já havia sido dada, mas eu votei na sua.
Redsandro 4/09/16
1

Se você estiver enviando isso de volta para o asp.net e precisar dos dados em request.form [], será necessário definir o tipo de conteúdo como "application / x-www-form-urlencoded; charset = utf-8"

Postagem original aqui

Em segundo lugar, livre-se do tipo de dados, se você não espera um retorno, o POST aguardará cerca de 4 minutos antes de falhar. Veja aqui

Tod
fonte