将枚举名称和字符串值作为 api 响应返回

Posted

技术标签:

【中文标题】将枚举名称和字符串值作为 api 响应返回【英文标题】:Returning both enum name and string value as api response 【发布时间】:2020-08-17 14:08:40 【问题描述】:

这是我的枚举类

public enum Status 
    OPEN("Open"),
    IN_PROCESS("In Process"),
    ON_HOLD("On Hold"),
    RESOLVED("Resolved");

    private String status;

    Status(String status) 
        this.status = status;
    

    @JsonValue
    public String getStatus() 
        return status;
    

我的 api 目前正在将 Status 的值作为字符串返回,这是返回的 json 响应的一部分。 "id":1,"name":"John","subject":"Help","status":"Open"

如何让我的回复类似于"status": "id": "ON_HOLD", "value": "On Hold"

这是使用枚举状态的模型,部分省略。

public class Ticket 
    private @Id @GeneratedValue(strategy=GenerationType.IDENTITY) Long id;
    private String name;
    private String subject;

    @Enumerated(EnumType.STRING)
    private Status status;

    //getters, setters, etc.

我的票控制器

@RestController
public class TicketController 
    private final TicketRepository repository;
    private final TicketResourceAssembler assembler;

    TicketController(TicketRepository repository, TicketResourceAssembler assembler) 
        this.repository = repository;
        this.assembler = assembler;
    

    @GetMapping("/tickets/id")
    public EntityModel<Ticket> one(@PathVariable Long id) 

        Ticket ticket = repository.findById(id).orElseThrow(() -> new EntityNotFoundException(Ticket.class, "id", id.toString()));
        return assembler.toModel(ticket);
    

汇编器

@Component
public class TicketResourceAssembler implements RepresentationModelAssembler<Ticket, EntityModel<Ticket>> 
    @Override
    public EntityModel<Ticket> toModel(Ticket ticket) 

        EntityModel<Ticket> ticketResource = new EntityModel<>(ticket,
            linkTo(methodOn(TicketController.class).one(ticket.getId())).withSelfRel(),
            linkTo(methodOn(TicketController.class).all()).withRel("tickets"));

        return  ticketResource;
    

存储库只是一个扩展至JpaRepository 的接口。

【问题讨论】:

你想如何在 api 请求中传递枚举? @GolamMazidSajib 使用名称 (IN_PROCESS, ON_HOLD) 那么你只能使用@JsonGetter注解。在机票类...@JsonGetter public JsonNode getStatus() return JsonNodeFactory.instance.objectNode().put("id",status.getName()).put("value",status.getValue()); 【参考方案1】:

需要添加getName()方法枚举类:

public enum Status 
        OPEN("Open"),
        IN_PROCESS("In Process"),
        ON_HOLD("On Hold"),
        RESOLVED("Resolved");

        private String status;

        Status(String status) 
            this.status = status;
        

        public String getName() 
            return this.name();
        

        @JsonValue
        public String getStatus() 
            return status;
        
    

现在您需要在 Ticket 类中为状态添加 @JsonGetter 方法:

@JsonGetter
    public JsonNode getStatus() 
        return JsonNodeFactory.instance.objectNode().put("id",status.getName()).put("value",status.getValue());
    

【讨论】:

添加后,如何使用getStatus()比较值?我的一些代码现在显示错误Incompatible operand types JsonNode and Status,这些是比较代码,如if (ticket.getStatus() == Status.RESOLVED) 我明白了...所以我将有 2 个字段,一个只是一个枚举值,另一个返回一个带有 idvalue 的 json 对象? 在序列化jackson期间找到@JsonGetter方法...如果没有找到则搜索默认getter方法...所以你需要设置getter方法...或者你可以使用自定义序列化【参考方案2】:

我建议的一个不错的解决方案是使用@JsonProperty

public enum Status 

    @JsonProperty("LORA/TRACK_RFID")
    IN_PROCESS("In Process");

通过使用这个注解,我们只是告诉 Jackson 将 @JsonProperty 的值映射到使用这个值注解的对象。

由于上述声明,将有字符串:"In Process"

【讨论】:

以上是关于将枚举名称和字符串值作为 api 响应返回的主要内容,如果未能解决你的问题,请参考以下文章

使用 Graphene 返回具有字符串值的枚举列表

SystemVerilog枚举可以为null吗?

React Promise 不会返回值

枚举值返回为数字 [重复]

对象属性 Object.getOwnPropertyNames() Object.keys for...in

具有值和显示名称的typescript枚举