【问题标题】:Spring @RequestBody and Enum valueSpring @RequestBody 和枚举值
【发布时间】:2015-11-10 18:55:51
【问题描述】:

我有这个枚举

public enum Reos {

    VALUE1("A"),VALUE2("B"); 

    private String text;

    Reos(String text){this.text = text;}

    public String getText(){return this.text;}

    public static Reos fromText(String text){
        for(Reos r : Reos.values()){
            if(r.getText().equals(text)){
                return r;
            }
        }
        throw new IllegalArgumentException();
    }
}

还有一个名为 Review 的类,该类包含 enum Reos 类型的属性。

public class Review implements Serializable{

    private Integer id;
    private Reos reos;

    public Integer getId() {return id;}

    public void setId(Integer id) {this.id = id;}

    public Reos getReos() {return reos;}

    public void setReos(Reos reos) {
        this.reos = reos;
    }
}

最后我有一个控制器,它通过 @RequestBody 接收对象审查。

@RestController
public class ReviewController {

    @RequestMapping(method = RequestMethod.POST, value = "/reviews")
    @ResponseStatus(HttpStatus.CREATED)
    public void saveReview(@RequestBody Review review) {
        reviewRepository.save(review);
    }
}

如果我用

调用控制器
{"reos":"VALUE1"}

没有问题,但是当我用

调用时
{"reos":"A"}

我收到此错误

Could not read document: Can not construct instance of com.microservices.Reos from String value 'A': value not one of declared Enum instance names: [VALUE1, VALUE2] at [Source: java.io.PushbackInputStream@23ce847a; line: 1, column: 40] (through reference chain: com.microservices.Review["reos"]); nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not construct instance of com.microservices.Reos from String value 'A': value not one of declared Enum instance names: [VALUE1, VALUE2] at [Source: java.io.PushbackInputStream@23ce847a; line: 1, column: 40] (through reference chain: com.microservices.Review["reos"])"

我理解了这个问题,但我想知道一种方法来告诉 Spring 对于每个带有 Reos 枚举的对象都使用 Reos.fromText() 而不是 Reos.valueof()。

这可能吗?

【问题讨论】:

    标签: java spring spring-mvc enums


    【解决方案1】:

    我找到了我需要的东西。 http://chrisjordan.ca/post/50865405944/custom-json-serialization-for-enums-using-jackson.

    这是两步。

    1. 重写 Reos 枚举的 toString 方法
    @Override
    public String toString() {
        return text;
    }
    
    1. 使用 @JsonCreator 注释 Reos 枚举的 fromText 方法。
    @JsonCreator
    public static Reos fromText(String text)
    

    仅此而已。

    我希望这可以帮助其他面临同样问题的人。

    【讨论】:

    • JsonCreator 注释(第 2 步)解决了我正在处理的问题。很好的答案。
    【解决方案2】:

    我个人更喜欢使用jackson 提供的JsonDeserializer 编写我自己的反序列化器类。您只需要为您的枚举编写一个反序列化器类。在这个例子中:

    class ReosDeserializer extends JsonDeserializer<Reos> {
    
        @Override
        public Reos deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
    
            ObjectCodec oc = jsonParser.getCodec();
            JsonNode node = oc.readTree(jsonParser);
    
            if (node == null) {
                return null;
            }
    
            String text = node.textValue(); // gives "A" from the request
    
            if (text == null) {
                return null;
            }
    
            return Reos.fromText(text);
        }
    }
    

    那么,我们应该将上面的类标记为Reos的反序列化类,如下:

    @JsonDeserialize(using = ReosDeserializer.class)
    public enum Reos {
    
       // your enum codes here
    }
    

    就是这样。我们都准备好了。

    如果您需要enum 的序列化程序。您可以通过创建一个扩展 JsonSerializer 的序列化程序类并使用注释 @JsonSerialize 以类似的方式做到这一点。

    我希望这会有所帮助。

    【讨论】:

      【解决方案3】:

      您需要使用自定义 MessageConverter 来调用您的自定义 fromText() 方法。有一篇文章 here 概述了如何做到这一点。

      你扩展AbstractHttpMessageConverter&lt;Reos&gt;并实现所需的方法,然后你注册它。

      【讨论】:

      • 我认为这仅在我的 Review 对象仅包含 Reos 值时才有效。但在我的例子中,对象 Review 有很多属性。所以我必须映射每个属性来获取评论对象。另一个问题是我有另一个使用 Reos 枚举的对象,所以我必须为每个对象编写一个转换器。我想要一种编写类似 PropertyEditor 的方法,我只是为 Reos 值编写一个方法。
      猜你喜欢
      • 1970-01-01
      • 2017-11-10
      • 2022-01-19
      • 1970-01-01
      • 2015-08-22
      • 1970-01-01
      • 2018-10-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多