Forma correcta de escribir JSON deserializer en primavera o extenderlo
Estoy tratando de escribir un deserializador JSON personalizado en primavera. Quiero usar serializador predeterminado para la mayor parte de los campos y usar un deserializador personalizado para algunas propiedades. Es posible? Estoy tratando de esta manera porque, la mayor parte de las propiedades son valores, por lo que para estos puedo dejar que Jackson use deserializer predeterminado; pero pocas propiedades son referencias, por lo que en el deserializer personalizado tengo que consultar una base de datos para el nombre de referencia y obtener el valor de referencia de la base de datos.
Voy a mostrar algún código si necesario.
3 answers
He buscado mucho y la mejor manera que he encontrado hasta ahora es en este artículo:
Clase a 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 deserializer
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, puede ver este artículo que utiliza nuevas versiones de com.fasterxml.jackson.databind.JsonDeserializer.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-25 10:28:04
Estaba tratando de @Autowire
un servicio administrado por resorte en mi Deserializer
. Alguien me avisó a Jackson usando el operador new
cuando invocaba los serializadores/deserializadores. Esto significaba que no había cableado automático de la instancia de Jackson de mi Deserializer
. Así es como pude @Autowire
mi clase de servicio en mi Deserializer
:
Contexto.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 administrado por resorte, cableado automático 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: Aunque mi respuesta original funcionó para mí cuando escribí esto, la respuesta de @xi.lin es exactamente lo que se necesita. ¡Buen hallazgo!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-20 22:27:16
Con Resorte MVC 4.2.1.RELEASE, necesita usar las nuevas dependencias de Jackson2 como se muestra a continuación para que el Deserializador funcione.
No use esto
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.12</version>
</dependency>
Usa 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-15 11:53:36