我创建了一个按升序排序的元素,以便生成的 JSON 数组按排序顺序输出,而不是给定实现使用的任意迭代顺序。它按照文档的建议扩展了 Jackson 中的标准类。Jackson
Converter
Set
Set
StdConverter
Converter
注意:强烈鼓励实现者扩展
StdConverter
而不是直接实现Converter
,因为这可以帮助典型样板代码的默认实现。
public class OrderedSetConverter
extends StdConverter<Set<DayOfWeek>, Set<DayOfWeek>> {
@Override
public Set<DayOfWeek> convert(Set<DayOfWeek> value) {
return value == null ? null : value.stream()
.sorted(Comparator.nullsLast(Comparator.naturalOrder()))
.collect(Collectors.toCollection(LinkedHashSet::new));
}
}
public class MyType {
@JsonSerialize(converter = OrderedSetConverter.class)
private Set<DayOfWeek> myValues;
}
Run Code Online (Sandbox Code Playgroud)
Converter
当要转换特定类型的元素时(在本例中) ,这很有效DayOfWeek
。但是,此实现中没有任何特定于特定类型的内容;它对于任何类型都同样有效Comparable
。因此,我更希望有一个可用于任何Set
可比较的转换器的通用实现。
我尝试通过使用泛型的简单用法来实现这一点:
public class OrderedSetConverter<E extends Comparable<? super E>>
extends StdConverter<Set<E>, Set<E>> {
@Override
public Set<E> convert(Set<E> value) …
Run Code Online (Sandbox Code Playgroud) 如何处理枚举上空值的 InvalidFormatException。当空值传递到底层 Jackson 解析器时,我们希望抛出验证错误,而不是低级错误。我们怎样才能避免这种情况呢?
Exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `com.company.model.Flower` from String "": not one of the values accepted for Enum class: [Lilly, Jasmine]
at [Source: (PushbackInputStream); line: 1, column: 64]
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:389)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:342)
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:186)
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.readWithMessageConverters(RequestResponseBodyMethodProcessor.java:158)
at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:131)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:170)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1060)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:962)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doPut(FrameworkServlet.java:920)
Run Code Online (Sandbox Code Playgroud) 我有一条只有一个字段的 Java 记录:
public record AggregateId(UUID id) {}
Run Code Online (Sandbox Code Playgroud)
以及一个带有该AggregateId
字段的类(为了可读性而删除了其他字段)
public class Aggregate {
public final AggregateId aggregateId;
@JsonCreator
public Aggregate(
@JsonProperty("aggregateId") AggregateId aggregateId
) {
this.aggregateId = aggregateId;
}
}
Run Code Online (Sandbox Code Playgroud)
上面的实现使用给定的示例序列化和反序列化 JSON:
ObjectMapper objectMapper = new ObjectMapper();
String content = """
{
"aggregateId": {
"id": "3f61aede-83dd-4049-a6ff-337887b6b807"
}
}
""";
Aggregate aggregate = objectMapper.readValue(content, Aggregate.class);
System.out.println(objectMapper.writeValueAsString(aggregate));
Run Code Online (Sandbox Code Playgroud)
我如何更改 Jackson 配置以替换 JSON:
{
"aggregateId": "3f61aede-83dd-4049-a6ff-337887b6b807"
}
Run Code Online (Sandbox Code Playgroud)
不放弃一个单独的类AggregateId
并通过字段进行访问,没有吸气剂?
我尝试了@JsonUnwrapper
注释,但这导致了抛出
Exception in thread "X" com.fasterxml.jackson.databind.exc.InvalidDefinitionException:
Invalid type definition for …
Run Code Online (Sandbox Code Playgroud) 我有一个无法更改的数据模型。模型本身使用 GSON 注释进行注释。
@SerializedName("first_value")
private String firstValue = null;
Run Code Online (Sandbox Code Playgroud)
Jackson 的反序列化无法按需要进行。Jackson 无法匹配该条目,因此该值为空。
它将与
@JsonProperty("first_value")
private String firstValue = null;
Run Code Online (Sandbox Code Playgroud)
有什么方法可以让 Jackson 使用 GSON 注释,或者是否有其他解决方案不需要更改原始模型注释?
据我了解,Spring 已经为 Jackson 提供了一个 bean ObjectMapper
。因此,我不是创建一个新的 bean,而是尝试自定义这个 bean。
从这篇博文,然后这个Github项目我使用Jackson2ObjectMapperBuilder
bean来实现这个定制。
@Bean
public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder(ApplicationContext context) {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.findModulesViaServiceLoader(true);
return builder;
}
Run Code Online (Sandbox Code Playgroud)
然后,我尝试自定义反序列化器以使其宽松:如果在反序列化属性时引发异常,我希望结果对象的属性为并null
让反序列化继续(默认值是在第一个不能被序列化的属性上失败)反序列化)。
我已经能够通过NullableFieldsDeserializationProblemHandler
扩展的类来实现这一点DeserializationProblemHandler
(我认为代码不相关,但如果需要,我可以共享它)。
注册此处理程序的最简单方法是使用.addHandler()
的方法ObjectMapper
。但当然,这样做,我需要在每次注入和使用ObjectMapper
. 我希望能够配置处理程序,以便每次ObjectMapper
自动连接时,处理程序都已经存在。
到目前为止,我想到的最佳解决方案是@PostConstruct
仅使用注释来注册问题处理程序。
@Configuration
public class JacksonConfiguration implements InitializingBean {
@Autowired private ObjectMapper objectMapper;
@Bean
public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder(ApplicationContext context) {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.findModulesViaServiceLoader(true);
return builder;
}
@Override
public …
Run Code Online (Sandbox Code Playgroud) 我有一个实现 Serialized 接口的 java 类。它具有 String、BigDecimal 和其他可序列化的 java 预定义类型。它还包括一个自定义定义的类,该类不实现可序列化。自定义类型也被序列化为 JSON。
\n\n但有警告显示要么使其成为瞬态,要么使自定义类型实现可序列化。
\n\n即使类型没有\xe2\x80\x99t 实现 Serialized ,它如何被序列化?我应该忽略警告(SonarLint 消息)吗?
\n我们正在从Joda迁移到Java Time.目前我们DateTime
在我们的实体中使用Joda.AFAIK DateTime
相当于Java中的两种类型:OffsetDateTime
和ZonedDateTime
.既然我们要将它们保存在数据库中,我们将使用OffsetDateTime
(对此有何评论?).
现在的问题是如何ObjectMapper
正确配置杰克逊.我在网上找到的所有例子都是关于Jackson已经提供de/serializer实现的本地类型(例如LocalDateTime
,LocalDateTimeSerializer
和LocalDateTimeDeserializer
).
我终于设法做了这样的事情:
public class OffsetDateTimeSerializer extends StdSerializer<OffsetDateTime> {
private final DateTimeFormatter formatter; // We need custom format!
public OffsetDateTimeSerializer(DateTimeFormatter formatter) {
super(OffsetDateTime.class);
this.formatter = formatter;
}
@Override
public void serialize(OffsetDateTime value, JsonGenerator generator, SerializerProvider provider) throws IOException {
generator.writeString(value.format(formatter));
}
}
Run Code Online (Sandbox Code Playgroud)
和
public class OffsetDateTimeDeserializer extends StdDeserializer<OffsetDateTime> {
private final DateTimeFormatter formatter; // We need custom format!
public OffsetDateTimeDeserializer(DateTimeFormatter formatter) …
Run Code Online (Sandbox Code Playgroud) 我正在尝试遵循JDK8 java.time 是否有 jackson 数据类型模块中给出的解决方案?(这是这个问题的原因,而不是重复)。
我加了
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-modules-java8</artifactId>
<version>2.9.5</version>
<type>pom</type>
</dependency>
Run Code Online (Sandbox Code Playgroud)
但我仍然无法做到这一点:
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
Run Code Online (Sandbox Code Playgroud)
该JavaTimeModule
班是无处可寻。我究竟做错了什么?
我正在尝试使用 Jackson 将 JSON 反序列化为 Java POJO。Json 看起来像
"foo": {
"one": {
"a":1,
"b":"string"
}
"three":{
"a":2
"b":"another"
}
...
}
Run Code Online (Sandbox Code Playgroud)
我想反序列化的类有这个字段:
public class Myclass {
private Map<MyEnum, MyPojo> foo;
//setter and getter
public static MyPojo {
private int a;
private String b;
}
}
Run Code Online (Sandbox Code Playgroud)
我的枚举类型如下所示:
public enum MyEnum {
one("data1"),two("data2")
@JsonValue
String data;
EnumAttrib(String data) {
this.data = data;
}
private static Map<String, MyEnum> ENUM_MAP = new HashMap();
static {
for (MyEnum a: MyEnum.values()) {
ENUM_MAP.put(a.data, a);
}
} …
Run Code Online (Sandbox Code Playgroud) 似乎无法弄清楚这一点。我不断收到各种错误,所以我将用我从杰克逊收到的当前错误来写这个。
public class ResponseDetail {
private Response response;
}
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME)
@JsonSubTypes({
@JsonSubTypes.Type(value = ResponseTypeOne.class, name = "ResponseTypeOne"),
@JsonSubTypes.Type(value = ResponseTypeTwo.class, name = "ResponseTypeTwo"),
@JsonSubTypes.Type(value = ResponseTypeThree.class, name = "ResponseTypeThree")
})
@JsonIgnoreProperties(ignoreUnknown = true)
public abstract class Response {
}
Run Code Online (Sandbox Code Playgroud)
在其他包中我有这三个:
public class ResponseTypeOne extends Response {
private Integer status;
}
public class ResponseTypeTwo extends Response {
private String message;
}
public class ResponseTypeThree extends Response {
private String value;
}
Run Code Online (Sandbox Code Playgroud)
错误:
Caused by: com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Missing type id when …
Run Code Online (Sandbox Code Playgroud)