您如何使用Jackson将Java Map转换为组合的POJO?

时间:2019-06-06 16:37:48

标签: java json jackson-databind netflix conductor

我一直在尝试更可靠的方法来分析来自Conductor工作流程的输入。为此,我创建了一个包含一个人及其车辆的组合类结构。

Person.java

public class Person {

    protected String firstName;
    protected String lastName;
    protected List<Vehicle> vehicles;

    // Constructors, getters, setters

}

Vehicle.java

public class Vehicle {

    public String make;
    public String model;
    public String trim;
    public short year;

    // Constructors, getters, setters

}

然后,我创建了一个工作人员,该工作人员使用Jackson来将Conductor Client的Task.getInputData()映射转换为上述POJO。

ExperimentalStepWorker.java

public class ExperimentStepWorker implements Worker {

    protected ObjectMapper objectMapper = new ObjectMapper();

    // Other @Overloaded methods per the Worker interface

    /**
     * Executes a task and returns the updated task.
     *
     * @param task Task to be executed.
     * @return the {@link TaskResult} object
     * If the task is not completed yet, return with the status as IN_PROGRESS.
     */
    @Override
    public TaskResult execute(Task task) {

        TaskResult result = new TaskResult(task);

        Person person = objectMapper.convertValue(task.getInputData(), Person.class);

        System.out.println("The map's contents were:");
        System.out.println(task.getInputData());
        System.out.println();
        System.out.println("The objects's contents were:");
        System.out.println(person);

        result.setStatus(TaskResult.Status.COMPLETED);

        return result;
    }
}

然后,我将以下工作流程提交给了Conductor。第一个没有输入。第二个只有一个Person对象,最后一个也是最后一个具有三个载具的数组:

从Postman到Conductor Server的工作流输入

{
    "name": "see_if_jackson_works",
    "workflowDef": {
        "ownerApp": "postman",
        "createdBy": "postman_user",
        "name": "do_all_the_things_2",
        "description": "Test Http Task Workflow",
        "version": 1,
        "tasks": [
            {
                "name": "worker_1",
                "taskReferenceName": "First Experiment",
                "inputParameters": {},
                "type": "SIMPLE",
                "startDelay": 15,
                "optional": false
            },
            {
                "name": "worker_2",
                "taskReferenceName": "Second Experiment",
                "inputParameters": {
                    "firstName": "Kirkland",
                    "lastName": "Yuknis"
                },
                "type": "SIMPLE",
                "startDelay": 30,
                "optional": false
            },
            {
                "name": "worker_3",
                "taskReferenceName": "Third experiment",
                "inputParameters": {
                    "firstName": "Kirkland",
                    "lastName": "Yuknis",
                    "vehicles": [
                        {"make": "Subaru", "model": "Outback", "trim": "Limited", "year": 2018},
                        {"make": "Subaru", "model": "Outback", "trim": "Limited", "year": 2018},
                        {"make": "Subaru", "model": "Outback", "trim": "Limited", "year": 2018}
                        ]
                },
                "type": "SIMPLE",
                "startDelay": 45,
                "optional": false
            }
        ],
        "schemaVersion": 2,
        "restartable": true,
        "workflowStatusListenerEnabled": false
    },
    "input": {}
}

对于前两个实验,事情似乎运行良好,但是在最后一个实验中,指挥未能执行任务。阅读文档后,我想知道是否可以将组合对象作为Conductor任务的输入。有人可以确认或否认吗?如果可以的话,我在哪里可能会出错?

服务器呼叫呼叫工作人员时,

execute()方法的工作人员输出

The map's contents were:
{}

The objects's contents were:
Person{firstName='null', lastName='null', vehicles=null}

The map's contents were:
{firstName=Kirkland, lastName=Yuknis}

The objects's contents were:
Person{firstName='Kirkland', lastName='Yuknis', vehicles=null}

更新:我刚发现以下错误,这看起来像是杰克逊问题

