java 检查是否有字段为空

niwlg2el  于 2022-12-21  发布在  Java
关注(0)|答案(5)|浏览(154)

我想知道是否有一个更短的版本来检查我的ProfileDto是否有任何字段为空。
在互联网上搜索时,我只发现了关于如何检查一个字段是否为空或所有字段是否为空的问题,这是完全不同的。
对于context,如果为空,则应采用用户对象(只是对数据库的调用)的相应字段。如果不为空,则应采用ProfileDto字段

private void setEmptyFieldsForUpdatedUser(User user, ProfileDto profileDto) {
    String newFirstName = profileDto.getFirstName();
    String newLastName = profileDto.getLastName();
    String newEmailAdres = profileDto.getEmail();
    String oldPassword = profileDto.getPassword();
    String newPassword = profileDto.getNewPassword();

    if (newFirstName == null) {
        profileDto.setFirstName(user.getFirstName());
    }
    if (newLastName == null) {
        profileDto.setLastName(user.getLastName());
    }
    if (newEmailAdres == null) {
        profileDto.setEmail(user.getEmail());
    }
}

这个ProfileDto提供了一个JSON对象,它可以有空值。如果它是空的,我想用我数据库中的前一个用户字段来设置值。
我的数据库用户具有以下属性:

firstname: dj
lastname : test
email : dj@mail.com
password : qwerty

输入示例:

{
    "firstName": "freeman",
    "lastName": null,
    "email": null
    "password": null,
    "newPassword" : null
}

我的输出应变为:

{
    "firstName": "freeman",
    "lastName": "test",
    "email": "dj@mail.com",
    "password": "qwerty"
}

显然,我们可以看到,如果我有20多个变量,我需要很多的如果,所以我想知道是否有一个更好的方法。

zsohkypk

zsohkypk1#

使用JSON的解决方案

由于OP不想使用反射,另一个解决方案使用jackson-databind依赖来实现JSON:
首先,我们将类示例转换为JsonTree。然后,我们迭代ProfileDto JSON的字段,其中也包括空值,并将空值替换为我们在User的JSON中可以找到的值。我们检查用户JSON是否具有不会导致异常的字段。最后,我们将JsonTree转换回ProfileDto的示例:

ObjectMapper mapper = new ObjectMapper();
JsonNode userTree = mapper.valueToTree(user);
JsonNode dtoTree = mapper.valueToTree(dto);

Iterator<Entry<String, JsonNode>> fields = dtoTree.fields();
while (fields.hasNext()) {
    Entry<String, JsonNode> e = fields.next();
    if (e.getValue().isNull() && userTree.has(e.getKey())) {
        ((ObjectNode) dtoTree).put(e.getKey(), userTree.get(e.getKey()).asText());
    }
}
dto = mapper.treeToValue(dtoTree, ProfileDto.class);

我使用了以下maven依赖项:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.3</version>
</dependency>

使用Java反射的解决方案

一种可能的解决方案包括反射。这样,只需迭代字段就可以检查所有字段。但是,此解决方案要求两个类具有相同的字段名,或者至少DTO中的字段名存在于用户类中

User user = new User();
user.setFirstName("dj");
user.setLastName("test");
user.setEmail("dj@mail.com");
user.setPassword("qwerty");
ProfileDto dto = new ProfileDto();
dto.setFirstName("test");

System.out.println(user);
System.out.println(dto);
System.out.println();

for (Field f : dto.getClass().getDeclaredFields()) {
    if (f.get(dto) == null) {
        try {
            f.set(dto, user.getClass().getDeclaredField(f.getName()).get(user));
        } catch (NoSuchFieldException e) {
            System.out.println("Field missing: " + f.getName());
        }
    }
}

System.out.println(user);
System.out.println(dto);
8fsztsew

8fsztsew2#

可以使用StringUtils类中的isBlank()方法检查字符串是空的还是只包含空格。

private void setEmptyFieldsForUpdatedUser(User user, ProfileDto profileDto) {
    String newFirstName = profileDto.getFirstName();
    String newLastName = profileDto.getLastName();
    String newEmailAdres = profileDto.getEmail();

    if (StringUtils.isBlank(newFirstName)) {
        profileDto.setFirstName(user.getFirstName());
    }
    if (StringUtils.isBlank(newLastName)) {
        profileDto.setLastName(user.getLastName());
    }
    if (StringUtils.isBlank(newEmailAdres)) {
        profileDto.setEmail(user.getEmail());
    }
}

这将检查是否有任何字符串为空或只包含空格,如果是,它将把ProfileDto对象中相应字段的值设置为User对象中的值。
如果变量的数量增加了,那么为了避免显式地检查每个变量,可以使用Map类来存储ProfileDto对象的字段以及每个字段对应的setter方法。()方法检查字段是否为空,如果为空,可以使用setter方法设置用户对象的相应字段。

private void setEmptyFieldsForUpdatedUser(User user, ProfileDto profileDto) {
    Map<String, BiConsumer<ProfileDto, String>> setters = new HashMap<>();
    setters.put("firstName", ProfileDto::setFirstName);
    setters.put("lastName", ProfileDto::setLastName);
    setters.put("email", ProfileDto::setEmail);

    for (Map.Entry<String, BiConsumer<ProfileDto, String>> entry : setters.entrySet()) {
        String fieldName = entry.getKey();
        BiConsumer<ProfileDto, String> setter = entry.getValue();

        try {
            Method getter = ProfileDto.class.getMethod("get" + StringUtils.capitalize(fieldName));
            String fieldValue = (String) getter.invoke(profileDto);

            if (StringUtils.isBlank(fieldValue)) {
                Method userGetter = User.class.getMethod("get" + StringUtils.capitalize(fieldName));
                String userValue = (String) userGetter.invoke(user);
                setter.accept(profileDto, userValue);
            }
        } catch (Exception e) {
            
        }
    }
}
vc9ivgsu

vc9ivgsu3#

我想不使用反射(不是很优雅)是不可能检查any字段是否为空的。
为了让你的代码更短更易读,我建议你使用Objects.requireNonNullElse()

profileDto.setFirstName(Objects.requireNonNullElse(profileDto.getFirstName(), user.getFirstName()));
dluptydi

dluptydi4#

如果你有java9或更高版本,你可以用下面的代码来减少代码

Optional.ofNullable(profileDto.getFirstName()).or(() -> Optional.ofNullable(user.getFirstName())).ifPresent(profileDto::setFirstName);
 //...same for each field

这边

  • 如果Dto字段和Entity字段都为空,则不会进行赋值。
  • 如果Dto字段具有非空值,它将始终保持其当前值,因为第一个运算符将为真并重新分配给DTO。
  • 如果Dto字段为空值,实体字段不为空,则实体字段将被分配给Dto。
1aaf6o9v

1aaf6o9v5#

您可以使用三元表达式,并且只需在一行中完成所有操作。(StringUtils类来自apache commons)

String newFirstName = StringUtils.isBlank(profileDto.getFirstName()) ? user.getFirstName() : profileDto.getFirstName();
String newLastName = StringUtils.isBlank(profileDto.getLastName()) ? user.getLastName() : profileDto.getLastName();
String newEmailAdres = StringUtils.isBlank(profileDto.getEmail()) ? user.getEmail() : profileDto.getEmail();

相关问题