jQuery-如何使$ .post()使用contentType = application / json?


308

我注意到在jquery中使用$ .post()时,默认contentType为application / x-www-form-urlencoded-当我的ASP.NET MVC代码需要具有contentType = application / json时

(有关为什么我必须使用application / json的信息,请参见此问题:ASPNET MVC-当该字段具有值时,为什么ModelState.IsValid为false“ x字段是必需的”?

如何使$ .post()发送contentType = application / json?我已经有大量的$ .post()函数,所以我不想更改为$ .ajax(),因为这会花费太多时间

如果我尝试

$.post(url, data, function(), "json") 

它仍然具有contentType = application / x-www-form-urlencoded。那么,如果没有将contenttype更改为json,“ json”参数到底会做什么?

如果我尝试

$.ajaxSetup({
  contentType: "application/json; charset=utf-8"
});

那行得通,但会影响我拥有的每个$ .get和$ .post并导致某些中断。

因此,有什么方法可以更改$ .post()的行为以发送contentType = application / json?

Answers:


70

我想你可能不得不

1.修改源以使$ .post始终使用JSON数据类型,因为它实际上只是预配置$.ajax调用的快捷方式

要么

2. 定义您自己的实用程序功能,该功能是$.ajax您要使用的配置的快捷方式

要么

3. $.post function您可以通过猴子补丁使用自己的实现覆盖。

您的示例中的JSON数据类型是指服务器返回的数据类型而不是发送给服务器的格式。


5
+1,我将去定义一个新方法或覆盖jQuery.post方法,这是一个非常简单的功能 ……
CMS 2010年

3
这不是一个坏主意,只需创建一个名为$ .mvcpost()的方法,该方法与$ .post相同(通过复制链接的代码),并更改contenttype。然后,对于所有需要更改的$ .post(),我只需要在前面键入3个额外的字符。它比将它们重写为$ .ajax()快得多。
JK。

9
@PavelRepin,我必须在有效负载上调用JSON.stringify()。
Ustaman Sangat'4

2
@dragon-这是3种解决方案:“是否可以通过某种方式更改$ .post()的行为来发送contentType = application / json?”。哪一部分不是答案?
Russ Cam

2
知道这一点也很重要:$ .ajax及其各种方法将尝试根据您提供的数据来猜测contentType应该是什么(除非指定了该内容)。"mystring data"将成为application/x-www-form-urlencoded;对象的{ anyKey: "anyvalue and type" }位置application/json。许多读取json的服务器将只允许一个对象或数组,而不允许一个字符串-因此jquery以此方式预测事物。如果您的服务器读取字符串,数字等而没有包装在对象中,则必须像在此答案中那样指定内容类型。
bzuillsmith 2014年

395
$.ajax({
  url:url,
  type:"POST",
  data:data,
  contentType:"application/json; charset=utf-8",
  dataType:"json",
  success: function(){
    ...
  }
})

参见:jQuery.ajax()


13
原始帖子问:“因此,有什么方法可以更改$ .post()的行为来发送contentType = application / json?” 但它也指出“这可行,但会影响我拥有的每个$ .get和$ .post并导致某些中断。” 我将问题理解为“如何实现与使用$ .post相同的功能,但发送正确的contentType而又不破坏$ .get和$ .post的其他情况”。那不对吗?
阿德里安

5
@ x1a4显然不了解.ajax是呼叫,而不是ajaxSetup
Walker

39
@Adrien,两年之后的价值是,当我用谷歌搜索时,我一直在寻找答案。
AwesomeTown 2012年

74
必须使用JSON.stringify(data),因为服务器需要一个JSON字符串,而jQuery会简单地使用与&字符连接键-值对,并使用形式化代码。

3
即使是四年之后,这个答案也用不到十行代码解决了我的搜索工作。
Pieter VDE

86

最终,我找到了适合我的解决方案:

jQuery.ajax ({
    url: myurl,
    type: "POST",
    data: JSON.stringify({data:"test"}),
    dataType: "json",
    contentType: "application/json; charset=utf-8",
    success: function(){
        //
    }
});

8
无法弄清楚为什么我总是出错,事实证明您必须对数据进行字符串化处理。
FriendlyGuy

5
我知道这可行,但是为什么需要为什么要进行分类?它是jQuery的错误吗?将data参数序列化为似乎很高兴x-www-form-urlencoded,但是如果您指示请求内容类型为JSON,它仍然坚持data以不匹配的格式发送。
帕维尔·列宾

好。我没有太多地挖掘它。我很高兴它正在工作。;)我的服务器需要JSON。
vvkatwss vvkatwss 2012年

