Jquery ajax call return JSON ошибка синтаксического анализа
Я использую jquery для вызова метода wcf ajax, который возвращает список объектов в виде строки JSON. Строка JSON выглядит так, когда вы проверяете ее в fiddler2 (в TextView):
{"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 View, он показывает следующий 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);
}
}
);
Спасибо заранее!
UPDATE:
Благодаря @user1370958, на один шаг ближе к решению.
При изменении функции обратного вызова ошибки на следующее он успешно возвращает результат...
error: function (jqXHR, textStatus, errorThrown) {
var test = $.parseJSON(jqXHR.responseText);
var test2 = $.parseJSON(test.d);
alert(test2[0].Name);
},
Не знаю, почему, но я должен проанализировать результат, а затем проанализировать вложенные объекты внутри него. Я предполагаю, что если бы какой-либо из возвращаемых типов содержал сложные объекты, ему также понадобился бы другой синтаксический анализ...
Ответы
Ответ 1
Здесь "application/json" не является допустимым значением для свойства dataType.
Я изменил его на "json" в моем проекте, и эта же проблема была решена.
Пожалуйста, проверьте сведения здесь (комментарий № 7): http://bugs.jquery.com/ticket/8216
Ответ 2
Попробуйте добавить тип MIME в код сервера:
Response.ContentType = "application/json";
Ответ 3
С WCF 4.0 вы можете добавить атрибут automaticFormatSelectionEnabled
, который позволяет службе просматривать заголовок Accept
в HTTP попросите определить, какой формат будет возвращен. Пока возвращаемое вами сериализуемое значение, WCF будет обрабатывать правильную сериализацию для вас. В вашем jQuery ajax-вызове заголовок Accept добавляется, включая accepts: {json: "application/json"}
.
Ответ 4
Я предполагаю, что вы хотите вернуть значение ser.Serialize(query.ToArray())
клиенту (массиву). Но вы возвращаете его как строку, поэтому WCF выйдет из этого JSON в строку, а то, что вы закончите, - это не массив, а строка.
Поскольку вы используете анонимные типы, которые не поддерживаются WCF, вам необходимо использовать JavaScriptSerializer
. Поэтому, чтобы предотвратить двойное кодирование JSON (в строку), вы должны вместо этого вернуть данные как Stream
, чтобы WCF не касался ваших данных (см. Пример кода ниже).
Еще одна вещь: я вижу, что ваш ответ имеет оболочку {"d":...}
, которая предполагает, что вы используете <enableWebScript/>
/WebScriptEnablingBehavior
/WebScriptServiceHostFactory
при определении своей службы/конечной точки. Поскольку вы не используете библиотеку AJAX ASP.NET, вам не нужна эта упаковка, поэтому вы можете использовать "более простой" <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;
}
}
Ответ 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;
}
}
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
});
}
}
);