2012-07-07 5 views
36

Ich versuche, einen benutzerdefinierten JSON Deserializer im Frühjahr zu schreiben. Ich möchte Standard-Serializer für den größten Teil der Felder verwenden und einen benutzerdefinierten Deserializer für einige Eigenschaften verwenden. Ist es möglich? Ich versuche diesen Weg, weil der größte Teil der Eigenschaften Werte sind, also kann ich Jackson den Standard-Deserializer verwenden lassen; Aber einige Eigenschaften sind Verweise, daher muss ich im benutzerdefinierten Deserializer eine Datenbank nach dem Referenznamen abfragen und den Referenzwert aus der Datenbank abrufen.Richtiger Weg JSON Deserializer im Frühling zu schreiben oder zu erweitern

Ich werde bei Bedarf Code anzeigen.

+0

Um zu klären, wie wird es bestimmt, ob eine benutzerdefinierte Verarbeitung verwendet werden soll: durch Feldnamen (effektiv) oder durch Feldtyp? –

+0

Sorry, ich habe diesen Kommentar nicht gesehen @ProgrammerBruce .. Ich denke, nach Feldtyp .. – gc5

Antwort

65

habe ich gesucht viel und der beste Weg, die ich bisher gefunden habe, ist auf dieser article:

Klasse

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 Klasse zu serialisiert

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()); 
    } 
} 

Edit: Alternativ können Sie 01 betrachten, die neue Versionen von com.fasterxml.jackson.databind.JsonDeserializer verwendet.

+43

Hey, das ist mein Artikel! Froh, dass Sie es hilfreich fanden :) – sghill

+0

Mein Tag gerettet! Vielen Dank. –

+0

In neuen Versionen von jackson in der 'com.fasterxml.jackson.databind.JsonDeserializer' Klasse verwenden Sie' asText() 'anstelle von' getTextValue() ', um den Text zu erhalten. Vielen Dank!! +1 ':)' – albciff

8

Ich habe versucht, @Autowire ein Spring-Managed Service in meine Deserializer. Jemand hat mich an Jackson mit dem Operator new gekippt, als er die Serializer/Deserializer aufgerufen hat. Dies bedeutete keine Auto-Verdrahtung von Jackson's Instanz meiner Deserializer. Hier ist, wie ich konnte meine Dienstklasse in meine Deserializer@Autowire:

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> 

Jetzt, wo mein Deserializer ist eine Feder-Managed Bean, Auto-Verkabelung funktioniert!

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 {} 

aktualisieren: Während meine ursprüngliche Antwort für mich wieder gearbeitet, als ich dies schrieb, @xi Die Antwort von .lin ist genau das, was benötigt wird. Schöner Fund!

+1

Ihre Lösung hat mir nicht geholfen. Ich löste dieses Problem mit ** [SpringBeanAutowiringSupport] (http://docs.spring.io/spring/docs/2.5.6/api/org/springframework/web/context/support/SpringBeanAutowiringSupport.html) **. –

+4

Ich denke, dass Sie auch dies sehen können (http://www.runningasroot.com/blog/2012/05/02/autowiring-jackson-deserializers-in-spring/), die 'HandlerInstantiator' verwenden, um dies zu tun. –

+0

Es ist interessant, dass dieser Ansatz für einige und nicht für andere funktioniert. Der von @ PeterJurkovič verwendete Ansatz funktionierte für mich nicht, aber dieser tut es. –

1

Mit Spring MVC 4.2.1.RELEASE müssen Sie die neuen Jackson2-Abhängigkeiten verwenden, damit der Deserializer funktioniert.

Dont diese diese stattdessen

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

Gebrauch verwenden.

<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> 

Auch com.fasterxml.jackson.databind.JsonDeserializer und com.fasterxml.jackson.databind.annotation.JsonDeserialize für die Deserialisierung verwenden und nicht die Klassen von org.codehaus.jackson

Verwandte Themen