【问题标题】:jquery ajax call return JSON parsing errorjquery ajax调用返回JSON解析错误
【发布时间】:2012-05-14 10:27:12
【问题描述】:

我正在使用 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\"}]"}

当我在 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"}]

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

Error: No conversion from text to application/json

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());
        }   
    }

最后,调用 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);
            }
        }
);

提前致谢!

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

将错误回调函数改成如下就成功返回结果...

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

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

【问题讨论】:

    标签: jquery ajax json wcf parsing


    【解决方案1】:

    这里,"application/json" 不是 dataType 属性的有效值。 我在我的项目中把它改成了"json",同样的问题也解决了。

    请在此处查看详细信息(评论 #7):http://bugs.jquery.com/ticket/8216

    【讨论】:

    • application/json 用于 http 标头而不是 jquery ajax。刚刚确认。
    【解决方案2】:

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

    Response.ContentType = "application/json";
    

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 我试试这个,在哪里添加 automaticFormatSelectionEnabled?
      • 答案中的链接显示了如何在配置中或以编程方式添加它。
      • 我试着添加你说的东西。它成功调用服务器,我可以单步执行 WebGET。然后它似乎返回了,但是 fiddler 报告:[Fiddler] ReadResponse() failed: The server did not return a response for this request。并且错误回调再次运行,没有返回数据。
      【解决方案4】:

      我假设您想将ser.Serialize(query.ToArray()) 的值返回给客户端(一个数组)。但是您将其作为字符串返回,因此 WCF 会将 JSON 转义为字符串,最终得到的不是数组,而是字符串。

      由于您使用的是 WCF 本身不支持的匿名类型,因此您需要使用 JavaScriptSerializer。因此,为了防止 JSON 的双重编码(到字符串中),您应该将数据返回为 Stream,以便 WCF 不会接触您的数据(请参见下面的示例代码)。

      还有一件事:我看到您的回复有一个{"d":...} 包装器,这表明您在定义服务/端点时使用了<enableWebScript/> / WebScriptEnablingBehavior / WebScriptServiceHostFactory。由于您没有使用 ASP.NET AJAX 库,因此您不需要该包装,因此您可以使用“更简单的”<webHttp/>/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;
              }
      
      }
      

      【讨论】:

      • 谢谢,但没有运气。我复制了您的代码,但现在 javascript 错误回调没有错误信息,只有空字符串并说错误是“错误”。此外,不再返回 resultText。
      • 尝试在服务器上启用跟踪,看看是否有什么奇怪的事情发生。或者查看实际的网络响应(使用 Fiddler 或浏览器开发者工具),看看是否有任何其他信息。
      • "[Fiddler] ReadResponse() 失败:服务器没有返回对此请求的响应。"
      • 然后尝试在服务器上启用跟踪。它会告诉服务器关闭连接的原因。
      • 不确定我是否遗漏了什么,但启用跟踪后,它只会发出原始页面请求的跟踪信息,而不是对服务的 ajax 调用。
      【解决方案5】:

      我找到了解决方法:

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

      服务

          [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;
              }   
          }
      

      客户

              $.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
                              });
      
                          }
                      }
      
              );
      

      【讨论】:

        猜你喜欢
        • 2017-07-31
        • 2013-10-15
        • 1970-01-01
        • 2021-04-23
        • 1970-01-01
        • 2012-07-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多