2015-11-10 16 views
10

mam ten enumWiosna @RequestBody i wartość 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(); 
    } 
} 

I klasy o nazwie Review, klasa ta zawiera właściwość typu wyliczenia 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; 
    } 
} 

Wreszcie Mam kontroler, który odbiera przeglądu obiektów z @RequestBody.

@RestController 
public class ReviewController { 

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

Gdybym wywołać kontrolera z

{"reos":"VALUE1"} 

Nie ma problemu, ale gdy przywołuję z

{"reos":"A"} 

otrzymuję ten błąd

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: [email protected]; 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: [email protected]; line: 1, column: 40] (through reference chain: com.microservices.Review["reos"])" 

I undertand problem, ale chciałem wiedzieć sposób powiedzieć Spring, że dla każdego obiektu z Reos enum użyj Reos.fromText() zamiast Reos.valueof().

Czy to możliwe?

Odpowiedz

11

Znalazłem to, czego potrzebuję.

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

Było 2 kroki.

  1. zastąpić metodę toString z wyliczenia REOs

    @Override public String toString() { tekst powrotu; }

  2. Adnotacja z @JsonCreator z metody fromText z wyliczenia Reos.

    @JsonCreator public static REOs fromText (String text)

I to wszystko.

Mam nadzieję, że pomoże to innym osobom zmierzyć się z tym samym problemem.

+2

Adnotacja JsonCreator (krok 2) rozwiązała problem, nad którym pracowałem. Niezła odpowiedź. –

1

Należy użyć niestandardowego MessageConverter, który wywołuje niestandardową metodę fromText(). Jest artykuł here, który opisuje, jak to zrobić.

Poszerzasz AbstractHttpMessageConverter<Reos> i zaimplementujesz wymagane metody, a następnie je zarejestrujesz.

+0

Myślę, że działa to tylko wtedy, gdy mój obiekt Review zawiera tylko wartość Reos. Ale w moim przypadku obiekt Przegląd ma wiele właściwości. Muszę więc zmapować każdą właściwość, aby uzyskać obiekt recenzji. Kolejnym problemem jest to, że mam inne obiekty, które używają enum Reos, więc muszę napisać konwerter dla każdego obiektu. Chcę, aby napisać coś podobnego do PropertyEditor, gdzie po prostu napisałem metodę dla wartości Reos. – reos

1

Osobiście wolę pisać własną klasę deserializatora przy użyciu JsonDeserializer, którą należy podać pod numerem jackson. Musisz tylko zapisać klasę deserializatora dla swojego wyliczenia.W tym przykładzie:

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

Następnie należy zaznaczyć powyższą klasę jako klasę Deserializator z REOs następująco:

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

    // your enum codes here 
} 

to wszystko. Wszystko gotowe.

Jeśli potrzebujesz serializatora dla enum. Możesz to zrobić w podobny sposób, tworząc klasę serializatora rozszerzającą JsonSerializer i używając adnotacji @JsonSerialize.

Mam nadzieję, że to pomoże.

Powiązane problemy