带有 Payara 服务器的 Jax-RS 应用程序无法通过自定义序列化器序列化颜色

问题描述 投票:0回答:1

我正在开发基于 JAX-RS 的应用程序和 Payara 服务器。我想将 java Color 类中的构建序列化为字符串格式:

color
=
"RcolorValu, GColorValue, BColor
值”。例如以
"255,255,255"
形式。这就是我编写自定义序列化程序的原因:

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);
        }
    }
}

我也在

ObjectMapperProvider
中注册了它,如下所示:

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;
    }
}

我的 Employee 实体类具有

favoriteColor
属性和注释
@JsonSerialize(using = ColorSerializer.class)
,它应该导致序列化,其形式如下:

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;
    }
}

我的 EmployeeResource 包含员工端点列表,应返回员工列表:

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();
    }   
}

除此之外,我配置了可以工作的转换器。我从日志中找出了它,但序列化器没有:

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;
    }
}

无论如何,我每次都会收到 json 响应,例如:

enter image description here

数据库中的示例数据:

enter image description here

我不知道如何利用我的自定义序列化器而不是内置。

jakarta-ee jackson jax-rs payara jsonserializer
1个回答
0
投票

您在同一应用程序中混合 JSON-Binding 和 Jackson 注释。 JSON-Binding 注释位于以

jakarta.json.bind.annotation
开头的包中,例如代码中的
JsonbDateFormat
注释。 Jackson 注释位于以
com.fasterxml.jackson
开头的包中,例如
JsonSerialize
。您只能使用其中之一,而不能同时使用两者。 Payara 不支持开箱即用的 Jackson 注释。如果启用 Jackson,则 JSON-Binding 注释将被忽略,因为 Jackson 不支持 JSON-Binding。

了解您是否使用标准 JSON 绑定或启用了 Jackson(如此处所述)。如果您没有启用 Jackson,则

JsonSerialize
注释和
ObjectMapperProvider
中的所有 Jackson 配置都将被忽略。那么你应该在 JSON-Binding 中使用
JsonbSerializer
来代替。它记录在 Jakarta EE 教程中:https://jakarta.ee/learn/docs/jakartaee-tutorial/current/web/jsonb/jsonb.html#_using_customizations

或者您应该启用 Jackson 并用 Jackson 支持的等效内容替换

JsonbDateFormat
注释和其他 JSON-B 注释。

您的

ColorConverter
类是持久实体的转换器。当数据存储到数据库时使用它。当为 REST 响应构建 JSON 时,它会被忽略。

© www.soinside.com 2019 - 2024. All rights reserved.