Java 8将从每个字段中删除“字符串"的字符串值.值来自自定义对象 [英] Java 8 to remove string value from each field where "string" value comes of the Custom Object

查看:462
本文介绍了Java 8将从每个字段中删除“字符串"的字符串值.值来自自定义对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我通过链接:

I went through link: Is it possible in Java to check if objects fields are null and then add default value to all those attributes? and implemented the same solution as below -

注意:我正在使用 Swagger/Open API规范(使用springdoc-openapi-ui),并在使 POST 请求所有字符串字段时具有默认值"string",我真的想将其设置为null或空格.

Note: I am using Swagger/Open API Specs (using springdoc-openapi-ui) and while making POST request all string fields are having default value as "string" which I really wanted to set it to null or space.

任何快速指针吗?

public static Object getObject(Object obj) {
        for (Field f : obj.getClass().getFields()) {
            f.setAccessible(true);
            try {
                if (f.get(obj) == "string") {
                    f.set(obj, null);
                }
            } catch (IllegalArgumentException | IllegalAccessException e) {
                log.error("Error While Setting default values for String");
            }
        }
   return obj;
}

REST端点

@GetMapping(value = "/employees")
public ResponseEntity<PagedModel<EmployeeModel>> findEmployees(
        EmployeeDto geoDto,
        @Parameter(hidden=true) String sort,
        @Parameter(hidden=true) String order,
        @Parameter(hidden=true) Pageable pageRequest) {

    EmployeeDto dto = (EmployeeDto) CommonsUtil.getObject(geoDto);

    Page<CountryOut> response = countryService..............;
    PagedModel<EmployeeModel> model = employeePagedAssembler.toModel(response, countryOutAssembler);

    return new ResponseEntity<>(model, HttpStatus.OK);
}

推荐答案

我想您可以做些简单一些.如果您控制EmployeeDto,例如:

You could do it a bit simpler, I guess. If you control EmployeeDto, for example:

@Accessors(chain = true)
@Getter
@Setter
@ToString
static class EmployeeDto {

    private String firstname;
    private String lastname;
    private int age;

}

您可以遍历类的字段,并使用MethodHandles调用所需的setter,当某些getter返回您感兴趣的string时(并且使用equals而不是==比较字符串).这甚至可以做成一个很小的库.这是一个开始:

You could iterate over fields of the class and using MethodHandles invoke the needed setters, when some getters return the string you are interested in (and Strings are compared using equals, not ==). This can even be made into a tiny library. Here is a start:

private static final Lookup LOOKUP = MethodHandles.lookup();

/**
 * this computes all the know fields of some class (EmployeeDTO in your case) and their getter/setter
 */
private static final Map<Class<?>, Map<Entry<String, ? extends Class<?>>, Entry<MethodHandle, MethodHandle>>> ALL_KNOWN =
    Map.of(
        EmployeeDto.class, metadata(EmployeeDto.class)
    );
private Map<String, Entry<MethodHandle, MethodHandle>> MAP;

/**
 * For example this will hold : {"firstname", String.class} -> getter/setter to "firstname"
 */
private static Map<Entry<String, ? extends Class<?>>, Entry<MethodHandle, MethodHandle>> metadata(Class<?> cls) {
    return Arrays.stream(cls.getDeclaredFields())
                 .map(x -> new SimpleEntry<>(x.getName(), x.getType()))
                 .collect(Collectors.toMap(
                     Function.identity(),
                     entry -> {
                         try {
                             return new SimpleEntry<>(
                                 LOOKUP.findGetter(cls, entry.getKey(), entry.getValue()),
                                 LOOKUP.findSetter(cls, entry.getKey(), entry.getValue()));
                         } catch (Throwable t) {
                             throw new RuntimeException(t);
                         }
                     }
                 ));
}

有了这些信息,您可以提供一个供用户调用的公共方法,因此您需要提供DTO的实际实例,DTO类,要默认为"的字段的类,要检查的相等性反对和实际的defaultValue.

With that information you can provide a public method for users to call, So you need to provide the actual instance of your DTO, the DTO class, the Class of the fields you want to "default to", the equality to check against and the actual defaultValue.

    public static <T, R> T defaulter(T initial,
                                  Class<T> dtoClass,
                                  Class<R> fieldType,
                                  R equality,
                                  R defaultValue) throws Throwable {

    Set<Entry<MethodHandle, MethodHandle>> all =
        ALL_KNOWN.get(dtoClass)
                 .entrySet()
                 .stream()
                 .filter(x -> x.getKey().getValue() == fieldType)
                 .map(Entry::getValue)
                 .collect(Collectors.toSet());

    for (Entry<MethodHandle, MethodHandle> getterAndSetter : all) {
        R whatWeGot = (R) getterAndSetter.getKey().invoke(initial);
        if (Objects.equals(whatWeGot, equality)) {
            getterAndSetter.getValue().invoke(initial, defaultValue);
        }
    }

    return initial;

}

这是您的呼叫者可以调用的方式:

And this is how your callers can call it:

public static void main(String[] args) throws Throwable {
    EmployeeDto employeeDto = new EmployeeDto()
        .setFirstname("string")
        .setLastname("string");

    EmployeeDto withDefaults = defaulter(employeeDto, EmployeeDto.class, String.class, "string", "defaultValue");

    System.out.println(withDefaults);
}

这篇关于Java 8将从每个字段中删除“字符串"的字符串值.值来自自定义对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