I'm creating a Spring JPA project with the following structure:
public class Pipeline {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String name;
private SourceConfig sourceConfig;
private SinkConfig sinkConfig;
...
...
}
public abstract class SourceConfig {
private long id;
private String name;
}
public abstract class SinkConfig {
private long id;
private String name;
}
public KafkaSourceConfig extends SourceConfig {
private String topic;
private String messageSchema;
}
public MysqlSourceConfig extends SourceConfig {
private String databaseName;
private String tableName;
}
Now when the client passes the following JSON, how would the program know which SourceConfig subclass to add to the Pipeline object?
{
"name": "mysql_to_bq_1",
"sourceConfig": {
"source": "MYSQL",
},
"sinkConfig": {
},
"createdBy": "paul"
}
CodePudding user response:
You need to specify what class type you want to use like this So instead of
private SourceConfig sourceConfig;
use
private KafkaSourceConfig kafkaSourceConfig;
Or you can keep it like you have but in case you want use some property of child class you have to cast it to that class type.
e.g.
KafkaSourceConfig kafkaSourceConfig = (KafkaSourceConfig)sourceConfig;
it can look like this
if(sourceConfig instanceOf KafkaSourceConfig)
{
KafkaSourceConfig ksc = (KafkaSourceConfig)sourceConfig;
}
if(sourceConfig instanceOf MysqlSourceConfig)
{
MysqlSourceConfig mysc= (MysqlSourceConfig)sourceConfig;
}
CodePudding user response:
I looked around a bit and came to know about Polymorphic Deserialization, that's supported by Jackson.
Essentially, we have to infer from some field which subclass to refer to from the JSON that is provided.
For example,
"sourceConfig": {
"source": "MYSQL"
}
This should call MysqlSourceConfig's constructor. So the below code does the work.
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Data
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
property = "source",
defaultImpl = MysqlSourceConfig.class,
visible = true)
@JsonSubTypes({
@JsonSubTypes.Type(value = MysqlSourceConfig.class, name = "MYSQL"),
@JsonSubTypes.Type(value = KafkaSourceConfig.class, name = "KAFKA"),
})
public abstract class SourceConfig {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Enumerated(value = EnumType.STRING)
@NotNull
private Source source;
}