jquery ajax调用返回JSON解析错误

时间:2022-10-18 14:25:47

I am using jquery to call an ajax wcf method that returns a list of objects as a JSON string. The JSON string looks like this when inspecting it in fiddler2 (in TextView):

我正在使用jquery调用ajax wcf方法,该方法以JSON字符串的形式返回对象列表。在fiddler2(在TextView中)检查JSON字符串时是这样的:

{"d":"[{\"ID\":\"6b2b8c62-31ce-4df2-982b-054ff5f6be72\",\"Name\":\"Carol\",\"Surname\":\"IrishWife\"},{\"ID\":\"d254740a-0a0f-4a1e-9e4f-0812227dd5af\",\"Name\":\"Willie\",\"Surname\":\"Le Roux\"},{\"ID\":\"660bf0dd-436a-4588-a9c0-19fd6fdcee23\",\"Name\":\"Emmas\",\"Surname\":\"Mum\"},{\"ID\":\"6b9403c5-b728-4e96-bcb1-203e7472eec3\",\"Name\":\"Owen\",\"Surname\":\"Lima\"},{\"ID\":\"d52c08fb-4418-4600-960f-243ff4443ee6\",\"Name\":\"Tim\",\"Surname\":\"Lee\"},{\"ID\":\"e2aacf5b-8855-44ce-9338-3d39f8ab3349\",\"Name\":\"Marcello\",\"Surname\":\"MT\"},{\"ID\":\"578be087-8385-46d6-89de-3db31d352cbc\",\"Name\":\"Carlyn\",\"Surname\":\"Homegroup\"},{\"ID\":\"4c805825-2bee-447a-8b75-41ead17db33e\",\"Name\":\"George\",\"Surname\":\"Homegroup\"},{\"ID\":\"ae48804f-5e78-42c8-9ba0-4214c98a5a89\",\"Name\":\"Isla\",\"Surname\":\"Le Roux\"},{\"ID\":\"f8be2f4f-fedb-4863-8a84-44fddea84ea9\",\"Name\":\"Peter\",\"Surname\":\"Anderson\"},{\"ID\":\"15e7644d-ec43-44ff-a959-47e00112da6b\",\"Name\":\"Kitty\",\"Surname\":\"Corbett\"},{\"ID\":\"8fd7fccc-335c-4d5c-93b5-4b00f96a9950\",\"Name\":\"Natalie\",\"Surname\":\"Archibald\"},{\"ID\":\"09b5aad2-2cf1-488a-962b-4d692b05ddea\",\"Name\":\"Miku\",\"Surname\":\"Heally\"},{\"ID\":\"affa369e-5af3-4537-a0f4-71422956da41\",\"Name\":\"Steven\",\"Surname\":\"Corbett\"},{\"ID\":\"65f57da3-4f88-4798-9590-83b4ccecfc44\",\"Name\":\"Tim\",\"Surname\":\"Archibald\"},{\"ID\":\"53bfb451-f66f-4b6e-b430-8d13c95b30d8\",\"Name\":\"Philip\",\"Surname\":\"MT\"},{\"ID\":\"c7f22b9b-4030-4f82-9f75-bbb726cabb73\",\"Name\":\"Vincent\",\"Surname\":\"Van Der Walt\"},{\"ID\":\"232577be-3165-4316-a20d-c2f2a09c5382\",\"Name\":\"Scott\",\"Surname\":\"Lynn\"},{\"ID\":\"913508a1-5dca-4504-8caf-c8e3dc386fc0\",\"Name\":\"Dan\",\"Surname\":\"MT\"},{\"ID\":\"36054a07-b14d-4c1c-b35f-e00875dde7e5\",\"Name\":\"Sarah\",\"Surname\":\"MT\"},{\"ID\":\"f14e7d98-e040-4ba9-928f-f2ff48116b0b\",\"Name\":\"Josh\",\"Surname\":\"IrishDude\"}]"}

