2012-07-07 20 views
36

İlkbaharda özel bir JSON serpantini yazmayı deniyorum. Alanların çoğu için varsayılan seri hale getirici kullanmak ve birkaç özellik için özel bir deserializer kullanmak istiyorum. Mümkün mü? Bu şekilde deniyorum çünkü özelliklerin çoğu birer değerdir, bu yüzden Jackson'ın varsayılan deserializer'ı kullanmasına izin verebilirim; ancak birkaç özellik referanstır, bu nedenle özel deserializer'da referans adı için bir veritabanı sorgulamalı ve veritabanından referans değeri almalıyım.Baharda JSON deserializer yazmanın ya da onu genişletmenin doğru yolu

Gerekirse bazı kodları göstereceğim.

+0

den com.fasterxml.jackson.databind.JsonDeserializer ve com.fasterxml.jackson.databind.annotation.JsonDeserialize seri kaldırma için olup sınıfları kullanarak, özel işlem kullanılacak olup olmadığının tespit edilmesi nasıl: bir alan adı (etkili) ya göre göre alan türü? –

+0

Üzgünüz, bu yorumu görmedim @ProgrammerBruce .. Alan türüne göre .. – gc5

cevap

65

Ben çok ve ben şimdiye kadar bulduğum en iyi yolu bu article üzerindedir arama yapmış:

package net.sghill.example; 

import net.sghill.example.UserDeserializer 
import net.sghill.example.UserSerializer 
import org.codehaus.jackson.map.annotate.JsonDeserialize; 
import org.codehaus.jackson.map.annotate.JsonSerialize; 

@JsonDeserialize(using = UserDeserializer.class) 
public class User { 
    private ObjectId id; 
    private String username; 
    private String password; 

    public User(ObjectId id, String username, String password) { 
     this.id = id; 
     this.username = username; 
     this.password = password; 
    } 

    public ObjectId getId()  { return id; } 
    public String getUsername() { return username; } 
    public String getPassword() { return password; } 
} 

Deserializer sınıfı seri hale getirmek

Sınıf

package net.sghill.example; 

import net.sghill.example.User; 
import org.codehaus.jackson.JsonNode; 
import org.codehaus.jackson.JsonParser; 
import org.codehaus.jackson.ObjectCodec; 
import org.codehaus.jackson.map.DeserializationContext; 
import org.codehaus.jackson.map.JsonDeserializer; 

import java.io.IOException; 

public class UserDeserializer extends JsonDeserializer<User> { 

    @Override 
    public User deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { 
     ObjectCodec oc = jsonParser.getCodec(); 
     JsonNode node = oc.readTree(jsonParser); 
     return new User(null, node.get("username").getTextValue(), node.get("password").getTextValue()); 
    } 
} 

Düzeltme: Alternatif olarak 01 Com.fasterxml.jackson.databind.JsonDeserializer'ın yeni sürümlerini kullanan.

+43

Hey, bu benim makalem! Onu bulduğuna sevindim :) – sghill

+0

Günümü kurtardım! Teşekkürler. –

+0

'com.fasterxml.jackson.databind.JsonDeserializer' sınıfındaki jackson'un yeni sürümlerinde, metni almak için 'getTextValue()' yerine 'asText()' kullanın. Teşekkürler!! +1 ':)' – albciff

8

Deserializer numaralı telefonuma Spring tarafından yönetilen bir hizmet için @Autowire çalışıyordum. Birisi, serileştiriciler/serpantilizatörleri çağırırken beni new operatörünü kullanarak Jackson'a yolladı. Bu, Jackson'un Deserializer benim örneğimin otomatik kablolaması anlamına gelmiyordu. İşte benim Deserializer içine benim hizmet sınıfı @Autowire başardı açıklanmıştır:

context.xml

<mvc:annotation-driven> <mvc:message-converters> <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <property name="objectMapper" ref="objectMapper" /> </bean> </mvc:message-converters> </mvc> <bean id="objectMapper" class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean"> <!-- Add deserializers that require autowiring --> <property name="deserializersByType"> <map key-type="java.lang.Class"> <entry key="com.acme.Anchor"> <bean class="com.acme.AnchorDeserializer" /> </entry> </map> </property> </bean> 

Şimdi benim Deserializer bir bahar tarafından yönetilen fasulye, otomatik kablolama işleri olduğunu!

AnchorDeserializer.java

public class AnchorDeserializer extends JsonDeserializer<Anchor> { 
    @Autowired 
    private AnchorService anchorService; 
    public Anchor deserialize(JsonParser parser, DeserializationContext context) 
      throws IOException, JsonProcessingException { 
     // Do stuff 
    } 
} 

AnchorService.java

@Service 
public class AnchorService {} 

Güncelleme: Bunu yazdığımda benim orijinal cevap benim için geri çalışırken, @xi .lin'in cevabı tam olarak ihtiyaç duyulan şeydir. Güzel bul!

+1

Çözümünüz bana yardımcı olmadı. Bu sorunu ** [SpringBeanAutowiringSupport] (http://docs.spring.io/spring/docs/2.5.6/api/org/springframework/web/context/support/SpringBeanAutowiringSupport.html) ** kullanarak çözdüm. –

+4

Ayrıca bunu yapmak için "HandlerInstantiator" kullanan [bakın] (http://www.runningasroot.com/blog/2012/05/02/autowiring-jackson-deserializers-in-spring/) bence de görebilirsiniz. –

+0

Bu yaklaşımın, bazıları için değil, bazıları için işe yaraması ilginç. PeterJurkovič tarafından kullanılan yaklaşım benim için işe yaramadı, ama bu bir tane var. –

1

Spring MVC 4.2.1.RELEASE ile, Deserializer'ın çalışması için yeni Jackson2 bağımlılıklarını kullanmanız gerekir.

Dont yerine bu

<dependency> 
      <groupId>org.codehaus.jackson</groupId> 
      <artifactId>jackson-mapper-asl</artifactId> 
      <version>1.9.12</version> 
     </dependency> 

kullanın kullanın.

<dependency> 
      <groupId>com.fasterxml.jackson.core</groupId> 
      <artifactId>jackson-annotations</artifactId> 
      <version>2.2.2</version> 
     </dependency> 
     <dependency> 
      <groupId>com.fasterxml.jackson.core</groupId> 
      <artifactId>jackson-core</artifactId> 
      <version>2.2.2</version> 
     </dependency> 
     <dependency> 
      <groupId>com.fasterxml.jackson.core</groupId> 
      <artifactId>jackson-databind</artifactId> 
      <version>2.2.2</version> 
     </dependency> 

da açıklamak için org.codehaus.jackson