63

我正在尝试在 Spring 中编写自定义 JSON 反序列化器。我想对大部分字段使用默认序列化程序,并对少数属性使用自定义反序列化程序。是否可以?我正在尝试这种方式,因为大部分属性都是值,所以对于这些我可以让杰克逊使用默认的反序列化器;但很少有属性是引用,所以在自定义反序列化器中,我必须查询数据库以获取引用名称并从数据库中获取引用值。

如果需要,我会展示一些代码。

4

4 回答 4

95

我已经搜索了很多,到目前为止我发现的最好方法是在这篇文章中

要序列化的类

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的这篇文章。

于 2012-07-07T17:54:48.330 回答
11

我试图将@AutowireSpring 管理的服务放入我的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 的回应正是需要的。很好的发现!

于 2013-12-12T18:30:13.143 回答
1

使用 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.JsonDeserializerand com.fasterxml.jackson.databind.annotation.JsonDeserialize用于反序列化,而不是来自的类org.codehaus.jackson

于 2015-10-07T03:14:02.060 回答
0
  1. 如果您想覆盖特定属性的默认反序列化器,您可以标记要使用的属性和反序列化器,例如:

--

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

是一个完整的例子。

  1. 如果您想在 Spring 应用程序上下文中使用非 Spring 托管对象映射器并配置序列化器/反序列化器以使用 Spring 托管服务来查询数据库,这可以通过告诉 Jackson 用于Spring Handler instantiator创建反序列化器/序列化器的实例来实现。

在您的应用程序上下文配置中,创建ObjectMapperbean,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 解串器的示例。

于 2021-09-15T19:25:09.350 回答