{
         "taskType": "worker_3",
         "status": "FAILED",
         "inputData": {
            "firstName": "Kirkland",
            "lastName": "Yuknis",
            "vehicles": [
               {
                  "make": "Subaru",
                  "model": "Outback",
                  "trim": "Limited",
                  "Year": 2018
               },
               {
                  "make": "Subaru",
                  "model": "Outback",
                  "trim": "Limited",
                  "Year": 2018
               },
               {
                  "make": "Subaru",
                  "model": "Outback",
                  "trim": "Limited",
                  "Year": 2018
               }
            ]
         },
         "referenceTaskName": "Third experiment",
         "retryCount": 0,
         "seq": 3,
         "pollCount": 1,
         "taskDefName": "worker_3",
         "scheduledTime": 1559838042119,
         "startTime": 1559838087887,
         "endTime": 1559838088012,
         "updateTime": 1559838087888,
         "startDelayInSeconds": 45,
         "retried": true,
         "executed": false,
         "callbackFromWorker": true,
         "responseTimeoutSeconds": 1200,
         "workflowInstanceId": "08a7bf21-6f4b-4265-97b0-0ce9cc93d1a4",
         "workflowType": "do_all_the_things_2",
         "taskId": "3b4906df-7136-4669-a8c8-a12a9b7c2f6a",
         "reasonForIncompletion": "Error while executing the task: java.lang.IllegalArgumentException: Unrecognized field \"vehicles\" (class com.yuknis.egypt.models.Person), not marked as ignorable (2 known properties: \"lastName\", \"firstName\"])\n at [Source: UNKNOWN; line: -1, column: -1] (through reference chain: com.yuknis.egypt.models.Person[\"vehicles\"])",
         "callbackAfterSeconds": 0,
         "workerId": "Kirklands-MBP.hsd1.fl.comcast.net",
         "workflowTask": {
            "name": "worker_3",
            "taskReferenceName": "Third experiment",
            "inputParameters": {
               "firstName": "Kirkland",
               "lastName": "Yuknis",
               "vehicles": [
                  {
                     "make": "Subaru",
                     "model": "Outback",
                     "trim": "Limited",
                     "Year": 2018
                  },
                  {
                     "make": "Subaru",
                     "model": "Outback",
                     "trim": "Limited",
                     "Year": 2018
                  },
                  {
                     "make": "Subaru",
                     "model": "Outback",
                     "trim": "Limited",
                     "Year": 2018
                  }
               ]
            },
            "type": "SIMPLE",
            "startDelay": 45,
            "optional": false,
            "taskDefinition": {
               "createTime": 1559837812844,
               "name": "worker_3",
               "retryCount": 3,
               "timeoutSeconds": 0,
               "timeoutPolicy": "TIME_OUT_WF",
               "retryLogic": "FIXED",
               "retryDelaySeconds": 600,
               "responseTimeoutSeconds": 1200,
               "concurrentExecLimit": 100,
               "rateLimitPerFrequency": 50,
               "rateLimitFrequencyInSeconds": 60
            },
            "asyncComplete": false
         },
         "rateLimitPerFrequency": 0,
         "rateLimitFrequencyInSeconds": 0,
         "taskDefinition": {
            "present": true
         },
         "queueWaitTime": 45768,
         "taskStatus": "FAILED",
         "logs": [
            "06/06/19, 16:21:28:008 : java.lang.IllegalArgumentException: Unrecognized field \"vehicles\" (class com.yuknis.egypt.models.Person), not marked as ignorable (2 known properties: \"lastName\", \"firstName\"])\n at [Source: UNKNOWN; line: -1, column: -1] (through reference chain: com.yuknis.egypt.models.Person[\"vehicles\"])\n\tat com.fasterxml.jackson.databind.ObjectMapper._convert(ObjectMapper.java:3750)\n\tat com.fasterxml.jackson.databind.ObjectMapper.convertValue(ObjectMapper.java:3668)\n\tat com.yuknis.egypt.workers.ExperimentStepWorker.execute(ExperimentStepWorker.java:58)\n\tat com.netflix.conductor.client.task.WorkflowTaskCoordinator.execute(WorkflowTaskCoordinator.java:379)\n\tat com.netflix.conductor.client.task.WorkflowTaskCoordinator.lambda$pollForTask$4(WorkflowTaskCoordinator.java:340)\n\tat java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)\n\tat java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)\n\tat java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)\n\tat java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)\n\tat java.base/java.lang.Thread.run(Thread.java:835)\nCaused by: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field \"vehicles\" (class com.yuknis.egypt.models.Person), not marked as ignorable (2 known properties: \"lastName\", \"firstName\"])\n at [Source: UNKNOWN; line: -1, column: -1] (through reference chain: com.yuknis.egypt.models.Person[\"vehicles\"])\n\tat com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:61)\n\tat com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:823)\n\tat com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1153)\n\tat com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1589)\n\tat com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1567)\n\tat com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:294)\n\tat com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)\n\tat com.fasterxml.jackson.databind.ObjectMapper._convert(ObjectMapper.java:3745)\n\t... 9 more\n"
         ]
      },

1 个答案:

答案 0 :(得分:0)

我发现了问题。作为一种习惯,我不为类中的非原始数据成员创建访问器。由于List是非基元的,因此我(没有考虑)没有为其创建访问器。除此之外,车辆还受到保护而不是公开的。我添加了访问器,它解决了问题。感谢所有看过这个的人!