2014-12-08 23 views
5

Mam RESTFul API spożywający/zwracający JSON w treści żądania/odpowiedzi. Kiedy klient wysyła nieprawidłowe dane (poprawny JSON, ale nieprawidłowe wartości dla pól), chcę mieć możliwość zwrócenia struktury JSON (a także odpowiedniego kodu 400+).W języku Java, w jaki sposób zwracać znaczące, sformatowane błędy JSON z walidacji Resteasy?

Ta struktura umożliwiłaby następnie frontendowi analizę błędów w poszczególnych polach i renderowanie błędów obok pól wejściowych.

E.g. idealne wyjście:

{ 
    "errors":{ 
    "name":["invalid chars","too long","etc"] 
    "otherfield":["etc"] 
    } 
} 

Używam Resteasy dla API i używając wyjątki naruszeń to dość łatwo dostać się to uczynić błędy JSON:

@Provider 
@Component 
public class ValidationExceptionHandler implements ExceptionMapper<ResteasyViolationException> { 
    public Response toResponse(ResteasyViolationException exception) { 
     Multimap<String,String> errors = ArrayListMultimap.create(); 

     Consumer<ResteasyConstraintViolation> consumer = (violation) -> { 
      errors.put(violation.getPath(), violation.getMessage()); 
     }; 

     exception.getParameterViolations().forEach(consumer); 

     Map<String, Map<String, Collection<String>>> top = new HashMap<>(); 

     top.put("errors", errors.asMap()); 

     return Response.status(Status.BAD_REQUEST).entity(top) 
       .build(); 
    } 
} 

Jednak ścieżki błędach (violation.getPath()) stanowią własność -centryczne zamiast XmlElement-name-centric.

E.g. Powyższe wyjścia:

{ 
    "errors":{"createCampaign.arg1.name":["invalid chars","etc"]} 
} 

próbowałem stripping indeks wstecz od ostatniego punktu, aby uzyskać „nazwa”, ale są też inne problemy z tym hack.

E.g. jeśli moja „nazwa” nieruchomość nie jest „nazwa” to nie działa:

@XmlElement(name="name") 
@NotNull 
private String somethingelse; 

„somethingelse” zostaną zwrócone klientowi, ale klient nie ma pojęcia, co to jest:

{ 
    "errors":{"somethingelse":["cannot be null"]} 
} 

Klient chce "nazwa", ponieważ to pole zostało wywołane podczas wysyłania.

Mój zasób:

package com.foo.api; 

import org.springframework.stereotype.Service; 
import javax.validation.Valid; 
import javax.ws.rs.Consumes; 
import javax.ws.rs.POST; 
import javax.ws.rs.Path; 
import javax.ws.rs.Produces; 
import javax.ws.rs.core.MediaType; 
import com.foo.dto.CarDTO; 

@Service 
@Path("/car") 
public class CarResource { 

    @POST 
    @Produces({MediaType.APPLICATION_JSON}) 
    @Consumes(MediaType.APPLICATION_JSON) 
    public CarDTO create(
      @Valid CarDTO car 
    ) { 
     //do some persistence 
     return car; 
    } 
} 

przykład dto:

package com.foo.dto; 

import javax.validation.constraints.NotNull; 
import javax.validation.constraints.Min; 
import javax.validation.constraints.Max; 
import javax.xml.bind.annotation.XmlElement; 

public class CarDTO { 
    @Min(1) 
    @Max(10) 
    @NotNull 
    @XmlElement(name="gears") 
    private int cogs; 
} 

Odpowiedz

1

This article opisuje dość dobrze, co trzeba zrobić.

Zasadniczo należy wdrożyć ExceptionMapper.

@Provider 
public class ValidationExceptionMapper implements ExceptionMapper<ValidationException> { 

    @Override 
    public Response toResponse(ValidationException exception) { 
     Response myResponse; 
     // build your Response based on the data provided by the exception 
     return myResponse; 
    } 

} 
0

niestandardowy komunikat o błędzie może być stosowany tak byłby trzeba spojrzeć na ścieżkę

@NotNull(message="name cannot be null")