标签: jackson-databind

如何编写 Jackson 转换器来处理通用集合类型?

我创建了一个按升序排序的元素,以便生成的 JSON 数组按排序顺序输出,而不是给定实现使用的任意迭代顺序。它按照文档的建议扩展了 Jackson 中的标准类。Jackson ConverterSetSetStdConverterConverter

注意:强烈鼓励实现者扩展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)

java generics jackson jackson-databind

5
推荐指数
1
解决办法
6595
查看次数

如何处理枚举上空值的 InvalidFormatException

如何处理枚举上空值的 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 enums jackson spring-boot jackson-databind

5
推荐指数
1
解决办法
1万
查看次数

Jackson 中的扁平 JSON,用于具有一个字段的类/记录/值对象

我有一条只有一个字段的 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)

java jackson deserialization jackson-databind

5
推荐指数
1
解决办法
2831
查看次数

让 Jackson 使用 GSON 注释

我有一个无法更改的数据模型。模型本身使用 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 注释,或者是否有其他解决方案不需要更改原始模型注释?

java jackson gson jackson-databind

5
推荐指数
1
解决办法
726
查看次数

在 Spring 环境中配置 Jackson 的 DeserializationProblemHandler

据我了解,Spring 已经为 Jackson 提供了一个 bean ObjectMapper。因此,我不是创建一个新的 bean,而是尝试自定义这个 bean。

从这篇博文,然后这个Github项目我使用Jackson2ObjectMapperBuilderbean来实现这个定制。

@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)

spring jackson spring-boot jackson2 jackson-databind

4
推荐指数
1
解决办法
5951
查看次数

字段在不实现 Serialized 接口的情况下被序列化

我有一个实现 Serialized 接口的 java 类。它具有 String、BigDecimal 和其他可序列化的 java 预定义类型。它还包括一个自定义定义的类,该类不实现可序列化。自定义类型也被序列化为 JSON。

\n\n

但有警告显示要么使其成为瞬态,要么使自定义类型实现可序列化。

\n\n

即使类型没有\xe2\x80\x99t 实现 Serialized ,它如何被序列化?我应该忽略警告(SonarLint 消息)吗?

\n

java serialization jackson-databind

4
推荐指数
1
解决办法
2034
查看次数

Java 8 Time API的ObjectMapper配置

我们正在从Joda迁移到Java Time.目前我们DateTime在我们的实体中使用Joda.AFAIK DateTime相当于Java中的两种类型:OffsetDateTimeZonedDateTime.既然我们要将它们保存在数据库中,我们将使用OffsetDateTime(对此有何评论?).

现在的问题是如何ObjectMapper正确配置杰克逊.我在网上找到的所有例子都是关于Jackson已经提供de/serializer实现的本地类型(例如LocalDateTime,LocalDateTimeSerializerLocalDateTimeDeserializer).

我终于设法做了这样的事情:

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)

java jackson jackson-modules java-time jackson-databind

4
推荐指数
2
解决办法
1560
查看次数

即使在添加 jackson-modules-java8 依赖项后也找不到 Jackson JavaTimeModule?

我正在尝试遵循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班是无处可寻。我究竟做错了什么?

java jackson jackson-modules jackson-databind

4
推荐指数
1
解决办法
4817
查看次数

如果枚举映射键为空或未知,则忽略 JSON 反序列化

我正在尝试使用 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)

java json jackson jackson-databind

4
推荐指数
1
解决办法
2968
查看次数

杰克逊遗产

似乎无法弄清楚这一点。我不断收到各种错误,所以我将用我从杰克逊收到的当前错误来写这个。

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)

jackson spring-boot jackson-databind

4
推荐指数
1
解决办法
7320
查看次数