【问题标题】:Merge json payload values to Object将 json 有效负载值合并到 Object
【发布时间】:2019-04-09 17:59:09
【问题描述】:

我想在从数据库中获取 REST PATH 有效负载后将其合并到“实体”对象,这样只有有效负载中提供的属性才会在实体中更新。因此,我想确保只有作为补丁有效负载一部分提供的属性才能安全更新。

我正在将 Spring Rest Controller 与 Hibernate 实体一起使用。

@PatchMapping(value = "/{id}")
public Resource<DepartmentPEO> update(@PathVariable Long id,
        @RequestBody JSONObject payload) throws Exception
{
    DepartmentPEO eo = departmentService.getRow(id);
    // Have to do something to update the eo object from jsonObject.
    // Some api to update eo
    eo = departmentService.update(id, eo);

    Resource<DepartmentPEO> resource = new Resource<>(eo);
    DepartmentPEO dept = resource.getContent();
    id = dept.getDeptSeq();
    resource.add(
            linkTo(methodOn(DepartmentsRestController.class).getRow(id))
                    .withSelfRel());
    return resource;
}

仅将修改后的属性作为有效负载的一部分发送到服务器,而不是发送所有属性。资源(实体)将具有嵌套的对象列表(一对多)。我正在为此用例寻找防池解决方案,并且相信这对于每个支持 REST api 的应用程序来说都是常见/基本的。

如果您指点任何 API 来解决这个问题,我们将不胜感激!

谢谢

【问题讨论】:

    标签: java json hibernate rest spring-rest


    【解决方案1】:

    这是一个使用来自 Spring 的 Jackson 的 ObjectMapper 和 BeanUtils 的工作示例(因为我假设您使用的是 Spring):

    import com.fasterxml.jackson.databind.ObjectMapper;
    import java.io.IOException;
    import org.json.JSONException;
    import org.json.JSONObject;
    import org.junit.Test;
    import org.springframework.beans.BeanUtils;
    
    public class StackOverflow {
    
     @Test
     public void mergeTest() throws IOException, JSONException {
        DepartmentPEO existingDepartement = existingDepartmentPEO();
    
        JSONObject payload = new JSONObject();
        payload.put("name", "newName");
        DepartmentPEO result = mergeToObject(payload, existingDepartement);
        assert result.getName().equals("newName");
        assert result.getId().equals("1");
     }
    
     private DepartmentPEO existingDepartmentPEO() {
        DepartmentPEO existingDepartement = new DepartmentPEO();
        existingDepartement.setId("1");
        existingDepartement.setName("oldName");
        return existingDepartement;
     }
    
     private DepartmentPEO mergeToObject(JSONObject payload, DepartmentPEO object) throws IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        DepartmentPEO updateRequest = objectMapper.readValue(payload.toString(), DepartmentPEO.class);
        BeanUtils.copyProperties(updateRequest, object, "id");
        return object;
     }
    }
    

    在这里,我将 JSONObject 转换为 DepartmentPEO 类,然后将此对象复制到现有对象中,忽略字段 ID。

    您可能希望有一个通用的方法来忽略 JSONObject 中的空字段,然后您可以参考这篇文章,例如 How to ignore null values using springframework BeanUtils copyProperties?

    我建议将 DepartmentPEO 对象直接发送到 REST 方法签名中,而不是使用 JSONObject。

    问候

    【讨论】:

    • 谢谢 user3793803,我发现这种方法存在一个问题,即如果用户试图通过有效负载使值无效会发生什么?属性不会因为我们忽略而无效,您有什么解决方案吗?
    • 然后您将不得不添加额外行为,例如从您收到的 JSON 中区分显式空值和无值。您可以在从 Json 创建对象之前检查显式空值。就像将它们放入数组中一样。然后从属性数组中提取它们。但是,如果您有嵌套对象,这可能会变得难以维护和乏味......如果您有复杂的更新策略,我建议您参考这篇文章以获得正确的 PATCH 请求:williamdurand.fr/2014/02/14/please-do-not-patch-like-an-idiot
    • 感谢 user3793803 指点文档,我的意图是只发送有效载荷中修改后的属性。使用 JSONObject 的原因是在更新到目标对象之前找出空值。是的,资源(实体)将具有嵌套的对象列表(一对多)。我正在为这个用例寻找防池解决方案,并且相信这对于每个支持 REST API 的应用程序来说都是常见的/基本的。感谢您花时间在这方面。感谢任何进一步的 api 指针来解决这个问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多