ejemplo deserializer deserialize custom java json spring jackson deserialization

java - ejemplo - jackson custom deserializer



Forma correcta de escribir el deserializador JSON en Spring o ampliarlo (3)

Estoy intentando escribir un deserializador JSON personalizado en Spring. Quiero usar el serializador predeterminado para la mayoría de las partes de los campos y usar un deserializador personalizado para algunas propiedades. ¿Es posible? Lo intento porque la mayor parte de las propiedades son valores, así que para estos puedo dejar que Jackson use el deserializador predeterminado; pero pocas propiedades son referencias, por lo que en el deserializador personalizado debo consultar una base de datos para obtener el nombre de referencia y obtener el valor de referencia de la base de datos.

Mostraré un código si es necesario.


Con Spring MVC 4.2.1.RELEASE, debe usar las nuevas dependencias Jackson2 como se indica a continuación para que funcione el Deserializer.

No uses esto

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

Use esto en su lugar.

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

También use com.fasterxml.jackson.databind.JsonDeserializer y com.fasterxml.jackson.databind.annotation.JsonDeserialize para la deserialización y no las clases de org.codehaus.jackson


Estaba intentando @Autowire un servicio administrado por Spring en mi Deserializer . Alguien me avisó a Jackson usando el new operador al invocar los serializadores / deserializadores. Esto significaba que no había ningún cableado automático de la instancia de mi Deserializer de Deserializer . Así es como pude @Autowire mi clase de servicio en mi 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>

¡Ahora que mi Deserializer es un frijol manejado por Spring, el auto-cableado funciona!

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

Actualización : Si bien mi respuesta original funcionó para mí cuando escribí esto, la respuesta de @xi.lin es exactamente lo que se necesita. Buen hallazgo!


He buscado mucho y la mejor manera que he encontrado hasta ahora es en este article :

Clase para serializar

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

Clase de deserializador

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

Editar: Alternativamente, puedes mirar este artículo que usa nuevas versiones de com.fasterxml.jackson.databind.JsonDeserializer.