I’m developing JAX-RS based application and Payara server. I want to serialize build in java Color class to String format: color
= "RcolorValu, GColorValue, BColor
value”. For example in form "255,255,255"
. That’s why I’ve written custom serializer:
package org.example;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.awt.*;
import java.io.IOException;
import java.util.logging.Logger;
public class ColorSerializer extends JsonSerializer<Color> {
private static final Logger logger = Logger.getLogger(ColorSerializer.class.getName());
@Override
public void serialize(Color color, JsonGenerator generator, SerializerProvider serializers) throws IOException {
logger.info("Serializing color init ");
if (color == null) {
generator.writeNull();
} else {
String colorString = color.getRed() + "," + color.getGreen() + "," + color.getBlue();
logger.info("Serializing color: " + colorString); // Add logging
generator.writeString(colorString);
}
}
}
I also’ve registered it in ObjectMapperProvider
like below:
package org.example;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.ext.ContextResolver;
import jakarta.ws.rs.ext.Provider;
import java.awt.*;
@Provider
public class ObjectMapperProvider implements ContextResolver<ObjectMapper> {
private final ObjectMapper objectMapper;
public ObjectMapperProvider() {
// Register the JavaTimeModule for date/time serialization
objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
// Register the custom ColorSerializer
SimpleModule module = new SimpleModule();
module.addSerializer(Color.class, new ColorSerializer());
objectMapper.registerModule(module);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
}
@Override
public ObjectMapper getContext(Class<?> type) {
return objectMapper;
}
}
My Employee entity class with favoriteColor
property and annotation @JsonSerialize(using = ColorSerializer.class)
which should cause serialization is in form like below:
package org.example;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import jakarta.json.bind.annotation.JsonbDateFormat;
import jakarta.persistence.*;
import java.awt.*;
import java.io.Serializable;
import java.util.Date;
@Entity
@Table(name = "Employee")
public class Employee implements Serializable {
@Id
@Column(name = "EMPLOYEE_ID")
private Long id;
@Column(name = "FIRST_NAME")
private String firstName;
@Column(name = "LAST_NAME")
private String lastName;
public Date getHireDate() {
return hireDate;
}
public void setHireDate(Date hireDate) {
this.hireDate = hireDate;
}
@Column(name = "HIRE_DATE")
@Temporal(TemporalType.DATE)
@JsonbDateFormat("yyyy-MM-dd")
private Date hireDate;
@Column(name = "GENDER")
@Enumerated(EnumType.STRING)
private Gender gender;
public Color getFavoriteColor() {
return favoriteColor;
}
public void setFavoriteColor(Color favoriteColor) {
this.favoriteColor = favoriteColor;
}
@Column(name = "FAVORITE_COLOR")
@Convert(converter = ColorConverter.class)
@JsonSerialize(using = ColorSerializer.class)
private Color favoriteColor;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Gender getGender() {
return gender;
}
public void setGender(Gender gender) {
this.gender = gender;
}
}
And my EmployeeResource with list of employee endpoint which should return list of Employees:
package org.example;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import java.util.List;
import java.util.logging.Logger;
@Path("/employee")
@RequestScoped
public class EmployeeResource {
@Inject
private EmployeeService employeeService;
private static final Logger logger = Logger.getLogger(EmployeeService.class.getName());
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("/")
public List<Employee> getEmployees() {
logger.info("Retrieving all employees");
return employeeService.getAllEmployees();
}
}
Besides that I configured Converter which works. I figured out it from logs but Serializer dosen’t :
package org.example;
import jakarta.persistence.AttributeConverter;
import jakarta.persistence.Converter;
import java.awt.*;
import java.util.logging.Logger;
@Converter(autoApply = true)
public class ColorConverter implements AttributeConverter<Color, String> {
private static final Logger logger = Logger.getLogger(ColorSerializer.class.getName());
@Override
public String convertToDatabaseColumn(Color attribute) {
logger.info("converter color color: " + attribute.toString()); // Add logging
return attribute.getRed() +
"," +
attribute.getGreen() +
"," +
attribute.getBlue();
}
@Override
public Color convertToEntityAttribute(String dbData) {
if (dbData == null || dbData.isBlank()) {
return null;
}
String[] parts = dbData.split(",");
Color color = new Color(Integer.parseInt(parts[0]), Integer.parseInt(parts[1]), Integer.parseInt(parts[2]));
logger.info("Converting DB data to color: " + color.toString()); // Add logging
return color;
}
}
In any case I receive every time json response like:
Example data in database:
I don’t know how to leverage using my Custom Serializer instead of build in.