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