Ninja框架端点尝试将JSON映射到自定义对象时抛出500错误

时间:2018-10-16 19:39:29

标签: java json ninjaframework

所以我在这里有一个忍者终结点:

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

我只是试图向Webhook发送一些简单的JSON,由于某种原因,对象映射似乎无法正常工作。我想可能是我误解了文档?

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错误,并且在日志中没有任何其他指示。

据我所知,Ninja应该只是将JSON自动映射到我的对象,对吗?

4 个答案:

答案 0 :(得分:1)

给出特定的输入代码,其中data字段已被注释掉

//public Map data;

以及包含此字段的已发布输入JSON,请求应失败,并显示400 Bad Request

原因是Ninja使用Jackson进行JSON解析,并且默认情况下会抛出未知字段。

快速的解决方法是向@JsonIgnoreProperties类添加RecurOrderJSON注释。

例如

@JsonIgnoreProperties(ignoreUnknown = true)
public class RecurOrderJSON {
    ...
}

请参阅:Ignoring new fields on JSON objects using Jackson

现在,如果错误不是400,则没有太多信息可做,因为代码似乎没有其他任何明显的错误。

要么发布一个说明问题的SSCCE,要么尝试通过使用以下方法显示错误页面来进行调试:

  1. 使用mvn package ninja:run以调试模式启动应用程序
  2. 使用允许详细检查响应的工具(例如卷曲)访问端点。
    1. 将请求JSON存储在input.json
    2. 运行curl -v -o result.html -H 'Content-Type: application/json' --data '@input.json' http://localhost:8080/recurring
    3. 打开result.html查看回复

答案 1 :(得分:1)

我成功复制了您的问题,然后解决了该问题。

首先,为便于尝试/测试,我建议您(临时)进行修改:

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

请注意,指定 Content-type (内容类型)以获得良好的解释非常重要。

带有 /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}]

答案 2 :(得分:0)

可能是您执行了错误的请求(因此找不到JSON),但是对于某些Ninja错误,它会返回错误500?

例如,您可以看看here,其中指出在JSON请求中解析空JSON确实会导致错误的错误(500),而该错误应返回400“错误请求”

答案 3 :(得分:0)

process不需要上下文重复使用并使用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;
}

祝你好运!