正在尝试通过 Jackson 库运行一些即将到来的工作。我有以下测试模型:
地址.java
package com.example.domain;
import java.time.LocalDate;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
public class Address {
private String addressKey;
private String postalCode;
private String country;
@JsonSerialize(using = DateSerializer.class, as = String.class)
@JsonDeserialize(using = DateDeserializer.class, as = LocalDate.class)
private LocalDate dateEntered;
public String getAddressKey() {
return addressKey;
}
public void setAddressKey(String addressKey) {
this.addressKey = addressKey;
}
public String getPostalCode() {
return postalCode;
}
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public LocalDate getDateEntered() {
return dateEntered;
}
public void setDateEntered(LocalDate dateEntered) {
this.dateEntered = dateEntered;
}
@Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this, false);
}
@Override
public boolean equals(Object obj) {
return EqualsBuilder.reflectionEquals(this, obj, false);
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE, false);
}
}
和 dateEntered 字段的自定义序列化器:
DateSerializer.java
package com.example.domain;
import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import org.springframework.boot.jackson.JsonComponent;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
@JsonComponent
public class DateSerializer extends JsonSerializer<LocalDate> {
@Override
public void serialize(LocalDate lc, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
throws IOException, JsonProcessingException {
String date = lc.format(DateTimeFormatter.ofPattern("dd MM yyyy"));
jsonGenerator.writeString(date);
}
}
我整理了以下测试,利用 @JsonTest 注释来检查序列化程序类是否正在执行我认为应该执行的操作:
地址测试.java
@JsonTest
@RunWith(SpringRunner.class)
public class AddressTest {
@Autowired
private JacksonTester<Address> json;
@Test
public void test_Address_serialisation_dateEnteredSerialised() throws Exception {
final Address address = getTestAddress();
assertThat(json.write(address))
.hasJsonPathStringValue("@.dateEntered")
.extractingJsonPathStringValue("@.dateEntered")
.isEqualTo("01 05 2018");
}
private Address getTestAddress() {
final Address testAddress = new Address();
testAddress.setAddressKey("testAddressKey");
testAddress.setCountry("testCountry");
testAddress.setPostalCode("testPostalCode");
testAddress.setDateEntered(LocalDate.of(2018, 5, 1));
return testAddress;
}
}
当我运行序列化测试时,我在控制台中得到了这个:
com.fasterxml.jackson.databind.JsonMappingException: Invalid definition for property dateEntered (of type 'Lcom/example/domain/Address;'): Can not refine serialization type [simple type, class java.time.LocalDate] into java.lang.String; types not related
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:284)
at com.fasterxml.jackson.databind.SerializerProvider.mappingException(SerializerProvider.java:1110)
at com.fasterxml.jackson.databind.SerializerProvider.reportBadPropertyDefinition(SerializerProvider.java:1180)
at com.fasterxml.jackson.databind.ser.PropertyBuilder.buildWriter(PropertyBuilder.java:101)
at com.fasterxml.jackson.databind.ser.BeanSerializerFactory._constructWriter(BeanSerializerFactory.java:816)
at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.findBeanProperties(BeanSerializerFactory.java:610)
at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.constructBeanSerializer(BeanSerializerFactory.java:399)
at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.findBeanSerializer(BeanSerializerFactory.java:282)
at com.fasterxml.jackson.databind.ser.BeanSerializerFactory._createSerializer2(BeanSerializerFactory.java:234)
at com.fasterxml.jackson.databind.ser.BeanSerializerFactory.createSerializer(BeanSerializerFactory.java:168)
at com.fasterxml.jackson.databind.SerializerProvider._createUntypedSerializer(SerializerProvider.java:1308)
at com.fasterxml.jackson.databind.SerializerProvider._createAndCacheUntypedSerializer(SerializerProvider.java:1279)
at com.fasterxml.jackson.databind.SerializerProvider.findValueSerializer(SerializerProvider.java:536)
at com.fasterxml.jackson.databind.SerializerProvider.findTypedValueSerializer(SerializerProvider.java:743)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:330)
at com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1427)
at com.fasterxml.jackson.databind.ObjectWriter._configAndWriteValue(ObjectWriter.java:1158)
at com.fasterxml.jackson.databind.ObjectWriter.writeValueAsString(ObjectWriter.java:1031)
at org.springframework.boot.test.json.JacksonTester.writeObject(JacksonTester.java:116)
at org.springframework.boot.test.json.AbstractJsonMarshalTester.write(AbstractJsonMarshalTester.java:133)
at com.example.domain.AddressTest.test_Address_serialisation_dateEnteredSerialised(AddressTest.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
据我所知,将 @JsonComponent 添加到类中将允许它在与 @JsonTest 结合使用时被拾取和注册,但基于此,它似乎没有被扫描和添加。我是否遗漏了测试或 src 代码中的一个步骤?值得注意的是,反序列化器的设置方式相同(它以特定格式字符串化日期)并且工作正常。
最佳答案
指定 as = ...
在 @JsonSerialize
内很少需要,特别是当您还指定 using = ...
时.
引自 @JsonSerialize.as
的 javadoc :
...
Note: ifusing
is also used it has precedence (since it directly specifies serializer, whereas this would only be used to locate the serializer) and value of this annotation property is ignored.
在您的情况下:指定 as = String.class
似乎是罪魁祸首
未找到的 JSON 序列化程序。
如果您省略它并且在您的 Address
中类就写
@JsonSerialize(using = DateSerializer.class)
@JsonDeserialize(using = DateDeserializer.class)
private LocalDate dateEntered;
然后是 DateSerializer
找到并且 AddressTest
无一异常(exception)地运行良好。
关于java - Spring Boot JacksonTester 自定义序列化程序未注册,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51210284/