Конечная точка платформы Ninja выдает ошибку 500 при попытке сопоставить JSON с пользовательским объектом
Итак, у меня есть конечная точка ниндзя:
public Result processRecurring(Context context, RecurOrderJSON recurOrderJSON) {
String id = recurOrderJSON.id;
String event_type = recurOrderJSON.event_type;
String request_id = recurOrderJSON.request_id;
//Map data = recurOrderJSON.data;
//recurringRouter(event_type, data);
log.info("ID value");
log.info(id);
return JsonResponse.build()
.message("OK")
.toResult();
}
Класс, который я пытаюсь сопоставить с:
public class RecurOrderJSON {
public String id;
public String event_type;
public String request_id;
// Maybe switch data type?
//public Map data;
}
И маршрут:
router.POST().route("/recurring").with(RecurringController::processRecurring);
Я просто пытаюсь отправить какой-то простой JSON в webhook, и по какой-то причине сопоставление объектов не работает. Я думаю, может быть, я неправильно понимаю документацию?
http://www.ninjaframework.org/documentation/working_with_json_jsonp.html
Вот пример, который они вам дают:
If you send that JSON to your application via the HTTP body you only need to add the POJO class to the controller method and Ninja will parse the incoming JSON for you:
package controllers;
public class ApplicationController {
public Result parsePerson(Person person) {
String nameOfPerson = person.name; // will be John Johnson
...
}
}
Насколько я могу сказать, я делаю это правильно? Я неправильно понимаю документацию? Вот пример объекта JSON - в настоящее время я пытаюсь получить только строки верхнего уровня, но в конечном итоге я также хочу получить данные:
{
"id": "hook-XXXXX",
"event_type": "tx-pending",
"data": {
"button_id": "static",
"publisher_organization": "org-XXXXXXX",
"campaign_id": "camp-097714a40aaf8965",
"currency": "USD",
"order_currency": "USD",
"id": "tx-XXXXXXX",
"category": "new-user-order",
"modified_date": "2018-10-15T05:41:12.577Z",
"order_total": 9680,
"button_order_id": "btnorder-77c9e56fd990f127",
"publisher_customer_id": "XymEz8GO2M",
"rate_card_id": "ratecard-41480b2a6b1196a7",
"advertising_id": null,
"event_date": "2018-10-15T05:41:06Z",
"status": "pending",
"pub_ref": null,
"account_id": "acc-4b17f5a014d0de1a",
"btn_ref": "srctok-0adf9e958510b3f1",
"order_id": null,
"posting_rule_id": null,
"order_line_items": [
{
"identifier": "Antique Trading Card",
"description": "Includes Lifetime Warranty",
"amount": 9680,
"publisher_commission": 968,
"attributes": {},
"total": 9680,
"quantity": 1
}
],
"order_click_channel": "webview",
"order_purchase_date": null,
"validated_date": null,
"amount": 968,
"customer_order_id": null,
"created_date": "2018-10-15T05:41:12.577Z",
"commerce_organization": "org-XXXXXX"
},
"request_id": "attempt-XXXXXXX"
}
В настоящее время я просто пытаюсь получить строковые значения, но я постоянно получаю ошибку 500, и в моих журналах нет никаких других указаний на какую-либо ошибку.
Насколько я могу судить, ниндзя должен просто автоматически сопоставить JSON с моим объектом, правильно?
4 ответа
Я успешно воспроизвел вашу проблему, а затем исправил ее.
Во-первых, для облегчения тестирования / тестирования я рекомендую (временные) модификации:
package controllers;
import models.RecurOrderJSON;
import ninja.Context;
import ninja.Result;
public class RecurringController {
public Result processRecurring(Context context, RecurOrderJSON recurOrderJSON) {
log.info("recurOrderJSON => " + recurOrderJSON);
return ninja.Results.ok();
}
}
А затем обновите вашу модель следующим образом:
package models;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@JsonIgnoreProperties(ignoreUnknown = true)
public class RecurOrderJSON {
public String id;
public String event_type;
public String request_id;
public Map data;
@Override
public String toString() {
return "RecurOrderJSON [id=" + id + ", event_type=" + event_type + ", request_id=" + request_id + ", data="
+ data.toString() + "]";
}
}
Вы можете заметить:
- Тип данных должен оставаться необработанным (универсальный не может использоваться здесь)
- важная аннотация @JsonIgnoreProperties(ignoreUnknown = true), чтобы избежать проблемы десериализации, если ваши исходные данные не полностью соответствуют вашей модели (обязательно используйте последнюю версию аннотации в подпакете fastxml, вместо старой, в субпакет Codehaus)
- реализация toString(), позволяющая только быструю проверку десериализации OK/KO
Затем вы можете легко протестировать систему с помощью wget или curl:
curl -H 'Content-Type: application/json' -d "@/tmp/jsonINput.json" -X POST http://localhost:8080/recurring
Обратите внимание, что для правильной интерпретации очень важно указать тип содержимого.
С файлом /tmp/jsonINput.json, содержащим именно то содержимое json, которое вы указали в своем вопросе.
Таким образом, все работает как шарм, получая этот вывод:
recurOrderJSON => RecurOrderJSON [id=hook-XXXXX, event_type=tx-pending, request_id=attempt-XXXXXXX, data={button_id=static, publisher_organization=org-XXXXXXX, campaign_id=camp-097714a40aaf8965, currency=USD, order_currency=USD, id=tx-XXXXXXX, category=new-user-order, modified_date=2018-10-15T05:41:12.577Z, order_total=9680, button_order_id=btnorder-77c9e56fd990f127, publisher_customer_id=XymEz8GO2M, rate_card_id=ratecard-41480b2a6b1196a7, advertising_id=null, event_date=2018-10-15T05:41:06Z, status=pending, pub_ref=null, account_id=acc-4b17f5a014d0de1a, btn_ref=srctok-0adf9e958510b3f1, order_id=null, posting_rule_id=null, order_line_items=[{identifier=Antique Trading Card, description=Includes Lifetime Warranty, amount=9680, publisher_commission=968, attributes={}, total=9680, quantity=1}], order_click_channel=webview, order_purchase_date=null, validated_date=null, amount=968, customer_order_id=null, created_date=2018-10-15T05:41:12.577Z, commerce_organization=org-XXXXXX}]
Учитывая конкретный входной код с data
поле закомментировано
//public Map data;
и размещенный входной JSON, который включает это поле, запрос должен завершиться неудачно с 400 Bad Request
,
Причина в том, что Ninja использует Джексона для анализа JSON и по умолчанию выбрасывает неизвестные поля.
Быстрый способ это добавить @JsonIgnoreProperties
аннотация к RecurOrderJSON
учебный класс.
например
@JsonIgnoreProperties(ignoreUnknown = true)
public class RecurOrderJSON {
...
}
Смотрите: Игнорирование новых полей в объектах JSON с использованием Джексона
Теперь, если ошибка не была 400, не нужно много информации, потому что, похоже, нет ничего явно неправильного в коде.
Либо опубликуйте SSCCE, демонстрирующую проблему, либо попытайтесь отладить, открыв страницу ошибки следующим способом:
- Запустите приложение в режиме отладки с помощью
mvn package ninja:run
- Получите доступ к конечной точке с помощью инструмента, который позволяет детально изучить ответ, например, скручивание.
- Сохранить запрос JSON в
input.json
- Бежать
curl -v -o result.html -H 'Content-Type: application/json' --data '@input.json' http://localhost:8080/recurring
- открыто
result.html
изучить ответ
- Сохранить запрос JSON в
Контекст не нужен в processRecurring, используйте Results.json() и возвращайте оригинал
public Result processRecurring(RecurOrderJSON recurOrderJSON) {
String id = recurOrderJSON.id;
String event_type = recurOrderJSON.event_type;
String request_id = recurOrderJSON.request_id;
//Map data = recurOrderJSON.data;
//recurringRouter(event_type, data);
log.info("ID value");
log.info(id);
return Results.json().render(recurOrderJSON);
}
Убедитесь, что вы получили пространство имен в вашем RecurOrderJSON
package models;
public class RecurOrderJSON {
public String id;
public String event_type;
public String request_id;
// Maybe switch data type?
//public Map data;
}
Удачи!
Может быть, вы выполняете неверный запрос (следовательно, JSON не найден), но для некоторой ошибки ниндзя он возвращает ошибку 500?
Например, вы можете взглянуть здесь, где указано, что синтаксический анализ пустого JSON в запросе JSON действительно приводит к ошибочной ошибке (500), в то время как предполагается, что он возвращает 400 "Bad Request"