Подтвердить что ты не робот

Правильный способ записи десериализатора JSON в Spring или его расширение

Я пытаюсь написать собственный десериализатор JSON в Spring. Я хочу использовать сериализатор по умолчанию для большей части полей и использовать собственный десериализатор для нескольких свойств. Является ли это возможным? Я стараюсь так, потому что большая часть свойств - это значения, поэтому для них я могу позволить Jackson использовать десериализатор по умолчанию; но несколько свойств являются ссылками, поэтому в пользовательском десериализаторе я должен запросить базу данных для ссылочного имени и получить ссылочное значение из базы данных.

При необходимости покажу код.

4b9b3361

Ответ 1

Я много искал, и лучший способ, который я нашел до сих пор, - это статья:

Класс для сериализации

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.

Ответ 2

Я пытался @Autowire a Spring -управляемый сервис в мой Deserializer. Кто-то опрокинул меня в Джексон, используя оператор new при вызове сериализаторов/десериализаторов. Это означало отсутствие автоматической проводки экземпляра Джексона моего Deserializer. Вот как я смог @Autowire мой класс обслуживания в my 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 {}

Обновление. Хотя мой оригинальный ответ работал на меня, когда я писал это, ответ @xi.lin - это именно то, что необходимо. Приятно найти!

Ответ 3

С 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 и com.fasterxml.jackson.databind.annotation.JsonDeserialize для десериализации, а не классы из org.codehaus.jackson