【问题标题】:Validate Json Request Schema验证 Json 请求架构
【发布时间】:2017-10-18 22:38:02
【问题描述】:

所以我有一个包含这个方法的 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"
    }
}

现在它没有抛出任何错误。相反,它根本没有将该属性映射到任何东西。有没有我可以利用的注释可以快速实现?谢谢。

【问题讨论】:

  • 假设您参考此example 并尝试使用它建议的方法。
  • 你在使用@JsonIgnoreProperties注解吗?
  • 如果你在MyRequestClass 类上使用@JsonIgnoreProprties,那么它不会抛出任何异常。如果你删除它,它会抛出一个异常
  • @JayanandRaghuwanshi 不,我不是
  • @pvpkiran 没有使用该注释。我编辑了我的帖子以包含我当前使用的注释。

标签: java json spring spring-mvc jackson


【解决方案1】:

创建自定义反序列化器:

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)

唯一的“问题”是手动反序列化 json 可能很麻烦。我会为您的案例编写完整的代码,但我现在还不够好。我以后可能会更新答案。

编辑:完成,现在它的工作代码。我认为它更复杂。

【讨论】:

  • 谢谢你,我会在一段时间内尝试这种方法,让你知道我的结果。
  • 我编辑了代码,使其真正适用于您的示例(顺便说一句,您的示例 jsons 中存在错误,在第二个属性中,冒号位于属性名称内)。
  • 这实际上比我预期的还要好。它以类似的方式自动验证attribute1、attribute2和attribute3字段中的所有字段。
【解决方案2】:

你试过这个注解@JsonIgnoreProperties(ignoreUnknown = false)

如果是Spring boot,那就更好了,在application.properties(yaml)中使用这个属性

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

【讨论】:

  • 我刚刚尝试了注释,但由于某种原因它不起作用。该属性确实如此,但我猜它对整个应用程序都是全局的,也许他只需要在一个或一些端点而不是所有端点上的额外 json 属性上返回一个错误。
  • 你是对的。以前可以用,不知道是不是bug,现在不行了。 stackoverflow.com/questions/41128623/…
猜你喜欢
  • 1970-01-01
  • 2015-10-23
  • 2015-10-24
  • 1970-01-01
  • 1970-01-01
  • 2023-01-21
  • 2021-08-03
  • 2022-07-05
  • 2019-06-09
相关资源
最近更新 更多