2017-05-18 121 views
4

所以我必須包含這個方法這個控制器類:驗證JSON請求架構

@RequestMapping(value = "/x", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE) 
    public ResponseEntity<MyRepsonseClass> get(
     @ApiParam(value = "x", required = true) @Valid @RequestBody MyRequestClass request 
    ) throws IOException { 
     //yada yada my logic here 
     return something; 
    } 

JSON的請求被自動映射到MyRequestClass.java

這是什麼類的樣子:

@lombok.ToString 
@lombok.Getter 
@lombok.Setter 
@JsonInclude(JsonInclude.Include.NON_EMPTY) 
@ApiModel(description = "description") 
public class MyRequestClass { 
    private List<SomeClass> attribute1; 
    private SomeOtherClass attribute2; 
    private YetAnotherClass attribute3; 
} 

這是一個有效的JSON請求的例子:

{ 
    "attribute1": [ 
     { 
      "key":"value" 
     } 
    ], 
    "attribute3": { 
     "key":"value" 
    } 
} 

現在,我的要求是,當請求包含不在MyRequestClass.java存在的屬性返回一個錯誤信息。

這樣:

{ 
    "attribute1": [ 
     { 
      "key":"value" 
     } 
    ], 
    "attribute_that_doesnt_exist": { 
     "key":"value" 
    } 
} 

現在它不扔任何錯誤。相反,它根本不會將該屬性映射到任何東西。有沒有我可以利用的註釋可以使這種情況迅速發生?謝謝。

+0

假設你參考這個[示例](HTTP://計算器.com/questions/35080479/how-to-valid-incoming-json-and-check-for-missing-properties-jackson-jersey)並嘗試使用它建議的方法。 –

+0

你在使用@JsonIgnoreProperties註解嗎? –

+0

如果你正在'MyRequestClass'類中使用'@ JsonIgnoreProprties',那麼它不會拋出任何異常。如果你刪除它,它會拋出異常 – pvpkiran

回答

3

創建一個自定義解串器:

public class MyRequestClassDeserializer extends JsonDeserializer<MyRequestClass> { 
    @Override 
    public MyRequestClass deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException, JsonProcessingException { 
     MyRequestClass mrc = new MyRequestClass(); 
     ObjectMapper mapper = new ObjectMapper(); 
     JsonToken currentToken = null; 
     while((currentToken = jsonParser.nextValue()) != null) { 
      if(currentToken.equals(JsonToken.END_OBJECT) 
        || currentToken.equals(JsonToken.END_ARRAY)) 
       continue; 
      String currentName = jsonParser.getCurrentName(); 
      switch(currentName) { 
       case "attribute1": 
        List<SomeClass> attr1 = Arrays.asList(mapper.readValue(jsonParser, SomeClass[].class)); 
        mrc.setAttribute1(attr1); 
        break; 
       case "attribute2": 
        mrc.setAttribute2(mapper.readValue(jsonParser, SomeOtherClass.class)); 
        break; 
       case "attribute3": 
        mrc.setAttribute3(mapper.readValue(jsonParser, YetAnotherClass.class)); 
        break; 
       // <cases for all the other expected attributes> 
       default:// it's not an expected attribute 
        throw new JsonParseException(jsonParser, "bad request", jsonParser.getCurrentLocation()); 
      } 
     } 
     return mrc; 
    } 
} 

而這個註釋添加到您的MyRequestClass類:@JsonDeserialize(using=MyRequestClassDeserializer.class)

唯一的「問題」是手動反序列化jsons可以是一個麻煩。我會爲您的案例編寫完整的代碼,但我現在還不夠好。我可能會在未來更新答案。

編輯:完成,現在它的工作代碼。我認爲它更復雜。

+0

謝謝,我會在一段時間內嘗試這種方法,並讓你知道我的結果是什麼。 – adbar

+1

我編輯的代碼,以便它實際上與您的示例一起工作(順便說一句,在您的示例jsons中的錯誤,第二個屬性冒號是在屬性的名稱內)。 – nonzaprej

+0

這實際上比我預期的更好。它會以相似的方式自動驗證attribute1,attribute2和attribute3字段內的所有字段。 – adbar

1

你嘗試這個註釋@JsonIgnoreProperties(ignoreUnknown = false)

如果春天開機,甚至更好,使用application.properties這個屬性(YAML)

spring.jackson.deserialization.fail-on-unknown-properties=true 
+0

我只是嘗試了註釋,出於某種原因它不起作用。該屬性的確如此,但我想這對整個應用程序來說是全局的,也許他只需要在一個或多個端點上返回一個額外json屬性的錯誤,而不是全部。 – nonzaprej

+0

你是對的。它曾經工作,我不知道它是否是一個錯誤,現在它不再工作。 https://stackoverflow.com/questions/41128623/jsonignorepropertiesignoreunknown-false-is-not-working-in-spring-4-2-0-and-up –