Search code examples
jsonspringjstreestompsockjs

deserializing nested JSON with jackson, spring, stomp setup


Before diving into the issue, I'm using a project built off of Spring Starter Guide gs-messaging-stomp-websocket. Per the guide I'm using Stomp and SockJS. Having said that I've also added in JPA logic to allow changes to be persisted after receiving them from the web socket. My problem is that I'm finally able to send a serialized jstree to the backend, but it cannot deserialize it when it encounters a nested object. This is the send from the frontend:

function sendNode() {
    //get rid of the leading and trailing [ ]s
    var coreTree = $("#treeStart").jstree(true).get_json('#', { 'flat': true });
    var stringifiedTree = JSON.stringify(coreTree);
    var sendableTree = stringifiedTree.substring(1, stringifiedTree.length-1);
    stompClient.send("/app/nodes", {}, sendableTree);
}

and this is the output from the sendNode function above:

{"id":"rootNode","text":"Root node 1","icon":true,"li_attr":{"id":"rootNode","class":"rootNode"},"a_attr":{"href":"#","id":"rootNode_anchor"},"state":{"loaded":true,"opened":false,"selected":false,"disabled":false},"data":{},"parent":"#","type":"default"}

Currently my Node class follows this convention:

@Entity
public class Node { 
  @Id
  @GeneratedValue(strategy=GenerationType.IDENTITY)
  private Long id_incr;

  @JsonProperty
  private String id;

  @JsonProperty
  private String text;

  @JsonProperty
  private String parent;

  @JsonProperty
  private String type;

  @JsonProperty
  private boolean icon;

  @JsonProperty
  private String[] li_attr;

  @JsonProperty
  private String[] a_attr;

  @JsonProperty 
  private String[] state;

  @JsonProperty
  private String[] data;

  private String[] nodeContents;

  protected Node(){ }
  public Node(String content){ }

  public String getId() {
    return id;
  }
  public void setId(String id) {
    this.id = id;
  } 
  public String[] getNodeContents() {
    return this.nodeContents;
  } 
  public void setNodeContents(String[] nodeContents) {
    this.nodeContents = nodeContents;
  }

  public String getText() {
    return text;
  }
  public void setText(String text) {
    this.text = text;
  }
  public String getParent() {
    return parent;
  }
  public void setParent(String parent) {
    this.parent = parent;
  }
  public String getType() {
    return type;
  }
  public void setType(String type) {
    this.type = type;
  }
  public boolean isIcon() {
    return icon;
  }
  public void setIcon(boolean icon) {
    this.icon = icon;
  }
  public String[] getLi_attr() {
    return li_attr;
  }
  public void setLi_attr(String[] li_attr) {
    this.li_attr = li_attr;
  }
  public String[] getA_attr() {
    return a_attr;
  }
  public void setA_attr(String[] a_attr) {
    this.a_attr = a_attr;
  }
  public String[] getState() {
    return state;
  }
  public void setState(String[] state) {
    this.state = state;
  }
  public String[] getData() {
    return data;
  }
  public void setData(String[] data) {
    this.data = data;
  } 
}

My Controller returns the response as so:

@MessageMapping("/nodes")
@SendTo("/topic/nodes")
public String[] nodes(Node node) throws Exception {
    return node.getNodeContents();
}

This is the part of the stack trace I'm having issues with:

org.springframework.messaging.converter.MessageConversionException: Could not read JSON: Can not deserialize instance of java.lang.String[] out of START_OBJECT token
at [Source: [B@632d03de; line: 1, column: 50] (through reference chain: hello.Node["li_attr"])

I could be misunderstanding something, I'm pretty new to websockets and serializing/deserializing JSON. Thank you in advance, and please let me know if you need more information or description!


Solution

  • I recently encounter the same problem a week ago I was not able to retrieve and send objects using websocket sockjs stomp. I suggest to Serialize your Node Object by implementing Serializable. then let see what will happen .

    @Entity
    public class Node implements Serializable{ 
    
      private static final long serialVersionUID = 1L;
    
      @Id
      @GeneratedValue(strategy=GenerationType.IDENTITY)
      private Long id_incr;
    
      @JsonProperty
      private String id;
    
      @JsonProperty
      private String text;
    
      @JsonProperty
      private String parent;
    
      @JsonProperty
      private String type;
    
      @JsonProperty
      private boolean icon;
    
      @JsonProperty
      private String[] li_attr;
    
      @JsonProperty
      private String[] a_attr;
    
      @JsonProperty 
      private String[] state;
    
      @JsonProperty
      private String[] data;
    
      private String[] nodeContents;
    
      protected Node(){ }
      public Node(String content){ }
    
      public String getId() {
        return id;
      }
      public void setId(String id) {
        this.id = id;
      } 
      public String[] getNodeContents() {
        return this.nodeContents;
      } 
      public void setNodeContents(String[] nodeContents) {
        this.nodeContents = nodeContents;
      }
    
      public String getText() {
        return text;
      }
      public void setText(String text) {
        this.text = text;
      }
      public String getParent() {
        return parent;
      }
      public void setParent(String parent) {
        this.parent = parent;
      }
      public String getType() {
        return type;
      }
      public void setType(String type) {
        this.type = type;
      }
      public boolean isIcon() {
        return icon;
      }
      public void setIcon(boolean icon) {
        this.icon = icon;
      }
      public String[] getLi_attr() {
        return li_attr;
      }
      public void setLi_attr(String[] li_attr) {
        this.li_attr = li_attr;
      }
      public String[] getA_attr() {
        return a_attr;
      }
      public void setA_attr(String[] a_attr) {
        this.a_attr = a_attr;
      }
      public String[] getState() {
        return state;
      }
      public void setState(String[] state) {
        this.state = state;
      }
      public String[] getData() {
        return data;
      }
      public void setData(String[] data) {
        this.data = data;
      } 
    }