在Ajax处理中出现"Invalid JSON primitive"错误

111

我在使用jQuery的ajax调用时遇到了错误。

这是我的jQuery函数:

function DeleteItem(RecordId, UId, XmlName, ItemType, UserProfileId) {
    var obj = {
        RecordId: RecordId,
        UserId: UId,
        UserProfileId: UserProfileId,
        ItemType: ItemType,
        FileName: XmlName
    };
    var json = Sys.Serialization.JavaScriptSerializer.serialize(obj);

    $.ajax({
        type: "POST",
        url: "EditUserProfile.aspx/DeleteRecord",
        data: json,
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        async: true,
        cache: false,
        success: function(msg) {
            if (msg.d != null) {
                RefreshData(ItemType, msg.d);
            }
        },
        error: function(XMLHttpRequest, textStatus, errorThrown) {
            alert("error occured during deleting");
        }
    });
}

这是我的WebMethod

[WebMethod]
public static string DeleteRecord(Int64 RecordId, Int64 UserId, Int64 UserProfileId, string ItemType, string FileName) {
    try {
        string FilePath = HttpContext.Current.Server.MapPath(FileName);

        XDocument xmldoc = XDocument.Load(FilePath);
        XElement Xelm = xmldoc.Element("UserProfile");
        XElement parentElement = Xelm.XPathSelectElement(ItemType + "/Fields");

        (from BO in parentElement.Descendants("Record")
         where BO.Element("Id").Attribute("value").Value == RecordId.ToString()
         select BO).Remove();
        XDocument xdoc = XDocument.Parse(Xelm.ToString(), LoadOptions.PreserveWhitespace);
        xdoc.Save(FilePath);

        UserInfoHandler obj = new UserInfoHandler();
        return obj.GetHTML(UserId, UserProfileId, FileName, ItemType, RecordId, Xelm).ToString();
    } catch (Exception ex) {
        HandleException.LogError(ex, "EditUserProfile.aspx", "DeleteRecord");
    }
    return "success";
}

请问有人能告诉我我的代码哪里出了问题吗?

我遇到了这个错误:

{
    "Message":"Invalid JSON primitive: RecordId.",
    "StackTrace":"
       at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializePrimitiveObject()
       at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeInternal(Int32 depth)
       at System.Web.Script.Serialization.JavaScriptObjectDeserializer.BasicDeserialize(String input, Int32 depthLimit, JavaScriptSerializer serializer)
       at System.Web.Script.Serialization.JavaScriptSerializer.Deserialize(JavaScriptSerializer serializer, String input, Type type, Int32 depthLimit)
       at System.Web.Script.Serialization.JavaScriptSerializer.Deserialize[T](String input)
       at System.Web.Script.Services.RestHandler.GetRawParamsFromPostRequest(HttpContext context, JavaScriptSerializer serializer)
       at System.Web.Script.Services.RestHandler.GetRawParams(WebServiceMethodData methodData, HttpContext context)
       at System.Web.Script.Services.RestHandler.ExecuteWebServiceCall(HttpContext context, WebServiceMethodData methodData)",
    "ExceptionType":"System.ArgumentException"
}

