验证Json请求架构

时间:2017-05-18 23:19:02

标签: java json spring spring-mvc jackson

所以我有这个包含这个方法的Controller类:

    @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"
    }
}

现在它没有抛出任何错误。相反,它根本不会将该属性映射到任何东西。我可以使用哪些注释可以使这种情况快速发生?谢谢。

2 个答案:

答案 0 :(得分: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)

唯一的问题&#34;是手动反序列化jsons可能是一个麻烦。我会为你的案子写完整的代码,但我现在还不够好。我可能会在将来更新答案。

编辑:完成,现在它正在运行代码。我觉得它更复杂。

答案 1 :(得分:1)

您是否尝试过此注释@JsonIgnoreProperties(ignoreUnknown = false)

如果Spring启动,甚至更好,请在application.properties(yaml)

中使用此属性
spring.jackson.deserialization.fail-on-unknown-properties=true