代码之家  ›  专栏  ›  技术社区  ›  Simsons

jackosn JSON格式化程序正在反序列化,但没有进行适当的验证[重复]

  •  0
  • Simsons  · 技术社区  · 4 年前

    我有这段代码:

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

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

    "statusDate": "2017-13-27"
    

    "statusDate": "201823-12-12"
    

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

    0 回复  |  直到 7 年前
        1
  •  2
  •   Olantobi    7 年前

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

    最好创建一个接受StringstatusDate的DTO对象,然后在控制器中将其转换为Date格式。

    要验证字符串格式的日期,可以使用@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();
        }
    
        2
  •  1
  •   CharlieShi    7 年前

    是的,你可以。让我给你看看细节。

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

    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或其他组件头,如@NotBlank、@Pattern等。如果它们符合规则,它们将被BindingResult捕获,我们可以得到错误。下面是我使用的DTO对象,只需将其显示给您,您就可以获得更多详细信息:

    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);
        }
      }
    }
    

    通过使用上述方法,您可以在请求中轻松验证字段。这是一种很好的实现方式。

    希望这能有所帮助。

    编辑:

    用真实代码替换图像,以便任何人都需要对其进行测试。

        3
  •  0
  •   Abhijeet Ahuja    7 年前

    好吧,你需要编写一个自定义的日期序列化/去序列化类,如果在拦截数据时收到的日期格式不是你所期望的,则抛出一个自定义异常。

    This 这个答案将为你指明如何做到这一点的正确方向。

    此外,您还可以在代码中使用验证器来验证有效载荷,并让Jackson保持简单状态。