When I inspect the result in fiddler's JSON View, it shows the following JSON:

当我检查fiddler的JSON视图中的结果时,它显示了以下JSON:

d=[{"ID":"6b2b8c62-31ce-4df2-982b-054ff5f6be72","Name":"Carol","Surname":"IrishWife"},{"ID":"d254740a-0a0f-4a1e-9e4f-0812227dd5af","Name":"Willie","Surname":"Le Roux"},{"ID":"660bf0dd-436a-4588-a9c0-19fd6fdcee23","Name":"Emmas","Surname":"Mum"},{"ID":"6b9403c5-b728-4e96-bcb1-203e7472eec3","Name":"Owen","Surname":"Lima"},{"ID":"d52c08fb-4418-4600-960f-243ff4443ee6","Name":"Tim","Surname":"Lee"},{"ID":"e2aacf5b-8855-44ce-9338-3d39f8ab3349","Name":"Marcello","Surname":"MT"},{"ID":"578be087-8385-46d6-89de-3db31d352cbc","Name":"Carlyn","Surname":"Homegroup"},{"ID":"4c805825-2bee-447a-8b75-41ead17db33e","Name":"George","Surname":"Homegroup"},{"ID":"ae48804f-5e78-42c8-9ba0-4214c98a5a89","Name":"Isla","Surname":"Le Roux"},{"ID":"f8be2f4f-fedb-4863-8a84-44fddea84ea9","Name":"Peter","Surname":"Anderson"},{"ID":"15e7644d-ec43-44ff-a959-47e00112da6b","Name":"Kitty","Surname":"Corbett"},{"ID":"8fd7fccc-335c-4d5c-93b5-4b00f96a9950","Name":"Natalie","Surname":"Archibald"},{"ID":"09b5aad2-2cf1-488a-962b-4d692b05ddea","Name":"Miku","Surname":"Heally"},{"ID":"affa369e-5af3-4537-a0f4-71422956da41","Name":"Steven","Surname":"Corbett"},{"ID":"65f57da3-4f88-4798-9590-83b4ccecfc44","Name":"Tim","Surname":"Archibald"},{"ID":"53bfb451-f66f-4b6e-b430-8d13c95b30d8","Name":"Philip","Surname":"MT"},{"ID":"c7f22b9b-4030-4f82-9f75-bbb726cabb73","Name":"Vincent","Surname":"Van Der Walt"},{"ID":"232577be-3165-4316-a20d-c2f2a09c5382","Name":"Scott","Surname":"Lynn"},{"ID":"913508a1-5dca-4504-8caf-c8e3dc386fc0","Name":"Dan","Surname":"MT"},{"ID":"36054a07-b14d-4c1c-b35f-e00875dde7e5","Name":"Sarah","Surname":"MT"},{"ID":"f14e7d98-e040-4ba9-928f-f2ff48116b0b","Name":"Josh","Surname":"IrishDude"}]

So fiddler can parse it successfully, but on the client, the jquery ajax error callback function displays the following error:

所以fiddler可以成功解析它,但是在客户端,jquery ajax error callback函数显示如下错误:

Error: No conversion from text to application/json

The wcf method is defined as follows:

wcf方法定义如下:

    [OperationContract]
    [WebGet(ResponseFormat=WebMessageFormat.Json)]
    public string GetPeople(Guid groupId)
    {
        using (SchedulerContext context = new SchedulerContext())
        {
            JavaScriptSerializer ser = new JavaScriptSerializer();

            var query = from p in context.People
                        where p.Group_ID == groupId
                        select new
                        {
                            p.ID,
                            p.Name,
                            p.Surname
                        };

            return ser.Serialize(query.ToArray());
        }   
    }

And finally, the calling jquery is:

最后,调用jquery:

$.ajax(
        {
            type: "GET",
            dataType: "application/json",
            contentType: "json",
            data: { groupId: 'ae09a080-5d7c-4e92-9a87-591574b7c4b8' },
            url: "WebAPI.svc/GetPeople",
            error: function (jqXHR, textStatus, errorThrown) {
                alert("error");
            },
            success: function (msg) {
                alert(msg.d[0].Name);
            }
        }
);

