Die Instanz von java.lang.String kann nicht aus dem START_OBJECT-Token deserialisiert werden

Lesezeit: 11 Minuten

Benutzer-Avatar
Ben

Ich stoße auf ein Problem, bei dem mein bereitstellbares JAR auf eine Ausnahme trifft, die nicht auftritt, wenn ich dies lokal in IntelliJ ausführe.

Ausnahme:

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

Socket-Handler

Ich glaube, dass die Ausnahme auftritt, wenn der JSON aufgrund des folgenden Elements in ein WorkstationRequest-Objekt geparst wird. Dies ist der Socket-Handler:

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

Das Objekt, dem der Socket-Handler zugeordnet ist:

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

Das zugeordnete JSON:

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

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

Ich bin ziemlich ratlos, wie ich mit dem Debuggen beginnen soll. Der Stack-Trace berührt meine Anwendung nie. Ich benutze Maven -> Package um meine .jar-Datei bereitzustellen und damit auszuführen java -jar /path-to-jar.jar

Aktualisieren: Um zu verhindern, dass diese Frage unglaublich lang wird, habe ich meine pom.xml hier eingefügt: http://pastebin.com/1ZUtKCfE. Ich glaube, dass dies ein Abhängigkeitsproblem ist, da der Fehler nur auf meinem bereitstellbaren JAR und nicht auf meinem lokalen PC auftritt.

Benutzer-Avatar
Sotirios Delimanolis

Sie ordnen diesen JSON zu

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

das ein Element namens enthält data die ein JSON-Objekt als Wert hat. Sie versuchen, das genannte Element zu deserialisieren workstationUuid von diesem JSON-Objekt in diesen Setter.

