Jak wysłać JSON zamiast ciągu zapytania z $ .ajax?

172

Czy ktoś może w prosty sposób wyjaśnić, jak sprawić, by jQuery wysyłał rzeczywisty JSON zamiast ciągu zapytania?

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

W rzeczywistości spowoduje to konwersję starannie przygotowanego kodu JSON na ciąg zapytania. Jedną z denerwujących rzeczy jest to, że każdy obiekt array: []w twoim obiekcie zostanie przekonwertowany array[]: [], prawdopodobnie z powodu ograniczeń żądań zapytania.

Redsandro
źródło
7
Nie dataTypema to wpływu na sposób przesyłania danych. Określa jedynie, jakiego typu dane mają być zwrócone przez wywołanie. Jeśli chcesz wskazać serwerowi, jaki typ danych określasz we datawłaściwości, musisz ustawić contentTypewłaściwość podobnie jakcontentType: "application/json"
Nie.
Dzięki za wytłumaczenie. Ale w takim przypadku dlaczego muszę określać typ odpowiedzi po stronie klienta, jeśli serwer dostarcza w odpowiedzi nagłówek typu treści?
Redsandro
2
Nie musisz tego określać, domyślnie jQuery spróbuje inteligentnie zgadnąć na podstawie typu MIME odpowiedzi. Jednak określając go, wyraźnie mówisz jQuery, jakiego typu oczekujesz od serwera, a jQuery spróbuje przekonwertować odpowiedź na obiekt tego typu. Brak określenia tego i pozostawienie jQuery zgadywania może spowodować, że jQuery przekonwertuje odpowiedź na nieoczekiwany format, nawet jeśli wysłałeś JSON z serwera. Sprawdź dokumentację, aby uzyskać więcej informacji na temat typu dataType: api.jquery.com/jQuery.ajax
Nie,

Odpowiedzi:

256

Musisz JSON.stringifynajpierw serializować obiekt do formatu JSON, a następnie określić, contentTypeaby serwer zrozumiał, że to JSON. To powinno załatwić sprawę:

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

Należy pamiętać, że JSONobiekt jest natywnie dostępny w przeglądarkach obsługujących JavaScript 1.7 / ECMAScript 5 lub nowszy. Jeśli potrzebujesz starszej obsługi, możesz użyć json2 .

mekwall
źródło
14
To nie zadziała, brakuje ci contentType: 'application/json'.
Ohgodwhy
@Ohgodwhy Oh yeah.
Poszło
1
Dzięki. Myślałem, że dataType się tym zajął, ale zrozumiałem to wstecz. Jakieś przemyślenia na temat określania zestawu znaków w typie treści, tak jak zrobił to Bergi w drugiej odpowiedzi?
Redsandro
5
@Redsandro To nie powinno być konieczne. Według dokumentów jQuery:POST data will always be transmitted to the server using UTF-8 charset, per the W3C XMLHTTPRequest standard
mekwall
1
@ shorif2000 lepiej późno niż wcale ... Problem polega na tym, że w $_POSTphp widać tylko application/x-www-form-urlencoded, że jeśli chcesz odczytać dane json, musisz to zrobić file_get_contents("php://input")i być może wtedy ajson_decode()
santiago arizti
28

Nie, dataTypeopcja służy do analizowania odebranych danych.

Aby opublikować kod JSON, musisz samodzielnie go zdefiniować za pośrednictwem JSON.stringifyi ustawićprocessData opcję na false.

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

Zwróć uwagę, że nie wszystkie przeglądarki obsługują ten JSONobiekt i chociaż jQuery to obsługuje .parseJSON, nie zawiera on stringifier; będziesz potrzebować innej biblioteki polyfill.

Bergi
źródło
4
Ustawienie processDatana falsenie jest konieczne, ponieważ JSON.stringifyjuż zwraca ciąg.
mekwall
@MarcusEkwall: Afaik to nadal by było encodeURIComponented, prawda?
Bergi
OK, może nie być potrzebne, ale czy naprawdę myślisz, że spowodowałoby to niepowodzenie żądania?
Bergi
Nie powinno to sprawić, że się nie powiedzie, biorąc pod uwagę, że to już ciąg.
Kevin B
1
@Redsandro: Tak, robi "inteligentne przypuszczenie". Jednak powodem tego parametru nie jest (tylko) to, że ludzie chcą, aby był on ścisły, ale bardziej, że nie ustawiają odpowiednich typów MIME w swoich odpowiedziach serwera.
Bergi
5

Chociaż wiem, że wiele architektur, takich jak ASP.NET MVC, ma wbudowaną funkcjonalność do obsługi JSON.stringify jako contentType, moja sytuacja jest trochę inna, więc może to może pomóc komuś w przyszłości. Wiem, że zaoszczędziłoby mi to godziny!

Ponieważ moje żądania http są obsługiwane przez interfejs API CGI z IBM (środowisko AS400) w innej subdomenie, żądania te są pochodzenia krzyżowego, stąd plik jsonp. Właściwie wysyłam mój Ajax za pośrednictwem obiektów javascript. Oto przykład mojego POST Ajax:

 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
źródło
2
Dziękujemy za dodanie większej wiedzy do tego pytania! Satysfakcjonująca odpowiedź została już udzielona, ​​ale zagłosowałem za twoją.
Redsandro
1

Jeśli odsyłasz to z powrotem do asp.net i potrzebujesz danych w request.form [], musisz ustawić typ zawartości na „application / x-www-form-urlencoded; charset = utf-8”

Oryginalny post tutaj

Po drugie, pozbądź się typu danych, jeśli nie spodziewasz się powrotu, POST będzie czekał około 4 minuty, zanim zakończy się niepowodzeniem. Zobacz tutaj

Tod
źródło