2015-06-07 7 views
5

मेरे संस्था के साथ deserialize json:अशक्त आईडी संपत्ति जब जैक्सन और वसंत के Jackson2HalModule Hateoas

public class User { 

    private Integer id; 
    private String mail; 
    private boolean enabled; 

    // getters and setters 
} 

फ़ाइल test.json (बाकी वेब सेवा से प्रतिक्रिया):

{ 
"_embedded" : { 
    "users" : [ { 
    "id" : 1, 
    "mail" : "[email protected]", 
    "enabled" : true, 
    "_links" : { 
     "self" : { 
     "href" : "http://localhost:8080/api/users/1" 
     } 
    } 
    } ] 
} 
} 

और अपने परीक्षण वर्ग:

public class TestJson { 

    private InputStream is; 
    private ObjectMapper mapper; 

    @Before 
    public void before() { 
     mapper = new ObjectMapper(); 
     mapper.registerModule(new Jackson2HalModule()); 
     mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 

     is = TestJson.class.getResourceAsStream("/test.json"); 
    } 

    @After 
    public void after() throws IOException { 
     is.close(); 
    } 

    @Test 
    public void test() throws IOException { 
     PagedResources<Resource<User>> paged = mapper.readValue(is, new TypeReference<PagedResources<Resource<User>>>() {}); 
     Assert.assertNotNull(paged.getContent().iterator().next().getContent().getId()); 
    } 

    @Test 
    public void testResource() throws IOException { 
     PagedResources<User> paged = mapper.readValue(is, new TypeReference<PagedResources<User>>() {}); 
     Assert.assertNotNull(paged.getContent().iterator().next().getId()); 
    } 
} 

दूसरा परीक्षण गुजरता है लेकिन पहले नहीं। मुझे समझ में नहीं आ रहा है क्योंकि उपयोगकर्ता में आईडी संपत्ति केवल एक गायब है (मेल और सक्षम गुण खाली नहीं हैं) ...

इसे ठीक करने के लिए मुझे क्या करना है? क्या यह जैक्सन या स्प्रिंग जैक्सन 2 हैल मॉड्यूल में एक बग है?

आप मेरे वसंत-नफरत फोर्क repository क्लोनिंग और यूनिट परीक्षण लॉन्च करके पुन: पेश कर सकते हैं।

उत्तर

9

असल में, यह Resource वर्ग के कारण था जो आपके बीन की सामग्री को लपेटने के लिए बनाया गया है। सामग्री प्रॉपर्टी को @JsonUnwrapped द्वारा एनोटेट किया गया है ताकि Resource कक्षा इस संपत्ति में आपके बीन को मैप कर सकती है जबकि जेसन में, बीन गुण _links संपत्ति के समान स्तर पर हैं। इस एनोटेशन के साथ, रैपर और आंतरिक बीन के साथ संपत्ति का नाम संघर्ष करना संभव है। यह वास्तव में यहां मामला है क्योंकि Resource कक्षा में id संपत्ति ResourceSupport कक्षा से विरासत में मिली है, और इस संपत्ति को @JsonIgnore द्वारा दुखी किया गया है।

इस मुद्दे के लिए एक समाधान है। आप एक नया MixIn वर्ग ResourceSupportMixin वर्ग से विरासत में मिली बना सकते हैं और @JsonIgnore(false) टिप्पणी के साथ getId() विधि ओवरराइड कर सकते हैं:

public abstract class IdResourceSupportMixin extends ResourceSupportMixin { 

    @Override 
    @JsonIgnore(false) 
    public abstract Link getId(); 
} 

तो फिर तुम सिर्फ अपने ObjectMapper करने के लिए अपने IdResourceSupportMixin वर्ग को जोड़ने के लिए:

mapper.addMixInAnnotations(ResourceSupport.class, IdResourceSupportMixin.class); 

यह चाहिए समस्या का समाधान।

+1

'वसंत-hateoas' और' वसंत-boot' साथ एक ही समस्या है, इसलिए मैं किसी और – cahen

+0

हैं कुछ करने के लिए 'id' नाम बदलने के लिए किया था आपको यकीन है कि यह काम करता है? – Gazeciarz

+0

यह एक साल पहले था, लेकिन अगर मुझे सही याद है, तो यह वास्तव में एक संकलन त्रुटि के कारण काम नहीं करता है जो मुझे लगता है ... मुझे मिला एकमात्र समाधान कैहेन है। आपको अपनी आईडी संपत्ति का नाम किसी अन्य चीज़ में बदलना होगा। – mfalaize

0

यह मेरे लिए काम किया:

public class User extends ResourceSupport { 

    @JsonIgnore(false) 
    private Integer id; 
    private String mail; 
    private boolean enabled; 

    // getters and setters 
} 

इसके अलावा, PagedResources<Resource<User>>

0

के बजाय PagedResources <User> वापस जाने के लिए इस कोड को आप सभी @Entity सेम एक परिवर्तन config ईद मूल्य बेनकाब करने के लिए लगता है के साथ अपने http ग्राहक बदलने के लिए:

import java.util.LinkedList; 
import java.util.List; 

import javax.persistence.Entity; 

import org.springframework.beans.factory.config.BeanDefinition; 
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; 
import org.springframework.core.type.filter.AnnotationTypeFilter; 
import org.springframework.data.rest.core.config.RepositoryRestConfiguration; 
import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurerAdapter; 
import org.springframework.stereotype.Component; 

import com.rvillalba.exampleApiHateoas.entity.Example; 

import lombok.extern.slf4j.Slf4j; 

@Component 
@Slf4j 
public class SpringDataRestCustomization extends RepositoryRestConfigurerAdapter { 

    @Override 
    public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) { 
     listMatchingClasses(Entity.class).forEach(entity -> config.exposeIdsFor(entity)); 
    } 

    public List<Class> listMatchingClasses(Class annotationClass) { 
     List<Class> classes = new LinkedList<Class>(); 
     ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(true); 
     scanner.addIncludeFilter(new AnnotationTypeFilter(annotationClass)); 
     for (BeanDefinition bd : scanner.findCandidateComponents(Example.class.getPackage().getName())) { 
      try { 
       classes.add(Class.forName(bd.getBeanClassName())); 
      } catch (ClassNotFoundException e) { 
       log.error("listMatchingClasses problem", e); 
      } 
     } 
     return classes; 
    } 

} 
संबंधित मुद्दे