I wonder what's the recommended way to generate POJOs for Json schemas with "anyOf" fields?
For example, given the following json schemas:
hobby.json{
"anyOf": [
{ "type": {"$ref": "./exercise.json" } },
{ "type": {"$ref": "./music.json" } }
]
}
exercise.json
{
"type": "object"
"properties" {
"hobbyType": {"type": "string"}
"exerciseName": { "type": "string" },
"timeSpent": { "type": "number" },
"place": { "type": "string" }
}
}
music.json
{
"type": "object"
"properties" {
"hobbyType": {"type": "string"}
"instrument": { "type": "string" },
"timeSpent": { "type": "number" }
}
}
How could I generate a POJO for Hobby.java
with Jackson?
The approach I ended up taking is using polymorphic marshaling/unmarshaling functionality provided by Jackson.
Specifically -
hobby
to be an interface and annotate it with @JsonTypeInfo
and @JsonSubTypes
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
property = "hobbyType",
include = JsonTypeInfo.As.EXISTING_PROPERTY,
visible = true
)
@JsonSubTypes({
@Type(value = Exercise.class, name = "exercise"),
@Type(value = Music.class, name = "music")
})
public interface Hobby {
}
Exercise.java
and Music.java
that implements this interface@Builder
@Data
@AllArgsConstructor
public class Exercise implements Hobby {
@JsonProperty("hobbyType")
@Builder.Default
@NonNull
private final String hobbyType = "exercise";
@JsonProperty("exerciseName")
private String exerciseName;
@JsonProperty("place")
private String place;
//... (other fields)
}
Hobby
for serialization and deserialization.// create a Hobby object
Hobby exercise = Exercise.builder().exerciseName("swimming").place("swimmingPool").build();
// serialization
String serializedHobby = new ObjectMapper.writeValueAsString(exercise)
/**
serializedHobby looks like this ->
{
"hobbyType": "exercise",
"exerciseName": "swimming",
"place": "swimmingPool"
}
*/
// deserialization
Hobby deserializedObject = new ObjectMapper.readValue(jsonString, Hobby.class)
// deserializedObject.getClass() would return Exercise.java or Music.java based on the hobbyType