1

I'm developing a java client/server architecture where a client sends a message to the server using jackson. Exchanged data is defined by the Message class:

public class Message {
    private Header header; //Object that contains only String
    private Object pdu;

    public Message() {
    }

    // Get & Set
    [...]
}

This class can contain any object thanks to the pdu field. For example, a Data object can be instantiated and added as message.

public class Data{
    private String name;
    private String type;

    public Data() {
    }

    // Get & Set
    [...]
}

On the server side, when the message is received, I would like to retrieve the nested object (Data). However, the following exception occurs "com.fasterxml.jackson.databind.node.ObjectNode cannot be cast to Model.Data" when I try to cast the pdu into Data object. How can I perform that for any object.

Here is the server snippet code:

Socket socket = serverSocket.accept();
is = new DataInputStream(socket.getInputStream());
os = new DataOutputStream(socket.getOutputStream());
BufferedReader in = new BufferedReader(new InputStreamReader(is));

ObjectMapper mapper = new ObjectMapper();
Message message = mapper.readValue(in.readLine(), Message.class);

Data pdu = (Data) message.getPdu(); // Exception here

And here the client snippet code:

Message msg = new Message(header, new Data("NAME", "TYPE"));
ObjectMapper mapper = new ObjectMapper();
String jsonStr = mapper.writeValueAsString(msg);
PrintWriter pw = new PrintWriter(os);
pw.println(jsonStr);
pw.flush();

Note: The message sent by the client and received by the server is formatted as follow: Message{header=Header{type='TYPE', senderAddr='ADDR', senderName='NAME'}, pdu={"name":"NAME","type":"TYPE"}}

Steve23
  • 113
  • 5

2 Answers2

2

There is no way to figure out what pdu Java type is just from just {"name":"NAME", "type":"TYPE"} JSON. If pdu can store multiple different object types (currently it's declared as Object) a JSON field has to be used to tell Jackson what is the actual Java type e.g. by using @JsonTypeInfo:

@JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "type")
@JsonSubTypes({
    @JsonSubTypes.Type(value = DataA.class, name = "data-a"),
    @JsonSubTypes.Type(value = DataB.class, name = "data-b")
}) 

Another approach would be to write a custom serializer/deserializer for pdu field as explained here.

Karol Dowbecki
  • 43,645
  • 9
  • 78
  • 111
0

I know this is an old question, but you can get Jackson to do what Karol described under the hood, using the object class as the type source, which saves you from having to enumerate the types. You still have to be sure that any object you use will be serializable, it's not magic. Anyway solution is in the javadoc for @JsonTypeInfo, declare your field as:

    @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, property="pduClass")
    Object getPdu();

This will add a "pduClass" field to the json representation, but won't affect the java model

A D
  • 51
  • 3