我正在尝试在Spring中编写自定义的JSON反序列化器。我希望大部分字段使用默认的反序列化器,仅对少数属性使用自定义的反序列化器。这种方式可行吗? 我之所以采用这种方式是因为,大部分属性都是值类型,所以我可以让Jackson使用默认的反序列化器;但是有几个属性是引用类型,所以在自定义的反序列化器中,我必须查询数据库以获取引用名称并从数据库中获取引用值。
如果需要,我可以展示一些代码。
我正在尝试在Spring中编写自定义的JSON反序列化器。我希望大部分字段使用默认的反序列化器,仅对少数属性使用自定义的反序列化器。这种方式可行吗? 我之所以采用这种方式是因为,大部分属性都是值类型,所以我可以让Jackson使用默认的反序列化器;但是有几个属性是引用类型,所以在自定义的反序列化器中,我必须查询数据库以获取引用名称并从数据库中获取引用值。
如果需要,我可以展示一些代码。
我已经搜索了很多,目前发现最好的方法在这篇文章中:
用于序列化的类
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的新版本。
com.fasterxml.jackson.databind.JsonDeserializer
类中使用 asText()
而不是 getTextValue()
来获取文本。谢谢!+1 :)
- albciffStdDeserializer<Foo>
类,供您参考。 - coderatchetDeserializer
中。有人向我提示,Jackson在调用序列化器/反序列化器时使用new
操作符。这意味着无法自动装配Jackson实例中的Deserializer
。下面是我如何将我的服务类@Autowire
到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>
现在我的Deserializer
是一个由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 {}
使用Spring MVC 4.2.1.RELEASE版本时,您需要按照以下方式使用新的Jackson2依赖项才能使反序列化程序正常工作。
不要使用此方法
<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
和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
来创建Deserialisers / Serialisers实例来实现。在您的应用程序上下文配置中,创建带有 SpringHandlerInstantiator
的 ObjectMapper
bean,例如:
@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 来反序列化 json:
@Autowired
ObjectMapper objectMapper;
public Something readSomething(...){
...
Something st = objectMapper.readValue(json, Something.class);
...
return st;
}
ApplicationContext
管理的任何spring bean自动装配到其中。public class MyCustomDeserialiser extends ..{
@Autowired;
MyService service;
@AutoWired
SomeProperties properties;
@Override
public MyValue deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
....
}
...
}
此外,您可以在这里找到Jackson反序列化器的示例。