gpt4 book ai didi

java - 如何在java中使用jackson将缺失的属性反序列化为默认值

转载 作者:行者123 更新时间:2023-12-03 20:54:17 47 4
gpt4 key购买 nike

我试图让 jackson 将代表集合的缺失属性反序列化为空集合而不是 NULL。我尝试了一些不同的东西,这是最新的不起作用。

如果有一种方法可以为所有 POJO 反序列化全局配置任何潜在的解决方案,那就太好了。

鉴于以下 json,它缺少属性“ Assets ”:

{
"name":"my-layer",
"code": "ly1",
"types":["type1", "type2"],
"private": false
}

鉴于以下 POJO:
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSetter;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Builder.Default;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
public class CreateLayerRequest {

@NotBlank
@JsonProperty(required = true)
private String name;

@NotBlank
@JsonProperty(required = true)
private String code;

@Default
@NotNull
@JsonProperty(value = "private", required = true)
private Boolean privateLayer = Boolean.FALSE;

@Default
@JsonSetter(nulls = Nulls.AS_EMPTY)
@JsonProperty("types")
private Set<UUID> types = new HashSet<>();

@Default
@JsonSetter(nulls = Nulls.AS_EMPTY)
@JsonProperty("assets")
private Set<UUID> assets = new HashSet<>();
}

最佳答案

将我的修复配置为全局

@Configuration
public class MyAppConfiguration implements WebMvcConfigurer {

/**
* allows POJOs using json filtering to serialize all properties when not being filtered
*/
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
for (HttpMessageConverter<?> converter : converters) {
if (converter instanceof MappingJackson2HttpMessageConverter) {
((MappingJackson2HttpMessageConverter) converter)
.getObjectMapper()
// not related to this thread, this is for property filtering when serializing POJOs
.setFilterProvider(new SimpleFilterProvider().setFailOnUnknownId(false))
// these modules are related to to this thread
.registerModule(
new SimpleModule().addDeserializer(Set.class, new CollectionDeserializer())
)
.registerModule(
new SimpleModule().addDeserializer(List.class, new CollectionDeserializer())
)
.registerModule(
new SimpleModule().addDeserializer(Map.class, new CustomMapDeserializer())
);
}
}
}

@Slf4j
@NoArgsConstructor
@AllArgsConstructor
private static class CollectionDeserializer<T>
extends JsonDeserializer<Collection<T>>
implements ContextualDeserializer {

private JavaType type;
private final ObjectMapper mapper = new ObjectMapper();

@Override
public JsonDeserializer<?> createContextual(
DeserializationContext deserializationContext,
BeanProperty beanProperty) {

final JavaType javaType = deserializationContext.getContextualType() != null
? deserializationContext.getContextualType()
: beanProperty.getMember().getType();

return new CollectionDeserializer<>(javaType);
}

@Override
public Collection<T> deserialize(
JsonParser jsonParser,
DeserializationContext deserializationContext) throws IOException {

try {
if (Set.class.isAssignableFrom(type.getRawClass())) {
return deserializeJsonToCollection(jsonParser, new HashSet<>());
}

if (List.class.isAssignableFrom(type.getRawClass())) {
return deserializeJsonToCollection(jsonParser, new ArrayList<>());
}
} catch (IllegalArgumentException e) {
log.warn("unable to deserialize array property in request");
throw e;
}

final String message = "unable to deserialize collection";
log.warn(message);
throw new CollectionDeserializationException(message);
}

private Collection<T> deserializeJsonToCollection(
JsonParser jsonParser,
Collection<T> collection) throws IOException {

((ArrayNode) jsonParser
.getCodec()
.readTree(jsonParser))
.forEach(item -> {
try {
final T value = mapper.readValue(
String.format("\"%s\"", item.textValue()),
type.getContentType()
);
collection.add(value);
} catch (IOException e) {
final String message = String.format(
"unable to deserialize value [%s] to type [%]",
item.textValue(),
type.getContentType()
);
log.warn(message);
throw new CollectionDeserializationException(message);
}
});

return collection;
}

@Override
public Collection<T> getNullValue(DeserializationContext ctxt) {
if (Set.class.isAssignableFrom(type.getRawClass())) {
return new HashSet<>();
}

if (List.class.isAssignableFrom(type.getRawClass())) {
return new ArrayList<>();
}

return null;
}
}

@Slf4j
private static class CustomMapDeserializer<T, K> extends JsonDeserializer<Map<T, K>> {

private final ObjectMapper mapper = new ObjectMapper();
private final TypeReference<Map<T, K>> mapTypeReference = new TypeReference<>() {
};

@Override
public Map<T, K> deserialize(
JsonParser jsonParser,
DeserializationContext deserializationContext) {
try {
return mapper.readValue(jsonParser, mapTypeReference);
} catch (Exception e) {
final String message = "unable to deserialize map";
log.warn(message);
throw new MapDeserializationException(message, e);
}
}

@Override
public Map<T, K> getNullValue(DeserializationContext ctxt) {
return new HashMap<>();
}
}

关于java - 如何在java中使用jackson将缺失的属性反序列化为默认值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61396293/

47 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com