在下面的代码中,生成的 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) 我在 DoB 的 POJO 类中有以下属性。
@NotNull(message = "dateOfBirth is required")
@JsonDeserialize(using = LocalDateDeserializer.class)
LocalDate dateOfBirth;
Run Code Online (Sandbox Code Playgroud)
我怎样才能验证这一点
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) 为了在 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) 我正在开发 Spring Boot 应用程序,我想 jackson-databind
从2.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时出错:通过方法“表达的依赖关系不满足” …
有没有一种简单的方法可以使用 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) (注:我已经看到关于“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) 我的 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)
在这种情况下有没有办法只选择一个值?对于我的情况,地图中的一个应该优先。
我创建了一个按升序排序的元素,以便生成的 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) jackson-databind ×10
java ×9
jackson ×8
spring-boot ×3
json ×2
base64 ×1
enums ×1
generics ×1
maven ×1
rest-assured ×1
spring ×1