2014-12-08 4 views
5

Ich habe eine RESTFul-API, die JSON im Request/Response-Body verbraucht/zurückgibt. Wenn der Client ungültige Daten (gültiger JSON, aber ungültige Werte für die Felder) sendet, möchte ich eine JSON-Struktur (sowie den relevanten Code 400+) zurückgeben können.Wie gebe ich in Java sinnvolle JSON-formatierte Fehler aus der Reseasy-Validierung zurück?

Diese Struktur würde es dann dem Frontend ermöglichen, die Fehler pro Feld zu analysieren und die Fehler neben den Eingabefeldern darzustellen.

z. ideal Ausgang:

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

Ich bin mit Resteasy für die API und die Verletzung Ausnahmen verwendet es ist ziemlich einfach, um es JSON Fehler zu machen:

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

jedoch die Fehlerpfade (violation.getPath()) sind geistiges Eigentum -centric statt XmlElement-Name-centric.

z. die oben genannten Ausgänge:

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

habe ich versucht, den Index zurück aus dem letzten Punkt Strippen „namen“ zu bekommen, aber es gibt auch andere Probleme mit diesem Hack.

z. wenn meine Eigenschaft „Name“ ist nicht „name“ es funktioniert nicht:

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

„somethingelse“ wird an den Client zurückgegeben werden, aber sie Kunde hat keine Ahnung, was das ist:

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

Der Client möchte "name", da das Feld beim Senden aufgerufen wurde.

Meine Ressource:

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

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

Antwort

1

This article beschreibt ganz gut, was Sie tun müssen.

Grundsätzlich sollten Sie eine ExceptionMapper implementieren.

@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

Eine benutzerdefinierte Fehlermeldung kann verwendet werden, so dass Sie

@NotNull(message="name cannot be null") 
auf dem Weg aussehen würde nicht müssen
Verwandte Themen