我有一个PATCH
RESTendpoint,公开了一个JSON接口,可用于根据主体中实际发送的属性部分更新实体。
让我们考虑一个表示实体的样本类:
class Account {
private UUID accountUuid;
private UUID ownerUuid;
private String number;
private String alias;
// constructor, getters and setters omitted
}
其中,帐户Uuid
、所有者Uuid
和数字
是必需的属性,别名
是可选的。此外,我有一个用于更新所述帐户的命令类:
class UpdateAccountCommand {
private UUID accountUuid;
private String number;
private String alias;
// constructor, getters and setters omitted
}
对于我的PATCH
endpoint,例如PATCH /accounts/{Account t-uuid}
,我想实现一个功能,仅更改请求中实际发送的属性:
// this should only update the account number
{"number": "123456"}
// this should only update the alias, by setting it to null
{"alias": null}
// this shouldn't update anything
{}
对于所需的属性,这相当容易做到。使用杰克逊从 JSON 字符串反序列化到更新帐户命令
实例后,我只需检查所需的属性是否为 null
,当它不为 null
时,我更新给定的属性。
但是,使用可选属性会使情况复杂化,因为在这两种情况下,alias
属性都为 null
:
别名
指定为null时,alias
属性根本没有在请求正文中指定时。如何对这些可选属性进行建模,以便指示此可移动机制?
您可以添加一个额外的布尔属性,该属性表示请求中是否存在可选属性
class UpdateAccountCommand {
//...
private String alias;
@JsonIgnore
private boolean isAliasSet;
@JsonProperty
public void setAlias(String value) {
this.alias = value;
this.isAliasSet = true;
}
}
只有当“alias”存在时,才会调用setter,不管它是空的还是有值的
一个朴素的解决方案是引入某种包装器,它不仅包含原始值(例如,对于别名:字符串
属性),还包含一个布尔值
,指示是否在正文中指定了属性。这将要求您编写自定义反序列化机制,这可能是一项繁琐的工作。
由于问题是关于 Java 8 的,对于 Java 8 及更新版本,我建议使用可为空的可选
,这与 Jackson 几乎开箱即用。
对于可选字段(可移除字段),您可以通过将原始值包装在optional:
class UpdateAccountCommand {
private UUID accountUuid;
private String number;
private Optional<String> alias;
// constructor, getters and setters omitted
}
为了让杰克逊与可选
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new Jdk8Module());
以下代码:
public static void main(String[] args) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new Jdk8Module());
String withNewAliasS = "{\"alias\":\"New Alias\"}";
String withNullAliasS = "{\"alias\":null}";
String withoutPropertyS = "{}";
UpdateAccountCommand withNewAlias = objectMapper.readValue(withNewAliasS, UpdateAccountCommand.class);
if (withNewAlias.getAlias() != null && withNewAlias.getAlias().isPresent()) {
System.out.println("withNewAlias specified new alias.");
}
UpdateAccountCommand withNullAlias = objectMapper.readValue(withNullAliasS, UpdateAccountCommand.class);
if (withNullAlias.getAlias() != null && !withNullAlias.getAlias().isPresent()) {
System.out.println("withNullAlias will remove an alias.");
}
UpdateAccountCommand withoutProperty = objectMapper.readValue(withoutPropertyS, UpdateAccountCommand.class);
if (withoutProperty.getAlias() == null) {
System.out.println("withoutProperty did not contain alias property on input at all.");
}
}
然后将其打印到控制台:
withNewAlias specified new alias.
withNullAlias will remove an alias.
withoutProperty did not contain alias property on input at all.
我尝试了拉雷维尔的入门指南。通用域名格式。 有一章创建了任务。回调和函数
我想知道,如何在Java8中使用流API迭代多级列表 根据Java8,我应该做如下的操作 我想要流利地做这件事(使用内部迭代)。任何解释都会很感激。
null 所以我想我有几个问题是基于我的发现。 如果不能重用流,那么何时返回流的实例以供以后使用? 是否可以克隆流,以便重用它们而不会导致?
我有课。我需要在超时内做一些http工作。我面临的问题是超时内的http变量一直说它是未定义的。
如果我更改了方法的名称,它会进行编译,但它不会重写toString,因此print方法不会打印预期的内容。 这是试图定义一个日志子系统,该子系统仅在需要时(当它真的要打印时)对lambda求值,但与非lambda参数兼容。我知道其他的方法来实现它,但我想知道为什么我不能这样做,如果有一个变通办法或我做错了什么,
这是我的路由器 这是终端错误 正在端口3090上侦听。。。。。(节点:7764)未经处理的PromisejectionWarning:TypeError:无法读取/Users/macbook/Desktop/node project/server/routes/api/posts上未定义的属性“text”。js:19:24在ProcessTicks和Rejections(internal/proc