在使用Spring睡觉控制器中的PUT请求方法部分更新实体时,我try 区分空值和未提供的值.

以以下实体为例:

@Entity
private class Person {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    /* let's assume the following attributes may be null */
    private String firstName;
    private String lastName;

    /* getters and setters ... */
}

My Person repository (Spring Data):

@Repository
public interface PersonRepository extends CrudRepository<Person, Long> {
}

The DTO I use:

private class PersonDTO {
    private String firstName;
    private String lastName;

    /* getters and setters ... */
}

My Spring RestController:

@RestController
@RequestMapping("/api/people")
public class PersonController {

    @Autowired
    private PersonRepository people;

    @Transactional
    @RequestMapping(path = "/{personId}", method = RequestMethod.PUT)
    public ResponseEntity<?> update(
            @PathVariable String personId,
            @RequestBody PersonDTO dto) {

        // get the entity by ID
        Person p = people.findOne(personId); // we assume it exists

        // update ONLY entity attributes that have been defined
        if(/* dto.getFirstName is defined */)
            p.setFirstName = dto.getFirstName;

        if(/* dto.getLastName is defined */)
            p.setLastName = dto.getLastName;

        return ResponseEntity.ok(p);
    }
}

Request with missing property

{"firstName": "John"}

Expected behaviour: update 100 (leave 101 unchanged).

Request with null property

{"firstName": "John", "lastName": null}

Expected behaviour: update firstName="John" and set lastName=null.

I cannot distinguish between these two cases, sincelastName in the DTO is always set to null by Jackson.

Note: I know that REST best practices (RFC 6902) recommend using PATCH instead of PUT for partial updates, but in my particular scenario I need to use PUT.

推荐答案

Actually,if ignore the validation,you can solve your problem like this.

   public class BusDto {
       private Map<String, Object> changedAttrs = new HashMap<>();

       /* getter and setter */
   }
  • First, write a super class for your dto,like BusDto.
  • 其次,更改dto以扩展超类,并更改 DTO的set方法,将属性名和值放入 changedAttrs(因为当 属性具有值,无论是否为空).
  • Third,traversal the map.

Json相关问答推荐

MariaDB杨森:在任何子属性中包含特定值

Jolt Change将对象添加到数组

JOLT拉平数组

kotlinx-serialization:如何将具有不同类型对象的JsonArray转换为同一个Class

如何在PowerShell中扩展JSON中的嵌套数组

如何在数组抖动中按值分组

如何在PowerShell中访问嵌套的JSON字段

将JSON数组组织到菜单中

使用 Powershell,如何将 Azure AD 组成员转换为 Json 对象(文件),然后可以更新?

jq - 仅在键值对存在的地方打印值

使用 Groovy 将 XML 转换为 JSON

是否可以在有条件的情况下将 json 对象转换为 JOLT 中的数组?

MarkLogic REST 资源 API - 仅使用一个 POST 请求修补多个文档

在 JavaScript 中从 Json 数据中删除反斜杠

IE8 原生 JSON.parse 错误导致堆栈溢出

Jsonpath 与 Jackson 或 Gson

在视图中将 .Net 对象转换为 JSON 对象

使用 Node.js 对 JSON 中的字符串大小有限制吗?

ASP.NET Core API 仅返回列表的第一个结果

如何使用 Gson 将 JSONArray 转换为 List?