@JsonProperty("workstationUuid")
public void setWorkstation(String workstationUUID) {

Dies funktioniert nicht direkt, da Jackson ein JSON_OBJECT und keinen String sieht.

Versuchen Sie, eine Klasse zu erstellen Data

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

Schalten Sie Ihre Methode um

@JsonProperty("data")
public void setWorkstation(Data data) {
    // use getter to retrieve it

  • Ich habe es versäumt, dies im Detail zu beschreiben, aber die Socket-Bibliothek, die ich verwende, bildet das ab data Feld in diesem Array zu meinem Objekt über public WorkstationDashboard getDashboard(@Data WorkstationRequest request) {. Es ruft getDashboard() wegen dem type in diesem JSON, dann Karten data. Ich könnte mich irren, da ich nicht wirklich weiß, was los ist. Da dies jedoch alles lokal auf meinem PC funktioniert und bricht, wenn ich meine Anwendung über eine JAR-Datei bereitstelle, scheint es sich um eine Art Abhängigkeitsproblem zu handeln. Mein Pomp ist hier: pastebin.com/1ZUtKCfE

    – Ben

    16. Oktober 2013 um 13:47 Uhr


  • @Webnet ist @Data eine benutzerdefinierte Anmerkung, die die bindet data Feld aus dem JSON? Sie müssen zurückgehen, um zu sehen, wie es die generiert WorkstationRequest Streit.

    – Sotirios Delimanolis

    16. Oktober 2013 um 13:57 Uhr

  • @SotiriosDelimanolis, SOLID-Antwortmann. Hat mir Stunden der Fehlersuche erspart.

    – icfantv

    10. Juli 2015 um 17:20 Uhr

  • @SotiriosDelimanolis, wenn sich meine Daten ständig ändern, wäre ich mir nicht sicher, wie viele Werte es werden data Feld enthalten. Gibt es Arbeit um? stackoverflow.com/questions/39053106/…

    – theGamblerRises

    20. August 2016 um 11:25 Uhr

  • @theGamblerRises Wenn Sie absolut keine Ahnung haben, welcher Typ damit verknüpft wird, können Sie den generischen JSON-Typ für die von Ihnen verwendete JSON-Bibliothek verwenden. Mit Jackson, das ist JsonNode. Dies koppelt Ihren Code jedoch an Jackson und macht es nicht einfach, diesen Wert dann zu verwenden.

    – Sotirios Delimanolis

    20. August 2016 um 15:16 Uhr

Benutzer-Avatar
Sindhu

Wenn Sie keine separate Klasse für verschachteltes json definieren möchten, sollte das Definieren eines verschachtelten json-Objekts als JsonNode funktionieren, zum Beispiel:

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

@JsonProperty("data")
    private JsonNode data;

  • Ich musste die Annotation @ JsonProperty nicht verwenden – nach meinem Verständnis ist sie nur erforderlich, wenn sich der Name im JSON vom Attributnamen im Objekt unterscheidet.

    – Dagmar

    10. Mai 2018 um 10:02 Uhr

  • Wenn Sie „JsonNode“ nicht verwenden möchten, können Sie eine separate Klasse für das Array „data“:{..}“ definieren und diesen Klassennamen anstelle von „JsonNode“ verwenden.

    – hipokito

    31. Mai 2018 um 13:40 Uhr


Der Dateninhalt ist so variabel, dass es meiner Meinung nach am besten ist, ihn als “ObjectNode” zu definieren und als nächstes eine eigene Klasse zum Analysieren zu erstellen:

Endlich:

private ObjectNode-Daten;

  • Dafür hast du mir meine lange Jagd erspart. Mein data Feld kann jedes JSON enthalten, daher kann ich es nicht mit POJO abbilden. Ich habe nach einer Lösung gesucht, die nur JSON-Werte enthalten kann. Ich danke dir sehr. Nur um es noch einmal zu überprüfen, gibt es Nebenwirkungen oder Nachteile bei der Verwendung?

    – theGamblerRises

    20. August 2016 um 11:57 Uhr

Benutzer-Avatar
dilesh yadav

Um dies zu lösen (falls Ihr Datenobjekt einen undefinierten json haben kann oder kein POJO für Daten definiert ist), verwenden Sie einfach JsonNode Daten als Input nehmen

private JsonNode data;

Dann können Sie verwenden jsonpath-Abhängigkeit um auf die Werte in den Daten zuzugreifen.

Um uuid von diesem json abzurufen

  "data": {
    "workStation": {
        {
          "uuid": "2",
          "Title": "Graduation day party"              
        }
    }
    "code": 200
  }

Verwenden JsonContext aus der JsonPath-Bibliothek zum Lesen über JsonPath

DocumentContext jsonContext = JsonContext.createContext(data);
String uuid = jsonContext.read("workStation.uuid");

Die DocumentContext-Lesemethode nimmt den Pfad in JSON als Attribut

Benutzer-Avatar
Atul Kumar

Das Problem wurde mit der Jackson-Bibliothek behoben. Drucke werden aus der Hauptklasse aufgerufen und alle POJO-Klassen werden erstellt. Hier sind die Codeschnipsel.

MainClass.java

public class MainClass {
  public static void main(String[] args) throws JsonParseException, 
       JsonMappingException, IOException {

String jsonStr = "{\r\n" + "    \"id\": 2,\r\n" + " \"socket\": \"0c317829-69bf- 
             43d6-b598-7c0c550635bb\",\r\n"
            + " \"type\": \"getDashboard\",\r\n" + "    \"data\": {\r\n"
            + "     \"workstationUuid\": \"ddec1caa-a97f-4922-833f- 
            632da07ffc11\"\r\n" + " },\r\n"
            + " \"reply\": true\r\n" + "}";

    ObjectMapper mapper = new ObjectMapper();

    MyPojo details = mapper.readValue(jsonStr, MyPojo.class);

    System.out.println("Value for getFirstName is: " + details.getId());
    System.out.println("Value for getLastName  is: " + details.getSocket());
    System.out.println("Value for getChildren is: " + 
      details.getData().getWorkstationUuid());
    System.out.println("Value for getChildren is: " + details.getReply());

}

MyPojo.java

public class MyPojo {
    private String id;

    private Data data;

    private String reply;

    private String socket;

    private String type;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public Data getData() {
        return data;
    }

    public void setData(Data data) {
        this.data = data;
    }

    public String getReply() {
        return reply;
    }

    public void setReply(String reply) {
        this.reply = reply;
    }

    public String getSocket() {
        return socket;
    }

    public void setSocket(String socket) {
        this.socket = socket;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    } 
}

Daten.java

public class Data {
    private String workstationUuid;

    public String getWorkstationUuid() {
        return workstationUuid;
    }

    public void setWorkstationUuid(String workstationUuid) {
        this.workstationUuid = workstationUuid;
    }   
}

ERGEBNISSE:

Value for getFirstName is: 2
Value for getLastName  is: 0c317829-69bf-43d6-b598-7c0c550635bb
Value for getChildren is: ddec1caa-a97f-4922-833f-632da07ffc11
Value for getChildren is: true

Benutzer-Avatar
Ajay

So habe ich mein Problem gelöst. Hoffe es hilft anderen. In meinem Fall habe ich eine Klasse, ein Feld, deren Getter und Setter erstellt und dann das Objekt anstelle der Zeichenfolge bereitgestellt.

Benutze das

public static class EncryptedData {
    private String encryptedData;

    public String getEncryptedData() {
        return encryptedData;
    }

    public void setEncryptedData(String encryptedData) {
        this.encryptedData = encryptedData;
    }
}

@PutMapping(value = MY_IP_ADDRESS)
public ResponseEntity<RestResponse> updateMyIpAddress(@RequestBody final EncryptedData encryptedData) {
    try {
        Path path = Paths.get(PUBLIC_KEY);
        byte[] bytes = Files.readAllBytes(path);
        PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(base64.decode(bytes));
        PrivateKey privateKey = KeyFactory.getInstance(CRYPTO_ALGO_RSA).generatePrivate(ks);

        Cipher cipher = Cipher.getInstance(CRYPTO_ALGO_RSA);
        cipher.init(Cipher.PRIVATE_KEY, privateKey);
        String decryptedData = new String(cipher.doFinal(encryptedData.getEncryptedData().getBytes()));
        String[] dataArray = decryptedData.split("|");


        Method updateIp = Class.forName("com.cuanet.client.helper").getMethod("methodName", String.class,String.class);
        updateIp.invoke(null, dataArray[0], dataArray[1]);

    } catch (Exception e) {
        LOG.error("Unable to update ip address for encrypted data: "+encryptedData, e);
    }

    return null;

An Stelle von

@PutMapping(value = MY_IP_ADDRESS)
public ResponseEntity<RestResponse> updateMyIpAddress(@RequestBody final EncryptedData encryptedData) {
    try {
        Path path = Paths.get(PUBLIC_KEY);
        byte[] bytes = Files.readAllBytes(path);
        PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(base64.decode(bytes));
        PrivateKey privateKey = KeyFactory.getInstance(CRYPTO_ALGO_RSA).generatePrivate(ks);

        Cipher cipher = Cipher.getInstance(CRYPTO_ALGO_RSA);
        cipher.init(Cipher.PRIVATE_KEY, privateKey);
        String decryptedData = new String(cipher.doFinal(encryptedData.getBytes()));
        String[] dataArray = decryptedData.split("|");


        Method updateIp = Class.forName("com.cuanet.client.helper").getMethod("methodName", String.class,String.class);
        updateIp.invoke(null, dataArray[0], dataArray[1]);

    } catch (Exception e) {
        LOG.error("Unable to update ip address for encrypted data: "+encryptedData, e);
    }

    return null;
}

Benutzer-Avatar
Dhruv sahu

Diese Arten von Fehlern treten auf, wenn wir einen falschen Datentyp für POJO-Variablen verwenden.

1311030cookie-checkDie Instanz von java.lang.String kann nicht aus dem START_OBJECT-Token deserialisiert werden

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy