无法从START_OBJECT标记中反序列化java.lang.String的实例

Web*_*net 58 java deployment grizzly atmosphere

我遇到了一个问题,我的可部署jar遇到了一个异常,当我在IntelliJ中本地运行时,这个异常不会发生.

例外:

Receiving an event {id=2, socket=0c317829-69bf-43d6-b598-7c0c550635bb, type=getDashboard, data={workstationUuid=ddec1caa-a97f-4922-833f-632da07ffc11}, reply=true}
Firing getDashboard event to Socket#0c317829-69bf-43d6-b598-7c0c550635bb
Failed invoking AtmosphereFramework.doCometSupport()
java.lang.IllegalArgumentException: Can not deserialize instance of java.lang.String out of START_OBJECT token
 at [Source: N/A; line: -1, column: -1]
        at org.codehaus.jackson.map.ObjectMapper._convert(ObjectMapper.java:2502)
        at org.codehaus.jackson.map.ObjectMapper.convertValue(ObjectMapper.java:2468)
        at com.github.flowersinthesand.portal.support.DefaultDispatcher$DefaultHandler$DataParam.resolve(DefaultDispatcher.java:270)
        at com.github.flowersinthesand.portal.support.DefaultDispatcher$DefaultHandler.handle(DefaultDispatcher.java:204)
        at com.github.flowersinthesand.portal.support.DefaultDispatcher.fire(DefaultDispatcher.java:107)
        at com.github.flowersinthesand.portal.support.AbstractSocketFactory.fire(AbstractSocketFactory.java:73)
        at com.github.flowersinthesand.portal.atmosphere.AtmosphereSocketFactory.onRequest(AtmosphereSocketFactory.java:75)
        at org.atmosphere.cpr.AsynchronousProcessor.action(AsynchronousProcessor.java:256)
        at org.atmosphere.cpr.AsynchronousProcessor.suspended(AsynchronousProcessor.java:166)
        at org.atmosphere.container.Grizzly2WebSocketSupport.service(Grizzly2WebSocketSupport.java:75)
        at org.atmosphere.cpr.AtmosphereFramework.doCometSupport(AtmosphereFramework.java:1342)
        at org.atmosphere.websocket.DefaultWebSocketProcessor.dispatch(DefaultWebSocketProcessor.java:219)
        at org.atmosphere.websocket.DefaultWebSocketProcessor$2.run(DefaultWebSocketProcessor.java:183)
        at org.atmosphere.util.VoidExecutorService.execute(VoidExecutorService.java:101)
        at org.atmosphere.websocket.DefaultWebSocketProcessor.dispatch(DefaultWebSocketProcessor.java:178)
        at org.atmosphere.websocket.DefaultWebSocketProcessor.invokeWebSocketProtocol(DefaultWebSocketProcessor.java:167)
        at org.atmosphere.container.Grizzly2WebSocketSupport$Grizzly2WebSocketApplication.onMessage(Grizzly2WebSocketSupport.java:171)
        at org.glassfish.grizzly.websockets.DefaultWebSocket.onMessage(DefaultWebSocket.java:164)
        at org.glassfish.grizzly.websockets.frametypes.TextFrameType.respond(TextFrameType.java:70)
        at org.glassfish.grizzly.websockets.DataFrame.respond(DataFrame.java:104)
        at org.glassfish.grizzly.websockets.WebSocketFilter.handleRead(WebSocketFilter.java:221)
        at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
        at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:265)
        at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:200)
        at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:134)
        at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
        at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:78)
        at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:770)
        at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
        at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115)
        at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55)
        at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135)
        at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:551)
        at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:531)
        at java.lang.Thread.run(Thread.java:781)
Caused by: org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of java.lang.String out of START_OBJECT token
 at [Source: N/A; line: -1, column: -1]
        at org.codehaus.jackson.map.JsonMappingException.from(JsonMappingException.java:163)
        at org.codehaus.jackson.map.deser.StdDeserializationContext.mappingException(StdDeserializationContext.java:219)
        at org.codehaus.jackson.map.deser.std.StringDeserializer.deserialize(StringDeserializer.java:44)
        at org.codehaus.jackson.map.deser.std.StringDeserializer.deserialize(StringDeserializer.java:13)
        at org.codehaus.jackson.map.ObjectMapper._readValue(ObjectMapper.java:2704)
        at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1315)
        at org.codehaus.jackson.map.ObjectMapper._convert(ObjectMapper.java:2498)
        ... 34 more
java.lang.IllegalArgumentException: Can not deserialize instance of java.lang.String out of START_OBJECT token
 at [Source: N/A; line: -1, column: -1] Status 500 Message Server Error
Run Code Online (Sandbox Code Playgroud)

套接字处理程序

我相信由于以下项目将JSON解析为WorkstationRequest对象时发生异常.这是套接字处理程序:

@On
@Reply
@JsonView({Views.WorkstationView.class})
public WorkstationDashboard getDashboard(@Data WorkstationRequest request) {
    return new WorkstationDashboard(request.getWorkstation());
}
Run Code Online (Sandbox Code Playgroud)

套接字处理程序映射到的对象:

public class WorkstationRequest {

    /* Class to instantiate if this workstation does not already exist */
    private Class<? extends Workstation> workstationClass;

    private WorkflowProcess workflowProcess;

    private PhysicalWorkstation workstation;

    WorkstationService workstationService;

    /**
     * @param workstationClass Required so when jackson maps the UUID we can auto fetch the class
     */
    public WorkstationRequest(Class<? extends Workstation> workstationClass) {
        this.workstationClass = workstationClass;
        workstationService = (WorkstationService) ApplicationContextProvider.getApplicationContext().getBean("workstationService");
    }

    /* Set the workstation based on UUID.  Will register the workstation if it's new */
    @JsonProperty("workstationUuid")
    public void setWorkstation(String workstationUUID) {
        workstation = (PhysicalWorkstation)WorkstationService.getWorkstation(workstationUUID);

        //setup new workstation
        if (workstation == null) {
            WorkstationEntity workstationEntity = workstationService.findByUUID(workstationUUID);
            workstation = (PhysicalWorkstation)Workstation.factory(workstationEntity, workstationClass);

            //register with queue
            WorkflowProcessService.getWorkflowProcess(workstation).registerWorkstation(workstation);
        }
    }

    public PhysicalWorkstation getWorkstation() {
        return workstation;
    }
}
Run Code Online (Sandbox Code Playgroud)

要映射的JSON:

{"id":2,"socket":"0c317829-69bf-43d6-b598-7c0c550635bb","type":"getDashboard","data":{"workstationUuid":"ddec1caa-a97f-4922-833f-632da07ffc11"},"reply":true}
Run Code Online (Sandbox Code Playgroud)

WorkstationDashboard.java

public class WorkstationDashboard {
    private HashMap<String, Object> queue = new HashMap<String, Object>();

    private LinkedBlockingDeque<JobSetEntity> currentWork;

    public WorkstationDashboard() {
        queue.put("size", 0);
    }

    public WorkstationDashboard(Workstation workstation) {
        fromWorkstation(workstation);
    }

    /* Populate dashboard data from a workstation */
    public void fromWorkstation(Workstation workstation) {
        WorkflowProcess workflowProcess = WorkflowProcessService.getWorkflowProcess(workstation);

        setCurrentWork(workstation.getCurrentWork());
        setQueueSize(workflowProcess.getQueue().size());
    }

    public void setQueueSize(Integer queueSize) {
        queue.put("size", queueSize);
    }

    public HashMap<String, Object> getQueue() {
        return queue;
    }

    public LinkedBlockingDeque<JobSetEntity> getCurrentWork() {
        return currentWork;
    }

    public void setCurrentWork(LinkedBlockingDeque<JobSetEntity> currentWork) {
        this.currentWork = currentWork;
    }
}
Run Code Online (Sandbox Code Playgroud)

关于如何开始调试,我感到非常茫然.堆栈跟踪永远不会触及我的应用程序.我正在使用Maven -> Package部署我的.jar并执行它java -jar /path-to-jar.jar

更新:为了防止这个问题长得太长,我在这里包含了我的pom.xml:http://pastebin.com/1ZUtKCfE.我认为这是一个依赖问题,因为错误只发生在我的可部署jar上,而不是我的本地PC上.

Sot*_*lis 63

你正在映射这个JSON

{
    "id": 2,
    "socket": "0c317829-69bf-43d6-b598-7c0c550635bb",
    "type": "getDashboard",
    "data": {
        "workstationUuid": "ddec1caa-a97f-4922-833f-632da07ffc11"
    },
    "reply": true
}
Run Code Online (Sandbox Code Playgroud)

包含名为dataJSON对象作为其值的元素.您正在尝试workstationUuid将从该JSON对象命名的元素反序列化为此setter.

@JsonProperty("workstationUuid")
public void setWorkstation(String workstationUUID) {
Run Code Online (Sandbox Code Playgroud)

这不会直接起作用,因为Jackson看到的是JSON_OBJECT,而不是String.

尝试创建一个类 Data

public class Data { // the name doesn't matter 
    @JsonProperty("workstationUuid")
    private String workstationUuid;
    // getter and setter
}
Run Code Online (Sandbox Code Playgroud)

切换你的方法

@JsonProperty("data")
public void setWorkstation(Data data) {
    // use getter to retrieve it
Run Code Online (Sandbox Code Playgroud)

  • @theGamblerRises如果您完全不知道将与哪种类型相关联,则可以将通用JSON类型用于您正在使用的JSON库.杰克逊就是"JsonNode".这会将您的代码与杰克逊结合起来,但这并不容易使用该值. (3认同)

ric*_*ell 22

数据内容是如此可变,我认为最好的形式是将其定义为"ObjectNode",然后创建自己的类进行解析:

最后:

私有ObjectNode数据;

  • 你为此节省了我的长期追逐.我的`data`字段里面可以有任何JSON,所以我不能用一些POJO映射它.我正在寻找一些只能容纳JSON值的解决方案.非常感谢.只是要仔细检查,使用它有任何副作用或缺点吗? (3认同)

Sin*_*dhu 18

如果您不想为嵌套的json定义单独的类,则将嵌套的json对象定义为JsonNode应该可以工作,例如:

{"id":2,"socket":"0c317829-69bf-43d6-b598-7c0c550635bb","type":"getDashboard","data":{"workstationUuid":"ddec1caa-a97f-4922-833f-632da07ffc11"},"reply":true}

@JsonProperty("data")
    private JsonNode data;
Run Code Online (Sandbox Code Playgroud)


dil*_*dav 7

要解决这个问题(如果您的数据对象可以有任何未定义的 json 或者没有为数据定义 POJO),只需使用JsonNode将数据作为输入

private JsonNode data;
Run Code Online (Sandbox Code Playgroud)

然后您可以使用jsonpath 依赖项来访问数据内的值。

从此 json 获取 uuid

  "data": {
    "workStation": {
        {
          "uuid": "2",
          "Title": "Graduation day party"              
        }
    }
    "code": 200
  }
Run Code Online (Sandbox Code Playgroud)

使用JsonPath 库中的JsonContext通过 JsonPath 读取

DocumentContext jsonContext = JsonContext.createContext(data);
String uuid = jsonContext.read("workStation.uuid");
Run Code Online (Sandbox Code Playgroud)

DocumentContext read方法将json中的路径作为属性