标签: jackson-databind

杰克逊无法用连字符反序列化字段

在下面的代码中,生成的 orderObj 没有合约 ID、订单号详细信息。它仅对带有连字符的字段进行反序列化。据我所知@jsonproperty应该映射。

请帮助获取我的结果 orderObj 中的所有字段。

import com.fasterxml.jackson.annotation.JsonProperty;

public class Order implements Serializable {

    private static final long serialVersionUID = 6791737023394030929L;

    @JsonProperty("id")
    private String id;

    @JsonProperty("contract-id")
    private String contractId;

    @JsonProperty("order-number")
    private String orderNumber;
}


final ObjectMapper mapper = new ObjectMapper();
mapper.setAnnotationIntrospector(new JaxbAnnotationIntrospector(mapper.getTypeFactory()));
mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, true);

Response response = orderServiceTarget.queryParam("contract-id",contractId).request().accept(MediaType.APPLICATION_JSON).headers(headersMap).get();
final String serverResponseStr = response.readEntity(String.class);
Order  orderObj = objectMapper.readValue(serverResponseStr, Order.class); 
Run Code Online (Sandbox Code Playgroud)

结果对象是:它缺少其他字段,

{
    "id": "7FABA1724B8F15306447852233",
}
Run Code Online (Sandbox Code Playgroud)

这是服务器响应:

{
    "id": "7FABA1724B8F15306447852233",
    "contract-id": "42BAD9AAA5231BD",
    "order-number": "ADD",
    "market-segment": "COM",
}
Run Code Online (Sandbox Code Playgroud)

java json jackson-databind

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

验证 Java LocalDate 是否与 yyyy-MM-dd 格式与可读消息匹配

我在 DoB 的 POJO 类中有以下属性。

@NotNull(message = "dateOfBirth is required")
@JsonDeserialize(using = LocalDateDeserializer.class)
LocalDate dateOfBirth;
Run Code Online (Sandbox Code Playgroud)

我怎样才能验证这一点

  1. 用户正在发送有效的日期格式(仅接受 YYYY-MM-DD)
  2. 如果用户输入不正确的日期,我想发送自定义消息或更易读的消息。目前,如果用户输入无效日期,则应用程序会发送以下长错误 -
JSON parse error: Cannot deserialize value of type `java.time.LocalDate` from String \"1984-33-12\": Failed to deserialize java.time.LocalDate:
(java.time.format.DateTimeParseException) Text '1984-33-12' could not be parsed: Invalid value for MonthOfYear (valid values 1 - 12): 33; 
...
Run Code Online (Sandbox Code Playgroud)

java jackson bean-validation jackson-databind

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

如何使用jpa在postgresql中将继承类列表保存为json?

为了在 postgresql 中保存 json 格式的列表,我com.vladmihalcea:hibernate-types-52在 Spring boot 2 中使用如下:

@Entity
@TypeDefs({
    @TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
})
public class Profile {
    ...
    @Type(type = "jsonb")
    @Column(columnDefinition = "jsonb")
    private List<String> locations;

    // getters & setters
}
Run Code Online (Sandbox Code Playgroud)

有了这个,一切都OK了,我可以将位置保存为postgresql中的json。但我想将位置保存为类继承结构。课程如下:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = As.PROPERTY, property = "type")
@JsonSubTypes({
    @JsonSubTypes.Type(value = SubClass1.class, name = "subClass1"),
    @JsonSubTypes.Type(value = SubClass2.class, name = "subClass2")
})
public abstract class MyClass {
    private String name;
    // getters & setters
}
public class SubClass1 extends …
Run Code Online (Sandbox Code Playgroud)

java jackson spring-boot postgresql-json jackson-databind

5
推荐指数
0
解决办法
1012
查看次数

升级 jackson-databind 版本后无法启动应用程序