Thanks in advance!

提前谢谢!

UPDATE: Thanks to @user1370958, one step closer to the solution.

更新:感谢@user1370958,离解决方案更近了一步。

When changing the error callback function to the following it successfully returns the result...

当将错误回调函数更改为以下时,它将成功地返回结果…

error: function (jqXHR, textStatus, errorThrown) {
    var test = $.parseJSON(jqXHR.responseText);
    var test2 = $.parseJSON(test.d);
    alert(test2[0].Name);
},

Not sure why, but I have to parse the result and then parse the nested objects inside that. I'm assuming if any of my returned types contained complex objects it would also have needed another parse...

不知道为什么,但我必须解析结果,然后解析其中的嵌套对象。我假设如果我返回的任何类型包含复杂的对象,它也需要另一个解析……

5 个解决方案

#1


49  

Here, "application/json" is not a valid value for the dataType property. I changed it to "json" in my project and the same problem was solved.

在这里,“application/json”不是dataType属性的有效值。在我的项目中,我将它改为“json”,同样的问题也得到了解决。

Please check details here (comment #7): http://bugs.jquery.com/ticket/8216

请在这里查看详细信息(注释#7):http://bugs.jquery.com/ticket/8216

#2


4  

Try adding the MIME type in your server-side code:

尝试在服务器端代码中添加MIME类型:

Response.ContentType = "application/json";

#3


1  

With WCF 4.0, you can add an attribute called automaticFormatSelectionEnabled which allows the service to look at the Accept header in the HTTP request to determine what format to return. As long as what you are returning is serializable, WCF will handle the correct serialization for you. In your jQuery ajax call, the Accept header is added by including accepts: {json: "application/json"}.

使用WCF 4.0,您可以添加一个名为automaticFormatSelectionEnabled的属性,该属性允许服务查看HTTP请求中的Accept标头,以确定返回的格式。只要返回的是可序列化的,WCF将为您处理正确的序列化。在jQuery ajax调用中,通过包含Accept: {json: "application/json"}添加Accept标头。

#4


0  

I assume you want to return the value of ser.Serialize(query.ToArray()) to the client (an array). But you're returning it as a string, so WCF will escape that JSON into a string, and what you'll end up is not an array, but a string.

我假设您希望将ser.Serialize(query.ToArray())的值返回给客户端(一个数组)。但是你把它作为一个字符串返回,所以WCF会把JSON转义成一个字符串,你最终得到的不是一个数组,而是一个字符串。

Since you're using anonymous types, which aren't natively supported by WCF, you need to use the JavaScriptSerializer. So to prevent the double-encoding of the JSON (into the string) you should return the data as a Stream instead, so that WCF won't touch your data (see sample code below).

因为您使用的是匿名类型,而WCF并不是本机支持的,所以您需要使用JavaScriptSerializer。因此,为了防止JSON的双重编码(到字符串中),您应该将数据作为流返回,这样WCF就不会触及您的数据(参见下面的示例代码)。

One more thing: I see your response has a {"d":...} wrapper, which suggests that you're using the <enableWebScript/> / WebScriptEnablingBehavior / WebScriptServiceHostFactory when defining your service / endpoint. Since you're not using the ASP.NET AJAX library, you don't need that wrapping, so you can use the "simpler" <webHttp/> / WebHttpBehavior / WebServiceHostFactory instead, and your response won't be wrapped in that "d" object.

还有一件事:我看到你的回复有一个“d”:……}包装器,这表明您在定义服务/端点时使用 / WebScriptEnablingBehavior / WebScriptServiceHostFactory。因为你没有使用ASP。NET AJAX库,您不需要那个包装,因此您可以使用“更简单”的 / WebHttpBehavior / WebServiceHostFactory,并且您的响应不会被包装在那个“d”对象中。

[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json)]
public System.IO.Stream GetPeople(Guid groupId)
{
    using (SchedulerContext context = new SchedulerContext())
    {
        JavaScriptSerializer ser = new JavaScriptSerializer();

        var query = from p in context.People
                    where p.Group_ID == groupId
                    select new
                    {
                        p.ID,
                        p.Name,
                        p.Surname
                    };

        string json = ser.Serialize(query.ToArray());
        using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(json)))
        {
            WebOperationContext.Current.OutgoingResponse.ContentType = "application/json; charset=utf-8";
            return ms;
        }

}

