2015-07-20 22 views
1

我有一個相當奇怪的行爲,在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,那麼它的工作原理。但它不是解決方案,因爲我需要遞歸結構的這些信息。

回答

1

我仍然不知道爲什麼會發生這種異常,但我使用StdTypeResolverBuilder爲每個dto,我序列化,然後它的工作。

可能會幫助有同樣問題的人...