我正在开发 Spring Boot 应用程序,我想 jackson-databind2.9.10.2升级到2.10.2。以下是我的 pom.xml 的片段以及升级依赖项后遇到的错误:
pom.xml:

         <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-xml</artifactId>
            <version>2.9.9</version>
            <exclusions>
                <exclusion>
                    <groupId>com.fasterxml.jackson.core</groupId>
                    <artifactId>jackson-databind</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.10.2</version>
        </dependency>
Run Code Online (Sandbox Code Playgroud)


依赖层次结构 错误:

启动 ApplicationContext 时出错。要显示条件报告,请在启用“调试”的情况下重新运行应用程序。13-03-2020 17:38:52.660 ||错误|osboot.SpringApplication:821 |应用程序运行失败org.springframework.beans.factory.BeanCreationException:创建类路径资源中定义的名为“requestMappingHandlerAdapter”的bean时出错[org/springframework /boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]:通过工厂方法实例化 Bean 失败;嵌套异常是 org.springframework.beans.BeanInstantiationException:无法实例化 [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter]:工厂方法“requestMappingHandlerAdapter”抛出异常;嵌套异常是org.springframework.beans.factory.BeanCreationException:创建名称为“org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration”的bean时出错:通过构造函数实例化Bean失败;嵌套异常是 org.springframework.beans.BeanInstantiationException:无法实例化 [org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration$$EnhancerBySpringCGLIB$$1f3fa4d]:构造函数抛出异常;嵌套异常是org.springframework.beans.factory.UnsatisfiedDependencyException:创建在类路径资源[org/springframework/boot/autoconfigure/http/JacksonHttpMessageConvertersConfiguration$MappingJackson2HttpMessageConverterConfiguration.class]中定义的名为“mappingJackson2HttpMessageConverter”的bean时出错:通过方法“表达的依赖关系不满足” mappingJackson2HttpMessageConverter'参数0;嵌套异常是org.springframework.beans.factory.BeanCreationException:创建类路径资源中定义的名为“jacksonObjectMapper”的bean时出错[org/springframework/boot/autoconfigure/jackson/JacksonAutoConfiguration$JacksonObjectMapperConfiguration.class]:合并bean的后处理定义失败;嵌套异常是 java.lang.IllegalStateException:无法从 org.springframework.beans.factory.support.ConstructorResolver 的 ClassLoader [sun.misc.Launcher$AppClassLoader@18b4aac2] 内省类 [com.fasterxml.jackson.databind.ObjectMapper]。实例化(ConstructorResolver.java:627)在org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:607)在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:132) 1)在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1160) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java: 555) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515) 在 org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) 在 org. springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)在org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)在org.springframework.beans.factory.support。 AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)在org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:845)在org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:877)在 org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549) 在 org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) 在 org.springframework.boot.SpringApplication .refresh(SpringApplication.java:742) 在 org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:389) 在 org.springframework.boot.SpringApplication.run(SpringApplication.java:311) 在 org.springframework.boot。 SpringApplication.run(SpringApplication.java:1213)在org.springframework.boot.SpringApplication.run(SpringApplication.java:1202)在com.finicity.accountowner.AccountOwnerApplication.main(AccountOwnerApplication.java:29)引起:org.springframework .beans.BeanInstantiationException:无法实例化[org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter]:工厂方法“requestMappingHandlerAdapter”抛出异常;嵌套异常是org.springframework.beans.factory.BeanCreationException:创建名称为“org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration”的bean时出错:通过构造函数实例化Bean失败;嵌套异常是 org.springframework.beans.BeanInstantiationException:无法实例化 [org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration$$EnhancerBySpringCGLIB$$1f3fa4d]:构造函数抛出异常;嵌套异常是org.springframework.beans.factory.UnsatisfiedDependencyException:创建在类路径资源[org/springframework/boot/autoconfigure/http/JacksonHttpMessageConvertersConfiguration$MappingJackson2HttpMessageConverterConfiguration.class]中定义的名为“mappingJackson2HttpMessageConverter”的bean时出错:通过方法“表达的依赖关系不满足” …