我不理解的是,JavaScript 是关于 AddAlbumToMyProfile,而 WebMethod 却被称为 DeleteRecord。你确定你展示给我们的是正确的代码片段吗? - jitter
你能否捕获POST请求的内容(使用Firebug或其他工具),并将其添加到问题中?我不确定是否是在发送数据之前对数据进行编码的方式,但你也可以尝试使用这个(http://www.json.org/json2.js)来序列化它。 - Roman
12个回答

145

仅仅是一个猜测:在执行之后,json变量包含了什么?

var json = Sys.Serialization.JavaScriptSerializer.serialize(obj);?
如果它是一个有效的 JSON 对象,例如 {"foo":"foovalue", "bar":"barvalue"},那么 jQuery 可能不会将其发送为 JSON 数据,而是序列化为 foor=foovalue&bar=barvalue,因此您会收到错误消息:"Invalid JSON primitive: foo"。尝试将数据设置为字符串。
$.ajax({
    ...
    data: '{"foo":"foovalue", "bar":"barvalue"}', //note the additional quotation marks
    ...
})

这样,jQuery就会不修改数据并将字符串发送到服务器,然后ASP.NET可以在服务器端解析JSON。


8
感谢澄清。再补充一句,你可以随时使用 JSON.stringify({foo:'foovalue', bar:'barvalue'}) 来简化生活。 - Elaine
1
虽然有十年的时间差,但仍然相关:这不是有效的JSON。在JSON中,字符串(包括属性名称)必须使用双引号,因此应该是{"foo": "foovalue", "bar": "barvalue"}。使用单引号会导致语法错误。 - Mike 'Pomax' Kamermans

116

使用

data : JSON.stringify(obj)

我相信在上述情况下会起作用。

注意:您应该添加json2.js库,因为不是所有浏览器都支持JSON对象(IE7-)json.js和json2.js的区别


3
谢谢!在使用简单的JS类时,这个方法可以奏效。我把data: { JSON.stringify(obj) }改为了 data: JSON.stringify(obj) (我的Javascript/JSON类样式是这样的:var myObj = { title: "x", subclass = someVar, ... })。 - lko
1
请注意,这是提供的解决方案,如果您实际上需要发送JSON(可能是使用asp.net Web服务),在其他情况下,只需删除contentType,让jQuery传递表单编码数据可能更容易。 - GSerg

22

它正在工作,类似这样的东西。

data: JSON.stringify({'id':x}),

3
这个回答出现在低质量审核队列中,可能是因为您没有对代码进行任何解释。如果该代码回答了问题,请考虑在回答中添加一些解释代码的文字说明。这样,您更有可能获得更多的赞同,并帮助提问者学到新知识。 - lmo
我想传递两个参数:一个复杂对象的数组和一个整数。我这样做:data: {items: JSON.stringify(myarray), myId:value}。 - A.Dara

19
如 jitter 所指出的那样,$.ajax 函数将 data 参数中使用的任何对象/数组序列化为 url 编码格式。奇怪的是,dataType 参数仅适用于来自服务器的响应,而不适用于请求中的任何数据。
在遇到相同问题后,我下载并使用了 jquery-json 插件 来正确编码向 ScriptService 发送的请求数据。然后,使用 $.toJSON 函数来对要发送到服务器的参数进行编码:
$.ajax({
    type: "POST",
    url: "EditUserProfile.aspx/DeleteRecord",
    data: $.toJSON(obj),
    contentType: "application/json; charset=utf-8",
    dataType: "json"
    ....
});

2
感谢指出调用中data参数被忽略了。 - Zephyr was a Friend of Mine
3
这个方法可行,但是如果你的 Javascript 类型是这样的 var myObj = { title: "x", subclass = someVar, ... },把 data: { JSON.stringify(obj) } 改成 data: JSON.stringify(obj) 对我有帮助,因为它解决了数据编码的问题。 - lko

14

jQuery Ajax 默认会将数据作为查询字符串参数形式发送,类似于表单:

RecordId=456&UserId=123

除非设置processData选项为false,否则它将作为对象发送到服务器。

  • contentType选项是告诉服务器客户端发送的数据格式。

  • dataType选项是告诉服务器客户端期望从服务器返回的数据类型。

不要指定contentType,这样服务器将把它们解析为查询字符串参数而不是json。

或者

使用contentType作为'application/json; charset=utf-8'并使用JSON.stringify(对象),以便服务器能够从字符串反序列化json。


6

我想@jitter的猜测是正确的,但他的解决方案对我没有用。

以下是有效的解决方案:

$.ajax({
    ...
    data: "{ intFoo: " + intFoo + " }",
    ...
});

我还没有尝试过,但我认为如果参数是字符串,应该像这样:
$.ajax({
    ...
    data: "{ intFoo: " + intFoo + ", strBar: '" + strBar + "' }",
    ...
});

9
如果我必须像那样编写代码(字符串拼接)来创建 JSON 对象,我会自杀(比喻)。一定有更好的方法。 - PandaWood

4

我曾遇到同样的问题,我找到了一个好的解决方案,如下:

尝试这个...

$.ajax({
    type: "POST",
    url: "EditUserProfile.aspx/DeleteRecord",
    data: '{RecordId: ' + RecordId + ', UserId: ' + UId + ', UserProfileId:' + UserProfileId + ', ItemType: \'' + ItemType + '\', FileName: '\' + XmlName + '\'}',
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    async: true,
    cache: false,
    success: function(msg) {
        if (msg.d != null) {
            RefreshData(ItemType, msg.d);
        }
    },
    error: function(XMLHttpRequest, textStatus, errorThrown) {
        alert("error occured during deleting");
    }
});

请注意,在此字符串类型参数中,我使用了(\)转义序列字符来表示它的字符串值。

数据:"{注释:"" + $('#txtNotes').val()+ ""} - estinamir

2

在这里dataType是“json”,因此,在调用API时,data/reqParam必须以字符串形式提供,可以使用尽可能多的对象,但最后在$.ajax的data中将对象stringify。

             let person= {  name: 'john',
                age: 22
            };

           var personStr = JSON.stringify(person); 

            $.ajax({
                url: "@Url.Action("METHOD", "CONTROLLER")",
                type: "POST",
                data: JSON.stringify( { param1: personStr } ),
                contentType: "application/json;charset=utf-8",
                dataType: "json",
        success: function (response) {

            console.log("Success");

        },
        error: function (error) {
            console.log("error found",error);
        }
    });

或者,

       $.ajax({
                url: "@Url.Action("METHOD", "CONTROLLER")",
                type: "POST",
                data: personStr,
                contentType: "application/json;charset=utf-8",
                dataType: "json",
        success: function (response) {

            console.log("Success");

        },
        error: function (error) {
            console.log("error found",error);
        }
    });

1
如果需要手动格式化JSON,这里有一个非常方便的验证器:jsonlint.com 请使用双引号而不是单引号:

无效:

{
    'project': 'a2ab6ef4-1a8c-40cd-b561-2112b6baffd6',
    'franchise': '110bcca5-cc74-416a-9e2a-f90a8c5f63a0'
}

有效:

{
    "project": "a2ab6ef4-1a8c-40cd-b561-2112b6baffd6",
    "franchise": "18e899f6-dd71-41b7-8c45-5dc0919679ef"
}

0

在服务器上,将json序列化/反序列化为自定义对象:

public static string Serialize<T>(T obj)
{
    DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());
    MemoryStream ms = new MemoryStream();
    serializer.WriteObject(ms, obj);
    string retVal = Encoding.UTF8.GetString(ms.ToArray());
    return retVal;
}

public static T Deserialize<T>(string json)
{
    T obj = Activator.CreateInstance<T>();
    MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(json));
    DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());
    obj = (T)serializer.ReadObject(ms);
    ms.Close();
    return obj;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接