J'essaie d'écrire un désérialiseur JSON personnalisé au printemps. Je souhaite utiliser le sérialiseur par défaut pour la plupart des champs et utiliser un désérialiseur personnalisé pour quelques propriétés. C'est possible? J'essaie de cette façon parce que, la plupart des propriétés sont des valeurs, je peux donc laisser Jackson utiliser le désérialiseur par défaut; mais peu de propriétés sont des références, donc dans le désérialiseur personnalisé, je dois interroger une base de données pour obtenir le nom de référence et obtenir la valeur de référence de la base de données.
Je montrerai du code si nécessaire.
J'ai beaucoup cherché et le meilleur moyen que j'ai trouvé jusqu'à présent est sur ce article :
Classe à 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; }
}
Classe de désérialiseur
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: Vous pouvez également consulter cet article , qui utilise les nouvelles versions de com.fasterxml.jackson.databind.JsonDeserializer.
J'essayais de @Autowire
Un service géré par Spring dans mon Deserializer
. Quelqu'un m'a prévenu de Jackson en utilisant l'opérateur new
lors de l'appel des sérialiseurs/désé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
:
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>
Maintenant que mon Deserializer
est un bean géré par Spring, le câblage automatique fonctionne!
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: Bien que ma réponse initiale ait fonctionné pour moi lorsque j'ai écrit ceci, la réponse de @ xi.lin correspond exactement à ce qui est nécessaire. Belle trouvaille!
Avec Spring MVC 4.2.1.RELEASE, vous devez utiliser les nouvelles dépendances de Jackson2 comme ci-dessous pour que le désérialiseur fonctionne.
Ne pas utiliser cette
<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>
Utiliser aussi com.fasterxml.jackson.databind.JsonDeserializer
et com.fasterxml.jackson.databind.annotation.JsonDeserialize
pour la désérialisation et non les classes de org.codehaus.jackson