it-swarm.com.de

Richtiger Weg, um JSON-Deserialisierer im Frühjahr zu schreiben oder zu erweitern

Ich versuche, im Frühjahr einen benutzerdefinierten JSON-Deserializer zu schreiben. Ich möchte das Standardserialisierungsprogramm für die meisten Felder und ein benutzerdefiniertes Deserialisierungsprogramm für einige Eigenschaften verwenden. Ist es möglich? Ich versuche es auf diese Weise, weil die meisten Eigenschaften Werte sind, also kann ich Jackson Standard-Deserialisierer verwenden lassen; Da nur wenige Eigenschaften Referenzen sind, muss ich im benutzerdefinierten Deserializer eine Datenbank nach dem Referenznamen abfragen und den Referenzwert aus der Datenbank abrufen.

Bei Bedarf zeige ich Code.

51
gc5

Ich habe viel gesucht und der beste Weg, den ich bisher gefunden habe, ist auf diesem Artikel :

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

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

Bearbeiten: Alternativ können Sie sich diesen Artikel ansehen, das neue Versionen von com.fasterxml.jackson.databind.JsonDeserializer verwendet.

78
gc5

Ich versuchte zu @Autowire ein Spring-Managed-Service in meinem Deserializer. Jemand hat mich mit dem Operator new an Jackson weitergeleitet, als er die Serializer/Deserializer aufrief. Dies bedeutete keine automatische Verkabelung von Jacksons Instanz meines Deserializer. So konnte ich @Autowire meine Serviceklasse in mein Deserializer:

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, da mein Deserializer ein Spring-Managed-Bean ist, funktioniert die automatische Verkabelung!

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

pdate: Während meine ursprüngliche Antwort zu dem Zeitpunkt, als ich sie schrieb, für mich funktionierte, ist die Antwort von @ xi.lin genau das, was benötigt wird. Nizza zu finden!

9
Beez

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

Verwenden Sie das nicht

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

Verwenden Sie dies stattdessen.

<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 verwenden com.fasterxml.jackson.databind.JsonDeserializer und com.fasterxml.jackson.databind.annotation.JsonDeserialize für die Deserialisierung und nicht die Klassen von org.codehaus.jackson

1
VimalKumar