#5


0  

I've found a workaround:

我找到了一个解决方案:

The first problem was the circular reference exception on the entity model. To overcome this I use the following code to Detach my entities from the context and then serialize them to strings. I then serialize them on the client using the code below that.

第一个问题是实体模型上的循环引用异常。为了克服这个问题,我使用下面的代码将我的实体从上下文中分离出来,然后将它们序列化为字符串。然后,我使用下面的代码在客户机上序列化它们。

Service

服务

    [WebGet(ResponseFormat = WebMessageFormat.Json)]
    [OperationContract]
    public string[] GetPeople(Guid groupId)
    {
        using (SchedulerContext context = new SchedulerContext())
        {

            var people = (from p in context.People
                          where p.Group_ID == groupId
                          select p).ToList();

            JavaScriptSerializer ser = new JavaScriptSerializer();
            string[] result = new string[people.Count];
            for (int i = 0; i<people.Count; i++)
            {
                context.Detach(people[i]);
                string json = ser.Serialize(people[i]);
                result[i] = json;
            }
            return result;
        }   
    }

Client

客户端

        $.ajax(
                {
                    type: "GET",
                    //dataType: "application/json",
                    //dataType: "text/plain",
                    contentType: "json",
                    data: { groupId: 'ae09a080-5d7c-4e92-9a87-591574b7c4b8' },
                    //data: { groupId: 'test' },
                    //data: { groupId: '739526F1-7C58-4E3B-97D8-4870948BFE32' },
                    url: "WebAPI.svc/GetPeople",
                    error: function (jqXHR, textStatus, errorThrown) {
                        alert(jqXHR.resultText);
                    },
                    success: function (people) {
                        //the returned param "people" is of type string[], so each string needs parsed 
                        $(people).each(function (index, value) {
                            var person = $.parseJSON(value);
                            //now I can use the Person object
                        });

                    }
                }

        );

#1


49  

Here, "application/json" is not a valid value for the dataType property. I changed it to "json" in my project and the same problem was solved.

在这里,“application/json”不是dataType属性的有效值。在我的项目中,我将它改为“json”,同样的问题也得到了解决。