java maven spring-boot jackson-databind

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

Jackson将对象序列化为JSON到base64(没有无限循环)

有没有一种简单的方法可以使用 Jackson 将对象序列化为 base64 编码的 JSON?(对象 -> JSON -> base64)

我尝试使用自定义StdSerializer,但这(当然)会导致无限循环:

class MySerializer extends StdSerializer<Foo> {
  public void serialize(Foo value, JsonGenerator gen, SerializerProvider provider) {
    StringWriter stringWriter = new StringWriter();
    JsonGenerator newGen = gen.getCodec().getFactory().createGenerator(stringWriter);
    gen.getCodec().getFactory().getCodec().writeValue(newGen, value);
    String json = stringWriter.toString();
    String base64 = new String(Base64.getEncoder().encode(json.getBytes()));
    gen.writeString(base64);
  }
}
Run Code Online (Sandbox Code Playgroud)

解决方法是将所有字段复制到另一个类并使用该类作为中间表示:

class TmpFoo {
  public String field1;
  public int field2;
  // ...
}

class MySerializer extends StdSerializer<Foo> {
  public void serialize(Foo value, JsonGenerator gen, SerializerProvider provider) {
    TmpFoo tmp = …
Run Code Online (Sandbox Code Playgroud)

java base64 json jackson jackson-databind

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

RestAssured - 无法识别的字段,未标记为可忽略

(注:我已经看到关于“Jackson 抱怨无法识别的属性”主题的多个问题的回答,但我没有找到专门使用 RestAssured 的对象映射器的问题)

我有 RestAssured 测试,它有效

@Test
public void objectMappingRelyingOnClassAnnotation() {

    User user = RestAssured.get("https://api.github.com/users/andrejss88")
            .as(User.class); // must have 'jackson-databind' dependency

    Assert.assertEquals(user.login, "andrejss88");
}
Run Code Online (Sandbox Code Playgroud)

它之所以有效,是因为该类已注释,如下所示

@JsonIgnoreProperties(ignoreUnknown = true)
public class User {
    public String login;
    public int id;
}
Run Code Online (Sandbox Code Playgroud)

但是,我想使用使用重载方法的替代方法as(),并在不使用注释的情况下传入我自己的映射器:

<T> T as(Class<T> cls, ObjectMapper mapper);
Run Code Online (Sandbox Code Playgroud)

但杰克逊的映射器不起作用:

@Test
public void objectMappingUsingSpecifiedMapper() {

    //  Doesn't compile - Jackson's ObjectMapper != RestAssured's Mapper
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

    AnotherUser user = RestAssured.get("https://api.github.com/users/andrejss88")
            .as(AnotherUser.class, objectMapper); …
Run Code Online (Sandbox Code Playgroud)

jackson rest-assured jackson-databind

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

Jackson 使用 @JsonAnyGetter 序列化重复字段

我的 DTO 类具有预定义的字段和未映射的映射。当 otherFields 映射包含具有相同名称的字段(field1 键)时,jackson 序列化它们并且我有无效的 json,例如

{
"field1": "value",
"field1": "otherValue"
}
Run Code Online (Sandbox Code Playgroud)
public class DTO implements Serializable {

    private String field1;

    @JsonIgnore
    @JsonAnySetter
    private final Map<String, Object> otherFields = new LinkedHashMap<>();

    @JsonAnyGetter
    public Map<String, Object> getOtherFields() {
        return otherFields;
    }

    public String getField1() {
        return field1;
    }

    public void setField1(String field1) {
        this.field1 = field1;
    }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下有没有办法只选择一个值?对于我的情况,地图中的一个应该优先。

java spring jackson jackson-databind

5
推荐指数
0
解决办法
139
查看次数

如何编写 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
查看次数