Java - 如何进行 JSON 日期验证?

Java - How to make JSON date validation?

我有这段代码:

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
    protected Date statusDate;

但不知何故它接受日期格式,如 -

"statusDate": "2017-13-27"

"statusDate": "201823-12-12"

是否可以在请求中验证格式(非手动)?

好吧,您需要编写一个自定义日期 serialisation/de-serialisation class,如果您在拦截数据时收到的日期格式不是您预期的格式,则抛出一个自定义异常。

This 答案将为您指明正确的操作方向。

您也可以在您的代码中使用验证器来验证有效负载并让 Jackson 保持简单状态。

是的,你可以。让我告诉你细节。

首先,请创建一个基本控制器来过滤所有请求,如下所示:

package com.letv.address.controller;

import com.letv.address.utils.ConstantCode;
import com.letv.address.utils.ResponseWrapper;
import com.letv.xice.core.controller.GlobalController;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by shichaoyang on 2017/1/10.
 */
public class BaseController extends GlobalController {

public ResponseWrapper requestCheckAndPost(BindingResult result) {

    if (result.hasErrors()) {

        List<Object> errorList = new ArrayList<>();

        StringBuilder sBuilder = new StringBuilder();

        for (ObjectError error : result.getAllErrors()) {

            String fieldName = ((FieldError) error).getField();
            String fieldMessage = error.getDefaultMessage();

            sBuilder.append(fieldName)
                    .append(" ")
                    .append(getMessage(fieldMessage))
                    .append(";");

            errorList.add(fieldName);
        }

        return new ResponseWrapper(
                  ConstantCode.FAILING_WITH_ERROR_PARAM_CODE
                , errorList.toArray()
                , ""
                , sBuilder.toString()
                );
    }
    return null;
  }
}

从上面的代码来看,BindingResult 将检查@JsonFormat 或其他组件header,如@NotBlank、@Pattern 等。如果他们符合规则,他们将被 BindingResult 捕获,我们可以得到错误。下面是我用过的DTO object,给你看看,这样你就可以得到更多的细节:

package com.letv.address.controller.dto;

import com.letv.address.utils.ConstantCode;
import org.hibernate.validator.constraints.NotBlank;

/**
 * Created by shichaoyang on 2016/12/23.
 */
public class ChildrenAreaSelectRequest{

@NotBlank(message = ConstantCode.REQUEST_VALIDATE_NOT_EMPTY)
private String areaIds;

public String getAreaIds() {
    return areaIds;
}

public void setAreaIds(String areaIds) {
    this.areaIds = areaIds;
  }
}

然后在我们的业务逻辑控制器中,我们需要扩展基础控制器并编写如下代码:

package com.letv.address.controller;

import com.letv.address.controller.dto.ChildrenAreaSelectRequest;
import com.letv.address.controller.dto.ParentAreaSelectReqeust;
import com.letv.address.domain.Area;
import com.letv.address.service.ChildAreaService;
import com.letv.address.utils.ConstantCode;
import com.letv.address.utils.ResponseWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by shichaoyang on 2016/12/12.
 */
@RestController("areaController")
public class AreaController extends BaseController {

@Autowired
protected ChildAreaService childAreaService;

/**
 * get area info by parent id
 *
 * @param areaReqeust
 * @param result
 */
@ResponseBody
@RequestMapping(value = ConstantCode.CHILD_AREA_PATH, method = {RequestMethod.POST})
public ResponseWrapper childArea(@RequestBody @Valid ParentAreaSelectReqeust areaReqeust, BindingResult result) {

    ResponseWrapper validationWrapper = requestCheckAndPost(result);
    if (validationWrapper != null) {
        return validationWrapper;
    }

    List<Area> areaList = childAreaService.selectByParentId(areaReqeust.getParentId());
    if (areaList == null || areaList.size() == 0) {
        return new ResponseWrapper(ConstantCode.SUCCESS_WITH_EMPTY_DATA_CODE, new ArrayList<>());
    } else {
        return new ResponseWrapper(ConstantCode.SUCCESS_WITH_FILL_DATA_CODE, areaList);
    }
  }
}

通过使用上述方法,您可以轻松验证请求中的字段。这是实现这一目标的绝妙方式。

希望对您有所帮助。

编辑:

图片替换为真实代码,方便大家测试。

@JsonFormat 用于设置返回 statusDate 作为响应时的输出格式。

最好创建一个接受字符串 statusDate 的 DTO 对象,然后在控制器中将其转换为日期格式。

要验证字符串格式的日期,您可以使用@Pattern

public class StatusDateDto {

    @NotNull(message="Status date is a required field")    
    @Pattern(regexp = "^\d{4}-\d{2}-\d{2}", message="Invalid status date")
    private String statusDate;

    //Getter and setter
}

public ResponseEntity<?> postStatusDate(@Valid @RequestBody StatusDateDto dateDto, BindingResult result) {

        if (result.hasFieldErrors()) {
            String errors = result.getFieldErrors().stream()
                .map(p -> p.getDefaultMessage()).collect(Collectors.joining("\n"));   

            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errors);
        }

        // Convert the String to Date after validation

        return ResponseEntity.ok().build();
    }