Please check details here (comment #7): http://bugs.jquery.com/ticket/8216

请在这里查看详细信息(注释#7):http://bugs.jquery.com/ticket/8216

#2


4  

Try adding the MIME type in your server-side code:

尝试在服务器端代码中添加MIME类型:

Response.ContentType = "application/json";

#3


1  

With WCF 4.0, you can add an attribute called automaticFormatSelectionEnabled which allows the service to look at the Accept header in the HTTP request to determine what format to return. As long as what you are returning is serializable, WCF will handle the correct serialization for you. In your jQuery ajax call, the Accept header is added by including accepts: {json: "application/json"}.

使用WCF 4.0,您可以添加一个名为automaticFormatSelectionEnabled的属性,该属性允许服务查看HTTP请求中的Accept标头,以确定返回的格式。只要返回的是可序列化的,WCF将为您处理正确的序列化。在jQuery ajax调用中,通过包含Accept: {json: "application/json"}添加Accept标头。

#4


0  

I assume you want to return the value of ser.Serialize(query.ToArray()) to the client (an array). But you're returning it as a string, so WCF will escape that JSON into a string, and what you'll end up is not an array, but a string.

我假设您希望将ser.Serialize(query.ToArray())的值返回给客户端(一个数组)。但是你把它作为一个字符串返回,所以WCF会把JSON转义成一个字符串,你最终得到的不是一个数组,而是一个字符串。

Since you're using anonymous types, which aren't natively supported by WCF, you need to use the JavaScriptSerializer. So to prevent the double-encoding of the JSON (into the string) you should return the data as a Stream instead, so that WCF won't touch your data (see sample code below).

因为您使用的是匿名类型,而WCF并不是本机支持的,所以您需要使用JavaScriptSerializer。因此,为了防止JSON的双重编码(到字符串中),您应该将数据作为流返回,这样WCF就不会触及您的数据(参见下面的示例代码)。

One more thing: I see your response has a {"d":...} wrapper, which suggests that you're using the <enableWebScript/> / WebScriptEnablingBehavior / WebScriptServiceHostFactory when defining your service / endpoint. Since you're not using the ASP.NET AJAX library, you don't need that wrapping, so you can use the "simpler" <webHttp/> / WebHttpBehavior / WebServiceHostFactory instead, and your response won't be wrapped in that "d" object.

还有一件事:我看到你的回复有一个“d”:……}包装器,这表明您在定义服务/端点时使用 / WebScriptEnablingBehavior / WebScriptServiceHostFactory。因为你没有使用ASP。NET AJAX库,您不需要那个包装,因此您可以使用“更简单”的 / WebHttpBehavior / WebServiceHostFactory,并且您的响应不会被包装在那个“d”对象中。

[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json)]
public System.IO.Stream GetPeople(Guid groupId)
{
    using (SchedulerContext context = new SchedulerContext())
    {
        JavaScriptSerializer ser = new JavaScriptSerializer();

        var query = from p in context.People
                    where p.Group_ID == groupId
                    select new
                    {
                        p.ID,
                        p.Name,
                        p.Surname
                    };

        string json = ser.Serialize(query.ToArray());
        using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(json)))
        {
            WebOperationContext.Current.OutgoingResponse.ContentType = "application/json; charset=utf-8";
            return ms;
        }

}

#5


0  

I've found a workaround:

我找到了一个解决方案:

The first problem was the circular reference exception on the entity model. To overcome this I use the following code to Detach my entities from the context and then serialize them to strings. I then serialize them on the client using the code below that.

第一个问题是实体模型上的循环引用异常。为了克服这个问题,我使用下面的代码将我的实体从上下文中分离出来,然后将它们序列化为字符串。然后,我使用下面的代码在客户机上序列化它们。

Service

服务

    [WebGet(ResponseFormat = WebMessageFormat.Json)]
    [OperationContract]
    public string[] GetPeople(Guid groupId)
    {
        using (SchedulerContext context = new SchedulerContext())
        {

            var people = (from p in context.People
                          where p.Group_ID == groupId
                          select p).ToList();

            JavaScriptSerializer ser = new JavaScriptSerializer();
            string[] result = new string[people.Count];
            for (int i = 0; i<people.Count; i++)
            {
                context.Detach(people[i]);
                string json = ser.Serialize(people[i]);
                result[i] = json;
            }
            return result;
        }   
    }

Client

客户端

        $.ajax(
                {
                    type: "GET",
                    //dataType: "application/json",
                    //dataType: "text/plain",
                    contentType: "json",
                    data: { groupId: 'ae09a080-5d7c-4e92-9a87-591574b7c4b8' },
                    //data: { groupId: 'test' },
                    //data: { groupId: '739526F1-7C58-4E3B-97D8-4870948BFE32' },
                    url: "WebAPI.svc/GetPeople",
                    error: function (jqXHR, textStatus, errorThrown) {
                        alert(jqXHR.resultText);
                    },
                    success: function (people) {
                        //the returned param "people" is of type string[], so each string needs parsed 
                        $(people).each(function (index, value) {
                            var person = $.parseJSON(value);
                            //now I can use the Person object
                        });

                    }
                }

        );