Hi. I'm using jackson-databind 2.9.8
What i do that is Converting 'Message' Class that including Sting message
to 'Protocol' Interface.
following is Message Object.
public class Message {
private String message;
public void setMessage(String message) {
this.message = message;
}
public String getMessage() {
return this.message;
}
}
following is Protocol
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY,
property = "protocolType")
@JsonSubTypes({
@JsonSubTypes.Type(value = AProtocol.class, name = "A"),
@JsonSubTypes.Type(value = BProtocol.class, name = "B"),
@JsonSubTypes.Type(value = CProtocol.class, name = "C")
})
public interface Protocol {
void execute();
ProtocolType getProtocolType();
}
there are some abstract classes that implements Protocol interface
(AProtocol, BProtocol, CProtocol)
Protocol interface has 2 method.
one is execute(). this method will be used to executing business logic
after deserialized.
each subclasses that implementing Protocol interface will execute business
logic polymorphically via execute().
like this.
public void execute(Protocol protocol) {
protocol.execute();
}
other one is getProtocolType().
this method will provide ProtocolType to ObjectMapper via public getter.
(so @JsonTypeInfo annotation's property value is 'protocolType')
actually, if I change A~C Protocol abstract class to concreteclass, error
will not occured.
but there are more Low-level SubProtocols that implementing A~CProtocol.
(A~CProtocol is not concrete class.)
like this
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY,
property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = A1Protocol.class, name = "A1"),
@JsonSubTypes.Type(value = A2Protocol.class, name = "A2")
})
public abstract class AProtocol implements Protocol {
@Override
public ProtocolType getProtocolType() {
return ProtocolType.A;
}
}
and A1Protocol is like this
public class A1Protocol extends AProtocol {
private String sender;
private String message;
public A1Protocol(String sender, String message) {
this.sender = sender;
this.message = message;
}
public void execute() {
System.out.println(this.getClass().getSimpleName());
System.out.println("sender : " + sender + ", message = " + message);
}
}
if A1Protocol convert to Message, Message.getMessage()'s result will be
{"protocolType": "A", "type" : "A1", "sender":"sender1", "message":"message1"}
and following is MessageProtocolConverter.
public class MessageProtocolConverter {
public Message protocolSerialize(Protocol protocol) {
ObjectMapper objectMapper = new ObjectMapper();
String json = null;
try {
json = objectMapper.writeValueAsString(protocol);
} catch (JsonProcessingException e) {
System.out.println("Protocol to Message Serialization Failure");
}
Message message = new Message();
message.setMessage(json);
return message;
}
public Protocol messageDeserialize(Message message) {
ObjectMapper objectMapper = new ObjectMapper();
Protocol protocol = null;
try {
protocol = objectMapper.readValue(message.getMessage(),
Protocol.class);
} catch (IOException e) {
e.printStackTrace();
System.out.println("Message to Protocol Deserialization Failure");
}
return protocol;
}
}
i dont want to annotate concrete classes' name in this class.
what i want to do is following.
- Serialize
1. Protocol protocol = new A1Protocol("sender1", "message1"); // Build
Low-level SubProtocolClass
2. Message message = new Message();
3. message.setMessage(objectMapper.writeValueAsString(protocol));
4. message.getMessage(); // result is {"protocolType": "A", "type" : "A1",
"sender":"sender1", "message":"message1"}
5. send to Stream
- Deserialize
1. Receive StringMessage // {"protocolType": "A", "type" : "A1",
"sender":"sender1", "message":"message1"} (A1Protocol Format)
2. Message message = new Message().setMessage(StringMessage);
3. Protocol protocol = objectMapper.readValue(message.getMessage(),
Protocol.class);
4. protocol.execute(); // run A1Protocol.execute().
5. print to console with A1Protocol's execute() logic
following is test.
public class Main {
public static void main(String[] args) {
MessageProtocolConverter messageProtocolConverter = new
MessageProtocolConverter();
Protocol protocol = new A1Protocol("sender1", "messag1");
Message message = messageProtocolConverter.protocolSerialize(protocol);
System.out.println(message.getMessage());
Protocol deserializedProtocol =
messageProtocolConverter.messageDeserialize(message);
deserializedProtocol.execute();
}
}
and following is error
{"type":"A1","protocolType":"A"}
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot
construct instance of `protocol.a.AProtocol` (no Creators, like default
construct, exist): abstract types either need to be mapped to concrete
types, have custom deserializer, or contain additional type information
at [Source: (String)"{"type":"A1","protocolType":"A"}"; line: 1, column:
29]
at
com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
at
com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1452)
at
com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1028)
at
com.fasterxml.jackson.databind.deser.AbstractDeserializer.deserialize(AbstractDeserializer.java:265)
at
com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer._deserializeTypedForId(AsPropertyTypeDeserializer.java:130)
at
com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:97)
at
com.fasterxml.jackson.databind.deser.AbstractDeserializer.deserializeWithType(AbstractDeserializer.java:254)
at
com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:68)
at
com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4013)
at
com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3004)
at
MessageProtocolConverter.messageDeserialize(MessageProtocolConverter.java:26)
at Main.main(Main.java:13)
Message to Protocol Deserialization Failure
Exception in thread "main" java.lang.NullPointerException
at Main.main(Main.java:14)
Process finished with exit code 1
--
You received this message because you are subscribed to the Google Groups
"jackson-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
For more options, visit https://groups.google.com/d/optout.