同样在这里。没有JSON.stringify,它将无法正常工作,我想知道为什么。
约翰·西蒙斯

42

我最终在脚本中向jQuery添加了以下方法:

jQuery["postJSON"] = function( url, data, callback ) {
    // shift arguments if data argument was omitted
    if ( jQuery.isFunction( data ) ) {
        callback = data;
        data = undefined;
    }

    return jQuery.ajax({
        url: url,
        type: "POST",
        contentType:"application/json; charset=utf-8",
        dataType: "json",
        data: data,
        success: callback
    });
};

并使用它

$.postJSON('http://url', {data: 'goes', here: 'yey'}, function (data, status, xhr) {
    alert('Nailed it!')
});

这是通过简单地从原始JQuery源复制“ get”和“ post”的代码并硬编码一些参数以强制执行JSON POST来完成的。

谢谢!


2
像往常一样-最好的答案是最后一次聚会,并且投票最少;(
nikib3ro 2014年

好的答案-花费一段时间才能意识到$ .post不会“开箱即用”。
markp3rry 2014年

21

仅使用

jQuery.ajax ({
    url: myurl,
    type: "POST",
    data: mydata,
    dataType: "json",
    contentType: "application/json; charset=utf-8",
    success: function(){
        //
    }
});

@JK 更新:如果您在问题中仅使用$ .post 编写一个代码示例,则在答案中将找到一个相应的示例。我不想重复您已经研究过的相同信息,直到知道:$ .post和$ .get是$ .ajax的缩写形式。因此,只需使用$ .ajax,您就可以使用其完整的参数集,而不必更改任何全局设置。

顺便说一句,我不建议覆盖标准的$ .post。这是我的个人看法,但对我来说很重要,不仅该程序可以运行,而且所有阅读您的程序的人都以相同的方式理解它。在没有非常重要的原因的情况下覆盖标准方法可能会导致在读取程序代码时产生误解。所以,我重申我的建议更多的时间:只要使用原来的$就形成jQuery的,而不是jQuery.getjQuery.post你接收节目,不仅完美地工作,但可以通过人没有任何误解读取。


1
很棒的解释和指导方针
Ved Prakash

8

您可以作为post()的最后一个参数传递的“ json”数据类型表示该函数在服务器响应中期望的数据类型,而不是请求中发送的数据类型。具体来说,它设置“ Accept”标头。

老实说,最好的选择是切换到ajax()调用。post()函数是为了方便起见;当您只进行简单的表单发布时,可以使用ajax()调用的简化版本。你不是

如果您真的不想切换,则可以创建自己的函数,例如xpost(),并使其简单地将给定参数转换为jQuery ajax()调用的参数,并设置内容类型。这样,您不必将所有这些post()函数重写为ajax()函数,而只需将它们全部从post更改为xpost(或其他)即可。


只需调用需要更改的$ .post()方法即可调用asp.net mvc控制器方法。纯jquery的应该不变(自动完成,diaplog,jqgrid等),我希望对相关的$ .post()可以做一个简单的更改。但看起来确实需要将它们转换为$ .ajax()。它的应用程序庞大而笨拙,因此有很多需要更改的地方。
JK。

5

我知道这是一个较晚的答案,实际上我有一个快捷方式,可用于在基于MS的服务中进行发布/读取操作。它可与MVC以及ASMX等一起使用。

采用:

$.msajax(
  '/services/someservice.asmx/SomeMethod'
  ,{}  /*empty object for nothing, or object to send as Application/JSON */
  ,function(data,jqXHR) {
    //use the data from the response.
  }
  ,function(err,jqXHR) {
    //additional error handling.
  }
);
//sends a json request to an ASMX or WCF service configured to reply to JSON requests.
(function ($) {
  var tries = 0; //IE9 seems to error out the first ajax call sometimes... will retry up to 5 times

  $.msajax = function (url, data, onSuccess, onError) {
    return $.ajax({
      'type': "POST"
      , 'url': url
      , 'contentType': "application/json"
      , 'dataType': "json"
      , 'data': typeof data == "string" ? data : JSON.stringify(data || {})
      ,beforeSend: function(jqXHR) {
        jqXHR.setRequestHeader("X-MicrosoftAjax","Delta=true");
      }
      , 'complete': function(jqXHR, textStatus) {
        handleResponse(jqXHR, textStatus, onSuccess, onError, function(){
          setTimeout(function(){
            $.msajax(url, data, onSuccess, onError);
          }, 100 * tries); //try again
        });
      }
    });
  }

  $.msajax.defaultErrorMessage = "Error retreiving data.";


  function logError(err, errorHandler, jqXHR) {
    tries = 0; //reset counter - handling error response

    //normalize error message
    if (typeof err == "string") err = { 'Message': err };

    if (console && console.debug && console.dir) {
      console.debug("ERROR processing jQuery.msajax request.");
      console.dir({ 'details': { 'error': err, 'jqXHR':jqXHR } });
    }

    try {
      errorHandler(err, jqXHR);
    } catch (e) {}
    return;
  }


  function handleResponse(jqXHR, textStatus, onSuccess, onError, onRetry) {
    var ret = null;
    var reterr = null;
    try {
      //error from jqXHR
      if (textStatus == "error") {
        var errmsg = $.msajax.defaultErrorMessage || "Error retreiving data.";

        //check for error response from the server
        if (jqXHR.status >= 300 && jqXHR.status < 600) {
          return logError( jqXHR.statusText || msg, onError, jqXHR);
        }

        if (tries++ < 5) return onRetry();

        return logError( msg, onError, jqXHR);
      }

      //not an error response, reset try counter
      tries = 0;

      //check for a redirect from server (usually authentication token expiration).
      if (jqXHR.responseText.indexOf("|pageRedirect||") > 0) {
        location.href = decodeURIComponent(jqXHR.responseText.split("|pageRedirect||")[1].split("|")[0]).split('?')[0];
        return;
      }

      //parse response using ajax enabled parser (if available)
      ret = ((JSON && JSON.parseAjax) || $.parseJSON)(jqXHR.responseText);

      //invalid response
      if (!ret) throw jqXHR.responseText;  

      // d property wrap as of .Net 3.5
      if (ret.d) ret = ret.d;

      //has an error
      reterr = (ret && (ret.error || ret.Error)) || null; //specifically returned an "error"

      if (ret && ret.ExceptionType) { //Microsoft Webservice Exception Response
        reterr = ret
      }

    } catch (err) {
      reterr = {
        'Message': $.msajax.defaultErrorMessage || "Error retreiving data."
        ,'debug': err
      }
    }

    //perform final logic outside try/catch, was catching error in onSuccess/onError callbacks
    if (reterr) {
      logError(reterr, onError, jqXHR);
      return;
    }

    onSuccess(ret, jqXHR);
  }

} (jQuery));

注意:我也有一个从json.org的JS文件修改而来的JSON.parseAjax方法,该方法增加了对MS“ /Date(...)/”日期的处理...

不包括经过修改的json2.js文件,在IE8的情况下,它使用基于脚本的解析器,因为在某些情况下,当扩展数组和/或对象的原型等时本机解析器会中断。

我一直在考虑修改此代码以实现promises接口,但对我来说真的很好。


5

$ .postJSON()的简单jquery API扩展(来自:https : //benjamin-schweizer.de/jquerypostjson.html)可以解决问题。您可以像其他所有本机jquery Ajax调用一样使用postJSON()。您可以附加事件处理程序等。

$.postJSON = function(url, data, callback) {
  return jQuery.ajax({
    'type': 'POST',
    'url': url,
    'contentType': 'application/json; charset=utf-8',
    'data': JSON.stringify(data),
    'dataType': 'json',
    'success': callback
  });
};

像其他Ajax API(例如来自AngularJS的$ http)一样,它将正确的contentType设置为application / json。您可以直接传递json数据(javascript对象),因为它在这里被字符串化了。预期返回的dataType设置为JSON。您可以将jQuery的默认事件处理程序附加到promise,例如:

$.postJSON(apiURL, jsonData)
 .fail(function(res) {
   console.error(res.responseText);
 })
 .always(function() {
   console.log("FINISHED ajax post, hide the loading throbber");
 });

4

问题的核心是,在撰写本文时,JQuery在getJSON存在且没有做正确的事情的情况下没有postJSON方法。

postJSON方法将执行以下操作:

postJSON = function(url,data){
    return $.ajax({url:url,data:JSON.stringify(data),type:'POST', contentType:'application/json'});
};

可以这样使用:

postJSON( 'path/to/server', my_JS_Object_or_Array )
    .done(function (data) {
        //do something useful with server returned data
        console.log(data);
    })
    .fail(function (response, status) {
        //handle error response
    })
    .always(function(){  
      //do something useful in either case
      //like remove the spinner
    });

1

当前文档显示,从3.0开始,$ .post将接受设置对象,这意味着您可以使用$ .ajax选项。3.0尚未发布,关于提交,他们正在谈论将其引用隐藏在文档中,但将来会寻找它!


1

以下JavaScript代码存在类似的问题:

var url = 'http://my-host-name.com/api/Rating';

var rating = { 
  value: 5,
  maxValue: 10
};

$.post(url, JSON.stringify(rating), showSavedNotification);

我可以在提琴手中看到请求的地方:

  • 标头: Content-Type: application/x-www-form-urlencoded; charset=UTF-8
  • 身体: {"value":"5","maxValue":"5"}

结果,我的服务器无法将对象映射到服务器端类型。

将最后一行更改为这一行后:

$.post(url, rating, showSavedNotification);

在提琴手中,我仍然可以看到:

  • 标头: Content-Type: application/x-www-form-urlencoded; charset=UTF-8
  • 身体: value=5&maxValue=10

但是,服务器开始返回我所期望的。


0

你自己的适配器/包装怎么样?

//adapter.js
var adapter = (function() {

return {

    post: function (url, params) {
        adapter.ajax(url, "post", params);
        },
    get: function (url, params) {
        adapter.ajax(url, "get", params);
    },
    put: function (url, params) {
        adapter.ajax(url, "put", params);
    },
    delete: function (url, params) {
        adapter.ajax(url, "delete", params);
    },
    ajax: function (url, type, params) {
        var ajaxOptions = {
            type: type.toUpperCase(),
            url: url,
            success: function (data, status) {
                var msgType = "";
                // checkStatus here if you haven't include data.success = true in your
                // response object
                if ((params.checkStatus && status) || 
                   (data.success && data.success == true)) {
                            msgType = "success";
                            params.onSuccess && params.onSuccess(data);
                    } else {
                            msgType = "danger";
                            params.onError && params.onError(data);
                    }
            },
            error: function (xhr) {
                    params.onXHRError && params.onXHRError();
                    //api.showNotificationWindow(xhr.statusText, "danger");
            }
        };
        if (params.data) ajaxOptions.data = params.data;
        if (api.isJSON(params.data)) {
            ajaxOptions.contentType = "application/json; charset=utf-8";
            ajaxOptions.dataType = "json";
        }
        $.ajax($.extend(ajaxOptions, params.options));
    }
})();

    //api.js
var api = {
  return {
    isJSON: function (json) {
        try {
            var o = JSON.parse(json);
            if (o && typeof o === "object" && o !== null) return true;
        } catch (e) {}
        return false;
    }
  }
})();

极其简单的用法:

adapter.post("where/to/go", {
    data: JSON.stringify(params),
    onSuccess: function (data) {
        //on success response...
    }
    //, onError: function(data) {  //on error response... }
    //, onXHRError: function(xhr) {  //on XHR error response... }
});

尝试过但仍未获得预期结果。我有Spring Boot Rest API。
Suraj Shingade '18 -4-3

0

由于某种原因,在我的情况下,在ajax请求上将内容类型设置为@Adrien建议无效。但是,实际上,您可以通过在执行以下操作之前使用$ .post更改内容类型:

$.ajaxSetup({
    'beforeSend' : function(xhr) {
        xhr.overrideMimeType('application/json; charset=utf-8');
    },
});

然后$.post拨打电话:

$.post(url, data, function(), "json")

我在使用jQuery + IIS时遇到了麻烦,这是帮助jQuery理解对Ajax请求使用Windows-1252编码的唯一解决方案。


0

我们可以在$ .post中更改Content-type

$ .post(URL,data,function(data,status,xhr){xhr.setRequestHeader(“ Content-type”,“ application / x-www-form-urlencoded; charset = utf-8”);});;


-1

如果您遇到CORS(跨源资源共享)问题,则$ .post不起作用。尝试使用以下格式的$ .Ajax:“ $ .ajax({url:someurl,contentType:'application / json',data:requestInJSONFormat, headers:{'Access-Control-Allow-Origin':'*'}, dataType:'json',类型:'POST',异步:false,成功:function(Data){...}});“”


-19

您不能application/json直接发送-它必须是GET / POST请求的参数。

所以像

$.post(url, {json: "...json..."}, function());

这个答案可能是错误的,但它的质量不低,它是尝试回答该问题的尝试。从评论
Wai Ha Lee
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.