我有一个包含很多字段的类,从 JSON 反序列化时所有这些字段都是可选的。
有没有办法将其转换为匹配所有非可选类型的类。
我的选修课
@JsonDeserialize
public class VeryOptionalClass
{
@Value.Parameter
@JsonProperty("fieldOne")
public Optional<String> fieldOne()
@Value.Parameter
@JsonProperty("fieldTwo")
public Optional<Double> fieldTwo()
@Value.Parameter
@JsonProperty("fieldOne")
public Optional<String> fieldThree()
@Value.Parameter
@JsonProperty("fieldThree")
public Optional<SomeObject> fieldFour()
---skip a few lines here---
@Value.Parameter
@JsonProperty("fieldTwentyfive")
public Optional<String> fieldHundredTwentyFive()
}
我想要的结果:
public class TotallyNonOptionalClass
{
public String fieldOne()
public Double fieldTwo()
public String fieldThree()
public SomeObject fieldFour()
---skip a few lines here---
public Integer fieldHundredTwentyFive()
}
如果填充了所有可选字段,这可以优雅地完成吗? 我知道我可以做一个像这样的构建器:
VeryOptionalClass myOptionalClass = someProvider(someInput)
TotallyNonOptionalClass.builder()
.fieldOne(myOptionalClass.fieldOne().get())
.fieldTwo(myOptionalClass.fieldTwo().get())
.fieldThree(myOptionalClass.fieldThree().get())
.fieldFour(myOptionalClass.fieldFour().get())
---skip a few lines here---
.fieldHundredTwentyFive(myOptionalClass.fieldHundredTwentyFive().get())
.build()
或者,如果我愿意,我可以使用Optional.orElse(someDefault)并列出构建器中的所有字段。但是假设我知道所有选项都是非空的,有没有办法在没有很长的构建器的情况下实现同样的事情?
PS。我的类实际上没有 125 个字段,但它很长,我不想每次添加字段/函数时都必须在 VeryOptionalClass 和 TotallyNonOptionalClass 中进行更改。
ModelMapper 是一个专门为将结构相似的异构对象相互映射而构建的库。换句话说,两种不同类型的对象具有相似的命名和类型字段。因此,它自然适合您的问题。
不幸的是,它不支持内置的 Java 8 可选包装器。
值得庆幸的是,ModelMapper 确实允许您指定自定义转换器。
请阅读有关 ModelMapper 的更多信息:https://modelmapper.org/
我下面的代码大致基于:https://stackoverflow.com/a/29060055/2045291
Optional<T> --> T
注意:您可能需要验证Optional内容的类型是否与目标类型匹配。
import org.modelmapper.spi.*;
import java.util.Optional;
public class OptionalExtractingConverter implements ConditionalConverter<Optional, Object> {
@Override
public MatchResult match(Class<?> aClass, Class<?> aClass1) {
if (Optional.class.isAssignableFrom(aClass) && !Optional.class.isAssignableFrom(aClass1)) {
return MatchResult.FULL;
}
return MatchResult.NONE;
}
@Override
public Object convert(MappingContext<Optional, Object> context) {
final Optional<?> source = context.getSource();
if (source != null && source.isPresent()) {
final MappingContext<?, ?> childContext = context.create(source.get(), context.getDestinationType());
return context.getMappingEngine().map(childContext);
}
return null;
}
}
import org.modelmapper.ModelMapper;
import java.util.Optional;
public class MappingService {
private static final ModelMapper modelMapper = new ModelMapper();
static {
modelMapper.typeMap(OptionalObject.class, NonOptionalObject.class)
.setPropertyConverter(new OptionalExtractingConverter());
}
public static void main(String[] args) {
OptionalObject optionalObject = new OptionalObject(Optional.of("test"));
NonOptionalObject nonOptionalObject = modelMapper.map(optionalObject, NonOptionalObject.class);
System.out.println("⭐️ RESULT: " + nonOptionalObject.getName());
}
}
Optional
字段)import java.util.Optional;
public class OptionalObject {
private Optional<String> name;
public OptionalObject() {
}
public OptionalObject(final Optional<String> name) {
this.name = name;
}
public Optional<String> getName() {
return name;
}
public void setName(Optional<String> name) {
this.name = name;
}
}
Optional
字段)public class NonOptionalObject {
private String name;
public NonOptionalObject() {
}
public NonOptionalObject(final String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}