【问题标题】:Bind Form Data as JSON String/String Array to Request Params In String将表单数据绑定为 JSON 字符串/字符串数组以请求字符串中的参数
【发布时间】:2021-01-11 10:16:58
【问题描述】:

我有一个表格,我想通过 ajax 发送给我的控制器:

<div class="row">
            <label for="username" class="col-sm-2 col-form-label my-auto">Username:</label>
            <div class="col-sm-10 my-auto">
                <input type="text" class="form-control" id="username" name="username">
            </div>
        </div>
        <div class="row">
            <label for="password" class="col-sm-2 col-form-label my-auto">Password:</label>
            <div class="col-sm-10 my-auto">
                <input type="text" class="form-control" id="password" name="password">
            </div>
        </div>
        <div class="row" id="ratingRow">
            <label for="adminFoci" class="col-sm-2 col-form-label my-auto">User Rating:</label>
            <div class="col-sm-auto my-auto">
                <select class="selectpicker" multiple data-live-search="true" name="adminFoci" id="adminFoci" title="Choose Foci">
                    <c:forEach items="${foci}" var="focus">
                        <option name="${focus.focusName}" value="">${focus.focusName}</option>
                    </c:forEach>
                </select>
            </div>
            <div class="col-sm my-auto">
                <input type="text" class="form-control" id="rating" name="rating">
            </div>
            <div class="col-sm-auto my-auto" id="ratingButtonRow">
                <div class="btn btn-info btn-sm" id="adminAddGroup">Add Rating</div>
            </div>
        </div>
        <div class="row">
            <label for="adminUserGroups" class="col-sm-2 col-form-label my-auto">User's Groups:</label>
            <div class="col-sm-auto my-auto">
                <select class="selectpicker" multiple data-live-search="true" id="adminUserGroups" name="groups" title="Choose Groups">
                    <c:forEach items="${groups}" var="group">
                        <option name="${group.groupName}" value="${group.groupName}">${group.groupName}</option>
                    </c:forEach>
                </select>
            </div>
        </div>
        <div class="row">
            <label class="col-sm-2 col-form-label my-auto">User's Roles:</label>
            <div class="col-sm-10 my-auto">
                <select class="selectpicker" multiple data-live-search="true" id="adminUserRoles" name="roles" title="Choose Roles">
                    <c:forEach items="${user.roles}" var="role">
                        <option name="${role.name}" value="${role.name}">${role.name}</option>
                    </c:forEach>
                </select>
            </div>
        </div>

我捕获表单提交并序列化表单数据:

$("#modalForm").submit(function(e){
        e.preventDefault();
        var form = $(this);
        $.ajax({
            type: "POST",
            url: form.attr('action'),
            dataType: 'json',
            contentType: "application/json; charset=utf-8",
            data: JSON.stringify($(this).serializeArray()), 
            success: function(data)
            {
                table.row('.selected').ajax.reload();
            }
        });

    });

然后我尝试将 json 字符串数组的数据绑定到我的控制器中请求参数:

@PostMapping(value="/AdminCreateUser", consumes = MediaType.APPLICATION_JSON_VALUE)
    public void createUser(@RequestParam String username, @RequestParam String password, @RequestParam (required = false) String[] roles,
                           @RequestParam (required = false) String[] groups){
        User user = new User(username, password);
        if(roles != null){
            Set<Role> roleList = roleService.findRoles(roles);
            if(roleList.size() > 0){
                user.setRoles(roleList);
            }
        }
        if(groups != null){
            Set<Group> groupList = groupService.findGroups(groups);
            for(Group group: groupList){
                group.addMember(user);
                groupRepository.save(group);
            }
        }
        userRepository.save(user);
    }

但是我得到Resolved [org.springframework.web.bind.MissingServletRequestParameterException: Required String parameter 'username' is not present]。 Jackson 不将 json 字符串数组的匹配元素绑定到请求参数吗?如果没有,我该怎么做?我想省去将每个表单字段作为单独数据发送的工作

【问题讨论】:

    标签: java json ajax spring spring-boot


    【解决方案1】:

    序列化数组的输出将是,

    [
       {
         "name" : "username",
         "value" : "test"
       },...
    ]
    

    然后把java代码改成,

    public void createUser(@RequestBody String body){
    

    将字符串转换为 JSONObject 并将其作为 JSON 处理。然后这将起作用。 如果你想处理请求参数。 将 content-type 更改为 multipart/form-data 并直接发布到 API。

    【讨论】:

    • 如果我将其转换为字符串,我无法拆分每个值,因为某些字段可能存在也可能不存在(必需 = false)
    • 您可以使用名称字段验证服务器端的值吗?
    【解决方案2】:

    有两种方法。

    1. 通过使用 application/json

    像这样修改你的js代码。

    $("#modalForm").submit(function(e){
        e.preventDefault();
        var form = $(this);
        
        //convert form data to json array of Object(name value pair)
        data = []
        var x = $(this).serializeArray();
        $.each(x, function(i, field){
          var name = field.name; var value = field.value;
          data[i] = {name : value};
        });
        
        
        $.ajax({
            type: "POST",
            url: form.attr('action'),
            dataType: 'json',
            contentType: "application/json; charset=utf-8",
            data: JSON.stringify(data), 
            success: function(data)
            {
                table.row('.selected').ajax.reload();
            }
        });
    
    });
    

    修改你的控制器

    public void createUser(@RequestBody CreateUserDto createUserRequest){
    
    1. 如果您想使用请求参数,请将 content-type 更改为 multipart/form-data。

    【讨论】:

    • 我不认为使用 DTO 对我有用。该表单包含与用户实体不直接相关的值,因此无法映射请求正文
    • 要将 DTO 映射到实体,即使它具有不同的字段,您可以使用 MapStruct 或者您可以使用 getter 从 DTO 获取值,并根据您的要求进行处理。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多