2017-05-18 210 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 –