Bonne façon d'écrire JSON deserializer au printemps ou de l'étendre

j'essaie d'écrire un JSON deserializer personnalisé au printemps. Je veux utiliser serializer par défaut pour la plupart des champs et utiliser un deserializer personnalisé pour quelques propriétés. Est-il possible? J'essaie de cette façon parce que, la plupart des propriétés sont des valeurs, donc pour celles-ci je peux laisser Jackson utiliser deserializer par défaut; mais peu de propriétés sont des références, donc dans le deserializer personnalisé je dois interroger une base de données pour le nom de référence et obtenir la valeur de référence de la base de données.

je vais en montrer code si nécessaire.

42
demandé sur rajadilipkolli 2012-07-07 19:36:20

3 réponses

j'ai beaucoup cherché et le meilleur moyen que j'ai trouvé pour l'instant est sur ce article:

Classe de sérialiser

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 classe

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

Modifier: Sinon, vous pouvez regarder cet article qui utilise de nouvelles versions de com.fasterxml.Jackson.databind.JsonDeserializer.

71
répondu fbrundu 2016-05-25 10:28:04

j'ai essayé @Autowire le Printemps de services gérés dans mon Deserializer. Quelqu'un m'a prévenu à Jackson en utilisant le new opérateur lors de l'invocation des sérialiseurs / desérialiseurs. Cela signifiait pas d'auto-câblage de L'instance de Jackson de mon Deserializer. Voici comment j'ai pu @Autowire ma classe de service dans mon Deserializer:

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

Maintenant que mon Deserializer est un haricot à ressort, auto-câblage œuvres!

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

mise à Jour: alors que ma réponse originale a fonctionné pour moi quand j'ai écrit ceci, @xi.la réponse de lin est exactement ce dont nous avons besoin. Jolie trouvaille!

8
répondu Beez 2015-01-20 22:27:16

avec ressort MVC 4.2.1.RELEASE, vous devez utiliser les nouvelles dépendances Jackson2 comme ci-dessous pour que le Deserializer fonctionne.

Ne pas utiliser ce

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

utilisez ceci à la place.

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

utilisez aussi com.fasterxml.jackson.databind.JsonDeserializer et com.fasterxml.jackson.databind.annotation.JsonDeserialize pour la desérialisation et non les classes de org.codehaus.jackson

1
répondu VimalKumar 2018-01-15 11:53:36