I have a class I want to deserlialize into a Java into a class. One of the class attributes is itself a serializable class which has one primitive (String) parameter and really represents an aliased String, i.e., a String with some extra stuff around it to make sure it comes in the correct format. This is useful in a variety of applications (e.g., identifiers), in this case it's a Cron string that has to have specific representation. So I have
class ScheduleConfigurations {
private Cron cron;
private Set<Cron> overrides;
// other attributes, getters/setters, constructor
}
class Cron {
private String cronString;
private void validate() { // validates string has correct representation }
// getters, setters, constructor
}
Obviously the standard Jackson deserializer expects a JSON of the format
{
"cron": {
"cronString": "someCronString",
"overrides": [
{ "cronString": "someCronString1" },
{ "cronString": "someCronString2" }
]
}
However, the Cron
class is clearly just an aliased String. I'd want the above to be serialized/deserialized as
{
"cron": "someCronString",
"overrides": ["someCronString1", "someCronString2"]
}
I can make that happen with a custom serializer with a bunch of boilerplate, but I am looking for an elegant way to say to Jackson "hey, this class has one String attribute, just pass through it and treat its serialized representation as its only attribute".
Since you want the entire object to be (de)serialized as a string, it's very easy:
@JsonSerialize(using = ToStringSerializer.class)
class Cron {
private String cronString;
public Cron(String cronString) { // Called by Jackson when deserializing from JSON string
this.cronString = cronString;
}
@Override
public String toString() { // Called by Jackson when serializing to JSON
return this.cronString;
}
}
Since the class is just a wrapper around a string, you don't even need getter, setter, or other constructor, not even for other Java code, though you can of course still have them.
Test
ScheduleConfigurations configObj = new ScheduleConfigurations();
configObj.setCron(new Cron("someCronString"));
configObj.setOverrides(new LinkedHashSet<>(Arrays.asList(
new Cron("someCronString1"), new Cron("someCronString2"))));
ObjectMapper mapper = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT);
System.out.println(mapper.writeValueAsString(configObj));
String json = "{\r\n" +
" \"cron\" : \"someCronString\",\r\n" +
" \"overrides\" : [ \"someCronString1\", \"someCronString2\" ]\r\n" +
"}";
ScheduleConfigurations configObj = new ObjectMapper().readValue(json, ScheduleConfigurations.class);
System.out.println("cron = " + configObj.getCron());
System.out.println("overrides = " + configObj.getOverrides());
Output
{
"cron" : "someCronString",
"overrides" : [ "someCronString1", "someCronString2" ]
}
cron = someCronString
overrides = [someCronString1, someCronString2]