我有一個相當奇怪的行爲,在serialize /反序列化java對象結構通過使用jackson ...錯誤發生在e2e測試,但我只能夠提取它,直到以下帶有這個特定巨大對象的測試用例。JSON與傑克遜 - 每個對象serializeable,在一起異常
二手傑克遜版本:傑克遜 - 數據綁定2.4.4
下面是測試:
@Test
public void testMapper3() throws JsonParseException, JsonMappingException, IOException{
ProductComponentDTO myComponent = new ProductComponentDTO("Value1", "Value2", null, null, false);
ProductOfferDTO offer = new ProductOfferDTO();
ChosenComponentDTO myChoice = new ChosenComponentDTO();
// Testvariant 3, remove the next line, so serialize and deserialize without the substructure, works!
myChoice.setProductComponentDTO(myComponent);
offer.addChosenComponentDTO(myChoice);
LaraObjectMapper om = new LaraObjectMapper();
// Testvariant 1, serialize and deserialize the hole object => doesn't work
String result = om.writeValueAsString(offer);
System.out.println("Result: " + result);
offer = om.readValue(result, ProductOfferDTO.class);
// Testvariant 2: serialize only a substructure of the object => works!
// String result = om.writeValueAsString(myChoice);
// System.out.println("Result: " + result);
// myChoice = om.readValue(result, ChosenComponentDTO.class);
}
的System.out變種1:
Result: {"@id":1,"numberOfPeople":null,"dateTime":null,"note":null,"state":null,"pk":null,"version":null,"componentNetSum":null,"componentDiscountSum":null,"offerNetSum":null,"offerDiscount":null,"taxSum":null,"grossSum":null,"afterAllDiscountsSum":null,"faultCause":null,"chosenComponentDTO":[{"@id":1,"pk":null,"version":null,"netSum":null,"afterDiscountSum":null,"tax":null,"discount":null,"grossSum":null,"chosenVariantDTO":null,"productComponentDTO":{"@id":1,"name":"Value1","description":"Value2","time":null,"pk":null,"version":null,"price":null,"mustComponent":false,"productDTO":null,"productVariantDTO":null,"chosenComponentDTO":null,"imagesDTO":null,"mainPicture":null,"changeManager":null},"productOfferDTO":null,"changeManager":null}],"productDTO":null,"productOfferCustomerDTO":null,"productBonusMalusDTO":null,"changeManager":null}
FAILED: testMapper3
com.fasterxml.jackson.databind.JsonMappingException: No _valueDeserializer assigned
at [Source: {"@id":1,"numberOfPeople":null,"dateTime":null,"note":null,"state":null,"pk":null,"version":null,"componentNetSum":null,"componentDiscountSum":null,"offerNetSum":null,"offerDiscount":null,"taxSum":null,"grossSum":null,"afterAllDiscountsSum":null,"faultCause":null,"chosenComponentDTO":[{"@id":1,"pk":null,"version":null,"netSum":null,"afterDiscountSum":null,"tax":null,"discount":null,"grossSum":null,"chosenVariantDTO":null,"productComponentDTO":{"@id":1,"name":"Value1","description":"Value2","time":null,"pk":null,"version":null,"price":null,"mustComponent":false,"productDTO":null,"productVariantDTO":null,"chosenComponentDTO":null,"imagesDTO":null,"mainPicture":null,"changeManager":null},"productOfferDTO":null,"changeManager":null}],"productDTO":null,"productOfferCustomerDTO":null,"productBonusMalusDTO":null,"changeManager":null}; line: 1, column: 456] (through reference chain: com.mleitner.product.service_contract.ProductOfferDTO["chosenComponentDTO"]->com.mleitner.product.service_contract.ChosenComponentDTOList[0]->com.mleitner.product.service_contract.ChosenComponentDTO["productComponentDTO"]->com.mleitner.product.service_contract.ProductComponentDTO["name"])
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148)
at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:770)
at com.fasterxml.jackson.databind.deser.impl.FailingDeserializer.deserialize(FailingDeserializer.java:27)
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:538)
at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:106)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:306)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeWithObjectId(BeanDeserializerBase.java:1036)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:122)
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:538)
at com.fasterxml.jackson.databind.deser.impl.ObjectIdReferenceProperty.deserializeSetAndReturn(ObjectIdReferenceProperty.java:76)
at com.fasterxml.jackson.databind.deser.impl.ObjectIdReferenceProperty.deserializeAndSet(ObjectIdReferenceProperty.java:67)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:306)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeWithObjectId(BeanDeserializerBase.java:1036)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:122)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:232)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:206)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:25)
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:538)
at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:106)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:306)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeWithObjectId(BeanDeserializerBase.java:1036)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:122)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3066)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2161)
at com.mleitner.businessmaximizer.webservice.ExceptionsHaveDefaultConstructorTest.testMapper3(ExceptionsHaveDefaultConstructorTest.java:67)
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:483)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:714)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
at org.testng.TestRunner.privateRun(TestRunner.java:767)
at org.testng.TestRunner.run(TestRunner.java:617)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
at org.testng.SuiteRunner.run(SuiteRunner.java:240)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1224)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1149)
at org.testng.TestNG.run(TestNG.java:1057)
at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:111)
at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:204)
at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:175)
的System.out變體2的:
Result: {"@id":1,"pk":null,"version":null,"netSum":null,"afterDiscountSum":null,"tax":null,"discount":null,"grossSum":null,"chosenVariantDTO":null,"productComponentDTO":{"@id":1,"name":"Value1","description":"Value2","time":null,"pk":null,"version":null,"price":null,"mustComponent":false,"productDTO":null,"productVariantDTO":null,"chosenComponentDTO":null,"imagesDTO":null,"mainPicture":null,"changeManager":null},"productOfferDTO":null,"changeManager":null}
PASSED: testMapper3
變體3的的System.out:
Result: {"@id":1,"numberOfPeople":null,"dateTime":null,"note":null,"state":null,"pk":null,"version":null,"componentNetSum":null,"componentDiscountSum":null,"offerNetSum":null,"offerDiscount":null,"taxSum":null,"grossSum":null,"afterAllDiscountsSum":null,"faultCause":null,"chosenComponentDTO":[{"@id":1,"pk":null,"version":null,"netSum":null,"afterDiscountSum":null,"tax":null,"discount":null,"grossSum":null,"chosenVariantDTO":null,"productComponentDTO":null,"productOfferDTO":null,"changeManager":null}],"productDTO":null,"productOfferCustomerDTO":null,"productBonusMalusDTO":null,"changeManager":null}
PASSED: testMapper3
所以變體2和3的工作=>因此每個的對象結構可以被序列化,但是它們不能被序列化在一起。爲什麼? 我也嘗試提取問題,複製所有使用的對象,以減少對象的屬性,直到我找到了錯誤,但在文件的副本之後,錯誤不再發生。然後我刪除了所有maven回購條目並做了一個新的構建(儘管可能是我正在使用一些舊文件),但也沒有幫助。然後我調試測試,錯誤發生在元素名稱(但這是一個通常的字符串,所以爲什麼不起作用?!)。
我序列化的對象包含列表。這個名單看起來像這樣:
public class ChosenComponentDTOList
extends ArrayList <ChosenComponentDTO>{
public ChosenComponentDTOList(){
}
public ChosenComponentDTOList(List<ChosenComponentDTO> values){
super();
if (values != null)
this.addAll(values);
}
}
下面是使用ObjectMapper:
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
public class LaraObjectMapper extends ObjectMapper{
/**
*
*/
private static final long serialVersionUID = -4831947927759735004L;
public LaraObjectMapper() {
this.setVisibilityChecker(
getSerializationConfig().
getDefaultVisibilityChecker().
withFieldVisibility(JsonAutoDetect.Visibility.ANY).
withGetterVisibility(JsonAutoDetect.Visibility.NONE).
withSetterVisibility(JsonAutoDetect.Visibility.NONE).
withCreatorVisibility(JsonAutoDetect.Visibility.NONE).
withIsGetterVisibility(JsonAutoDetect.Visibility.NONE));
this.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
this.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
this.setAnnotationIntrospector(new LaraJacksonAnnotationIntrospector());
}
}
而且使用annotationintrospector:
public class LaraJacksonAnnotationIntrospector extends
JacksonAnnotationIntrospector {
/**
*
*/
private static final long serialVersionUID = 1250247138609942147L;
@Override
public ObjectIdInfo findObjectIdInfo(final Annotated ann) {
if (BaseDTO.class.isAssignableFrom(ann.getRawType())) {
// this is needed for recursive structures
return new ObjectIdInfo(PropertyName.construct("@id", null),
ann.getRawType(),
ObjectIdGenerators.IntSequenceGenerator.class, null);
}
return super.findObjectIdInfo(ann);
}
@Override
public TypeResolverBuilder<?> findTypeResolver(MapperConfig<?> config,
AnnotatedClass ac, JavaType baseType) {
//every abstract class must serialize the concrete class => otherwise deserialize of the abstract class is not possible
if (__isAbstract(baseType.getRawClass()) && __handledClass(baseType.getRawClass())){
StdTypeResolverBuilder typeResolverBuilder = new StdTypeResolverBuilder();
typeResolverBuilder.typeProperty("@class");
typeResolverBuilder.inclusion(As.PROPERTY);
typeResolverBuilder.init(Id.CLASS, null);
return typeResolverBuilder;
}
return super.findTypeResolver(config, ac, baseType);
}
private boolean __handledClass(Class<?> clazz) {
return BaseDTO.class.isAssignableFrom(clazz) ||
FinderAttribute.class.isAssignableFrom(clazz) ||
ValidationError.class.isAssignableFrom(clazz) ||
AbstractChangeManager.class.isAssignableFrom(clazz);
}
private boolean __isAbstract(Class<?> clazz) {
return Modifier.isAbstract(clazz.getModifiers());
}
}
因此,任何人的想法有什麼不對?感謝您的時間和支持。
KR
更新 如果我刪除ObjectIdInfo,那麼它的工作原理。但它不是解決方案,因爲我需要遞歸結構的這些信息。