Java枚举BusinessCustomersStatus单个对象映射时获取shortName而非fullName的实现方法问询
Looks like you're hitting a common Jackson serialization quirk where @JsonValue enforces a global serialization behavior for your enum, but you need different output depending on whether you're returning a list or a single DTO. Let's break down the simplest and most maintainable fixes for this:
Option 1: Control the mapping directly in your DTO converter (Recommended)
Since you're using a mapper (businessCustomersMapper.toFullDTO()) to convert the entity to your FullDTO, this is the cleanest place to override the enum's serialization behavior.
If you're using MapStruct, update your mapper interface to explicitly map the enum's shortName instead of relying on Jackson's default:
@Mapper(componentModel = "spring") public interface BusinessCustomersMapper { // Map the enum's shortName directly to the DTO's status field @Mapping(source = "businessCustomers.status.shortName", target = "status") FullDTO toFullDTO(BusinessCustomers businessCustomers); // Keep your list mapping as-is (it will use @JsonValue for fullName) List<SummaryDTO> toSummaryList(List<BusinessCustomers> businessCustomers); }
If you're doing manual mapping in your mapper class, just explicitly fetch the shortName when building the FullDTO:
public FullDTO toFullDTO(BusinessCustomers businessCustomers) { FullDTO dto = new FullDTO(); // ... other mappings dto.setStatus(businessCustomers.getStatus().getShortName()); // Use shortName here return dto; }
This approach keeps your enum's global serialization behavior intact for the list endpoint, while giving you full control over the single DTO's output.
Option 2: Use a custom Jackson serializer for the FullDTO
If you prefer to handle this at the serialization level instead of the mapper, you can create a custom serializer specifically for your FullDTO's status field.
First, create the serializer:
public class BusinessCustomersStatusShortNameSerializer extends StdSerializer<BusinessCustomersStatus> { public BusinessCustomersStatusShortNameSerializer() { super(BusinessCustomersStatus.class); } @Override public void serialize(BusinessCustomersStatus status, JsonGenerator gen, SerializerProvider provider) throws IOException { gen.writeString(status.getShortName()); } }
Then, annotate the status field in your FullDTO to use this serializer:
public class FullDTO { // ... other fields @JsonSerialize(using = BusinessCustomersStatusShortNameSerializer.class) private BusinessCustomersStatus status; // ... getters/setters }
This way, when Jackson serializes FullDTO, it will use the short name, while your list DTOs (without this annotation) will continue using the @JsonValue-defined full name.
Option 3: Use Jackson's @JsonView to split serialization behavior
If you want a more flexible, view-based approach, you can use Jackson's @JsonView annotations to define different serialization rules for list vs detail views.
First, define your view classes:
public class Views { public static class ListView {} public static class DetailView extends ListView {} }
Update your enum to attach the fields to specific views (and remove the global @JsonValue if you want full control):
public enum BusinessCustomersStatus { // ... enum constants @Getter @JsonView(Views.DetailView.class) private String shortName; @Getter @JsonView(Views.ListView.class) private String fullName; // ... constructor and fromStatus method }
Then, annotate your controller methods to use the appropriate view:
// List endpoint uses ListView to return fullName @GetMapping("/list") @JsonView(Views.ListView.class) public List<SummaryDTO> getBusinessCustomersList() { // ... logic } // Single object endpoint uses DetailView to return shortName @GetMapping("/{id}") @JsonView(Views.DetailView.class) public ResponseEntity<FullDTO> getBusinessCustomer(@PathVariable Long id) { return businessCustomersService.findById(id).map( businessCustomers -> businessCustomersMapper.toFullDTO(businessCustomers) ).orElse(ResponseEntity.notFound().build()); }
This is great if you have multiple fields that need different serialization across views, but it adds a bit more complexity compared to the first option.
内容的提问来源于stack exchange,提问作者Peter Penzov

