我正在尝试在 Spring 中编写自定义 JSON 反序列化器。我想对大部分字段使用默认序列化程序,并对少数属性使用自定义反序列化程序。是否可以?我正在尝试这种方式,因为大部分属性都是值,所以对于这些我可以让杰克逊使用默认的反序列化器;但很少有属性是引用,所以在自定义反序列化器中,我必须查询数据库以获取引用名称并从数据库中获取引用值。
如果需要,我会展示一些代码。
我正在尝试在 Spring 中编写自定义 JSON 反序列化器。我想对大部分字段使用默认序列化程序,并对少数属性使用自定义反序列化程序。是否可以?我正在尝试这种方式,因为大部分属性都是值,所以对于这些我可以让杰克逊使用默认的反序列化器;但很少有属性是引用,所以在自定义反序列化器中,我必须查询数据库以获取引用名称并从数据库中获取引用值。
如果需要,我会展示一些代码。
我已经搜索了很多,到目前为止我发现的最好方法是在这篇文章中:
要序列化的类
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; }
}
反序列化器类
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());
}
}
编辑:或者,您可以查看使用新版本 com.fasterxml.jackson.databind.JsonDeserializer的这篇文章。
我试图将@Autowire
Spring 管理的服务放入我的Deserializer
. new
有人在调用序列化器/反序列化器时使用操作员向杰克逊小费。这意味着杰克逊的 my Deserializer
. 以下是我如何能够将@Autowire
我的服务类纳入我的Deserializer
:
上下文.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>
既然 myDeserializer
是 Spring 管理的 bean,自动装配就可以了!
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 {}
更新:当我写这篇文章时,我原来的答案对我有用,@xi.lin 的回应正是需要的。很好的发现!
使用 Spring MVC 4.2.1.RELEASE,您需要使用新的 Jackson2 依赖项,如下所示,Deserializer 才能工作。
不要使用这个
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.12</version>
</dependency>
改用这个。
<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>
也使用com.fasterxml.jackson.databind.JsonDeserializer
and com.fasterxml.jackson.databind.annotation.JsonDeserialize
用于反序列化,而不是来自的类org.codehaus.jackson
--
// root json object
public class Example {
private String name;
private int value;
// You will implement your own deserilizer/Serializer for the field below//
@JsonSerialize(converter = AddressSerializer.class)
@JsonDeserialize(converter = AddressDeserializer.class)
private String address;
}
这是一个完整的例子。
Spring Handler instantiator
创建反序列化器/序列化器的实例来实现。在您的应用程序上下文配置中,创建ObjectMapper
bean,SpringHandlerInstantiator
例如:
@Autowired
ApplicationContext applicationContext;
@Bean
public ObjectMapper objectMapper(){
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.handlerInstantiator(handlerInstantiator());
// add additional configs, etc.. here if needed
return builder.build();
}
@Bean
public HandlerInstantiator handlerInstantiator(){
return new SpringHandlerInstantiator(applicationContext.getAutowireCapableBeanFactory());
}
然后您可以在 objectMapper 上方 @Autowire 反序列化 jsons:
@Autowired
ObjectMapper objectMapper;
public Something readSomething(...){
...
Something st = objectMapper.readValue(json, Something.class);
...
return st;
}
无论您要使用哪种反序列化器,即:字段或类,您都可以在反序列化器中使用 spring 上下文,这意味着您可以 @Autowire 您的服务或由其管理的任何 spring bean ApplicationContext
。
public class MyCustomDeserialiser extends ..{
@Autowired;
MyService service;
@AutoWired
SomeProperties properties;
@Override
public MyValue deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
....
}
...
}
此外,您可以在此处找到 Jackson 解串器的示例。