Java Spring @RequestBody 和 Enum 值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33637427/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 14:51:57  来源:igfitidea点击:

Spring @RequestBody and Enum value

javaspringspring-mvcenums

提问by reos

I Have this enum

我有这个枚举

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

And a class called Review, this class contains a property of the type enum Reos.

还有一个名为 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;
    }
}

Finally I have a controller that receives an object review with the @RequestBody.

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

@RestController
public class ReviewController {

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

If I invoke the controller with

如果我调用控制器

{"reos":"VALUE1"}

There is not problem, but when I invoke with

没有问题,但是当我调用时

{"reos":"A"}

I get this error

我收到这个错误

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.Hymanson.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"])"

I undertand the problem, but I wanted to know a way to tell Spring that for every object with Reos enum use Reos.fromText() instead of Reos.valueof().

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

Is this possible?

这可能吗?

采纳答案by reos

I've found what I need.

我找到了我需要的东西。

http://chrisjordan.ca/post/50865405944/custom-json-serialization-for-enums-using-Hymanson

http://chrisjordan.ca/post/50865405944/custom-json-serialization-for-enums-using-Hymanson

It was 2 steps.

这是2个步骤。

  1. Override the toString method of the Reos enum

    @Override public String toString() { return text; }

  2. Annotate with @JsonCreator the fromText method of the Reos enum.

    @JsonCreator public static Reos fromText(String text)

  1. 覆盖 Reos 枚举的 toString 方法

    @Override public String toString() { 返回文本;}

  2. 使用 @JsonCreator 注释 Reos 枚举的 fromText 方法。

    @JsonCreator 公共静态 Reos fromText(String text)

And that's all.

就这样。

I hope this could help others facing the same problem.

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

回答by Chris Thompson

You need to use a custom MessageConverterthat calls your custom fromText()method. There's an article herethat outlines how to do it.

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

You extend AbstractHttpMessageConverter<Reos>and implement the required methods, and then you register it.

您扩展AbstractHttpMessageConverter<Reos>并实现所需的方法,然后注册它。

回答by Manoj Shrestha

I personally prefer writing my own deserializer class using JsonDeserializerprovided by Hymanson. You just need to write a deserializer class for your enum. In this example:

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

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

Then, we should mark the above class as a deserializer class of Reos as follows:

然后,我们应该将上述类标记为 Reos 的反序列化器类,如下所示:

@JsonDeserialize(using = ReosDeserializer.class)
public enum Reos {

   // your enum codes here
}

That's all. We're all set.

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

In case if you need the serializer for the enum. You can do that in the similar way by creating a serializer class extending JsonSerializerand using the annotation @JsonSerialize.

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

I hope this helps.

我希望这有帮助。