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.

Reply via email to