2016-04-01 8 views
2

私はspringboot rest serviceを持っています。ユーザーはこのJava POJOにデシリアライズされますJSONオブジェクトを渡し:Java 8ジャクソンの妥当性確認

public final class Request { 
    private String id; 
    private double code; 
    private String name; 

    public String getId() { 
     return id; 
    } 

    public double getCode() { 
     return code; 
    } 

    public String getName() { 
     return name; 
    } 
} 

したがって、ユーザーは、次のJSONに合格する必要があります。

{ 
    "id": “123457896”, 
    "code": "Foo", 
    "name": "test" 
} 

は、私は必要なすべてのフィールドを作りたいです。多かれ少なかれ何かを提供することは例外をスローするでしょう。デシリアライズ時に入力を検証するようにjacksonに指示する方法はありますか?私は@JsonProperty(required=true)を試しましたが、これはうまくいきません。明らかにherehereからは、JsonProperty注釈は尊重されていないようです。

私は私のコントローラに呼び出し、このバリデータがあります。

@Component 
public class RequestValidator implements Validator { 
    @Override 
    public boolean supports(Class<?> clazz) { 
     return false; 
    } 

    @Override 
    public void validate(Object target, Errors errors) { 
     String id = ((Request) target).getId(); 
     if(id == null || id.isEmpty()) { 
      throw new InvalidRequestException("A valid id is missing. Please provide a non-empty or non-null id."); 
     } 
    } 
} 

しかし、単にすべてのフィールドをチェックするために退屈で醜いと思われることを。私はjava 8、spring boot、jacksonの最新バージョンを使用していますので、入ってくるjson入力を検証する上でベストプラクティスは何ですか?それとも、私はすでに最新の方法でそれをやっていますか?

答えて

3

Spring Validatorのアプローチを使用しました。 別のアプローチがあります。

J2EE JSR-303/JSR-349 Bean検証APIです。検証アノテーション(javax、ジャックソンではありません)を提供します。

は両方here

+0

この手法では、検証が失敗したときに上記のように自分のカスタム例外をスローするにはどうすればよいですか? – Richard

+1

スローされた例外に対して@ExceptionHandlerアノテーションを使用し、必要な応答を提供できます。そのような何か:@ResponseStatus(値= HttpStatus.BAD_REQUEST) @ExceptionHandler({HttpMessageNotReadableException.class、MethodArgumentNotValidException.class、 HttpRequestMethodNotSupportedException.class}) 公共ResponseEntity badRequest(HttpServletRequestの要求、例外例){ –

4

カスタムバリデータため必要はありませんが良い例を参照してください。あなたが余分なフィールドを(UnrecognizedPropertyExceptionJsonMappingExceptionを単に延長される)がある場合は、必要なフィールドに

  • UnrecognizedPropertyExceptionを持っていない場合

    • JsonMappingExceptionをスローするようにジャクソンを伝える方法があります。

    @JsonCreatorまたはカスタムコンストラクタを追加するだけで済みます。このような何か作業をする必要があります:

    public Request(@JsonProperty(value= "id", required = true)String id, 
           @JsonProperty(value= "code",required = true)double code, 
           @JsonProperty(value= "name",required = true)String name) { 
        this.id = id; 
        this.code = code; 
        this.name = name; 
    } 
    

    全デモ:

    import com.fasterxml.jackson.annotation.JsonCreator; 
    import com.fasterxml.jackson.annotation.JsonProperty; 
    import com.fasterxml.jackson.databind.JsonMappingException; 
    import com.fasterxml.jackson.databind.ObjectMapper; 
    import java.io.IOException; 
    
    public class Main { 
    
    public static void main(String[] args) throws IOException { 
        test("{\"id\": \"123457896\",\"code\": 1,\"name\": \"test\"}"); 
        test("{\"id\": \"123457896\",\"name\": \"test\"}"); 
        test("{\"id\": \"123457896\",\"code\": 1, \"c\": 1,\"name\": \"test\"}"); 
    } 
    
    public static void test(String json) throws IOException{ 
        ObjectMapper mapper = new ObjectMapper(); 
        try { 
         Request deserialized = mapper.readValue(json, Request.class); 
         System.out.println(deserialized); 
         String serialized = mapper.writeValueAsString(deserialized); 
         System.out.println(serialized); 
        } catch (JsonMappingException e) { 
         System.out.println(e.getMessage()); 
        } 
    } 
    
    public static class Request { 
        private String id; 
        private double code; 
        private String name; 
    
        public Request(@JsonProperty(value= "id", required = true)String id, 
            @JsonProperty(value= "code",required = true)double code, 
            @JsonProperty(value= "name",required = true)String name) { 
         this.id = id; 
         this.code = code; 
         this.name = name; 
        } 
    
        public String getId() { 
         return id; 
        } 
    
        public void setId(String id) { 
         this.id = id; 
        } 
    
        public double getCode() { 
         return code; 
        } 
    
        public void setCode(double code) { 
         this.code = code; 
        } 
    
        public String getName() { 
         return name; 
        } 
    
        public void setName(String name) { 
         this.name = name; 
        } 
    
        @Override 
        public String toString() { 
         return "Request{" + 
           "id='" + id + '\'' + 
           ", code=" + code + 
           ", name='" + name + '\'' + 
           '}'; 
        } 
    } 
    } 
    

    結果:

    Request{id='123457896', code=1.0, name='test'} 
    {"id":"123457896","code":1.0,"name":"test"} 
    Missing required creator property 'code' (index 1) 
    at [Source: {"id": "123457896","name": "test"}; line: 1, column: 34] 
    Unrecognized field "c" (class Main7$Request), not marked as ignorable (3 known properties: "id", "code", "name"]) 
    at [Source: {"id": "123457896","code": 1, "c": 1,"name": "test"}; line: 1, column: 53] (through reference chain: Request["c"]) 
    
  • +0

    どの場合についてコードが空でもヌルでもないことを確認したい –

    +0

    これは、名前が空であるためにテストが失敗するようにするためのテストです( "{\" id \ ":\" 123457896 \ "、\" code \ ":1、\" name \ ":\" "}")フィールドは存在する –

    0

    @JsonCreatorアノテーションをコンストラクタと共に使用すると、@JsonPropertyが動作します。これもanswerにチェックしてください。

    public final class Request { 
        private String id; 
        private double code; 
        private String name; 
    
        @JsonCreator 
        public Request(@JsonProperty(required = true) String id, 
            @JsonProperty(required = true) double code, 
            @JsonProperty(required = true) String name) { 
         this.id = id; 
         this.code = code; 
         this.name = name; 
        } 
    
        public String getId() { 
         return id; 
        } 
    
        public double getCode() { 
         return code; 
        } 
    
        public String getName() { 
         return name; 
        } 
    }