Serializing and Deserializing Java Records with "stock" Jakarta EE 9 JSON-B 📎
<dependency>
<groupId>org.eclipse</groupId>
<artifactId>yasson</artifactId>
<version>2.0.2</version>
</dependency>
A Java Record:
public record Workshop(String title, Date date, String description) {
}
can be serialized by configuring JSON-B to use private fields with a custom PropertyVisibilityStrategy:
public class PrivateVisibilityStrategy implements PropertyVisibilityStrategy {
@Override
public boolean isVisible(Field field) {
return true;
}
@Override
public boolean isVisible(Method method) {
return false;
}
}
The PrivateVisibilityStrategy
has to be passed to JsonbConfig
:
import jakarta.json.bind.JsonbBuilder;
import jakarta.json.bind.JsonbConfig;
public interface Mapper {
final static JsonbConfig config = new JsonbConfig()
.withFormatting(true)
.withPropertyVisibilityStrategy(new PrivateVisibilityStrategy());
static String save(Workshop workshop) {
var jsonb = JsonbBuilder.create(config);
return jsonb.toJson(workshop);
}
}
To read the Workshop
record back, you will have to create a factory method annotated with @JsonbCreator:
public record Workshop(String title, Date date, String description) {
@JsonbCreator
public static Workshop create(String title, Date date, String description) {
return new Workshop(title, date, description);
}
}
The Jakarta JSON-B runtime will use the factory method instead of the default constructor to create a record instance and populate it with the JSON data.
The parameter names have to be available for reflection. Either make the parameter names available via a compiler switch: (<maven.compiler.parameters>true</maven.compiler.parameters>
)
or directly annotate the parameters:
import jakarta.json.bind.annotation.JsonbProperty;
//...
@JsonbCreator
public static Workshop create(@JsonbProperty("title") String title,
@JsonbProperty("date") Date date,
@JsonbProperty("description") String description) {
return new Workshop(title, date, description);
}
Now the Workshop
record:
public record Workshop(String title, Date date, String description) {
@JsonbCreator
public static Workshop create(String title,Date date,String description) {
return new Workshop(title, date, description);
}
}
can be serialized and deserialized in a Java SE application:
@Test
public void serializeThenDeserialize() {
var workshop = new Workshop("hello",new Date(),"nothing");
var serialized = Mapper.save(workshop);
System.out.println(serialized);
var copy = Mapper.load(serialized);
assertEquals(workshop.title(), copy.title());
}
The test generates the following output:
{
"date": "2021-10-07T07:58:17.606Z[UTC]",
"description": "nothing",
"title": "hello"
}