I am trying to write a custom JSON deserializer in Spring. I want to use default serializer for most part of fields and use a custom deserializer for few properties. Is it possible? I am trying this way because, most part of properties are values, so for these I can let Jackson use default deserializer; but few properties are references, so in the custom deserializer I have to query a database for reference name and get reference value from database.
I'll show some code if needed.
The @JsonDeserialize annotation is used to declare custom deserializer while deserializing JSON to Java object. We can implement a custom deserializer by extending the StdDeserializer class with a generic type Employee and need to override the deserialize() method of StdDeserializer class.
To create a custom deserializer, we need to create a class extending StdDeserializer and then override its deserialize() method. We can use custom deserializer either by registering with ObjectMapper or annotating class with @JsonDeserialize .
@JsonDeserialize is used to specify custom deserializer to unmarshall the json object.
Jackson is a powerful and efficient Java library that handles the serialization and deserialization of Java objects and their JSON representations. It's one of the most widely used libraries for this task, and runs under the hood of many other frameworks.
I've searched a lot and the best way I've found so far is on this article:
Class to serialize
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; } }
Deserializer class
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()); } }
Edit: Alternatively you can look at this article which uses new versions of com.fasterxml.jackson.databind.JsonDeserializer.
I was trying to @Autowire
a Spring-managed service into my Deserializer
. Somebody tipped me off to Jackson using the new
operator when invoking the serializers/deserializers. This meant no auto-wiring of Jackson's instance of my Deserializer
. Here's how I was able to @Autowire
my service class into 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>
Now that my Deserializer
is a Spring-managed bean, auto-wiring works!
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 {}
Update: While my original answer worked for me back when I wrote this, @xi.lin's response is exactly what is needed. Nice find!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With