You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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:

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 22:42:51