Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Error deserializing read-only property with Jackson

In My CXF-based REST layer I am using Jackson for seializing/deserializing Groovy objects. The issue I am experiencing deals with deserializing a property that does not have a setter method. There is a domain object Dashboard with getGroups() method returning a list of Group objects. Upon serialization this object is properly converted to JSON with "group" attribute. When I send the object for update from JavaScript, JSON still has the "group" attribute. Since the property is read-only on the domain object I would like to simply ignore the "group" property when deserializing JSON.

Since I am using Jackson mix-ins, I tried various combination of @JsonIgnore, @JsonGetter and @JsonProperty annotations - all to no avail. If the property is available upon serialization, I get the error below in deserialization. I can clean the JSON object in JavaScript by removing the "group" attribute, bit I would like to find a server-side solution.

Caused by: com.fasterxml.jackson.databind.JsonMappingException: Problem deserializing 'setterless' property 'groups': get method returned null (through reference chain: org.ozoneplatform.commons.server.domain.model.DashboardTemplate["groups"])
at com.fasterxml.jackson.databind.deser.impl.SetterlessProperty.deserializeAndSet(SetterlessProperty.java:114)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:198)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:577)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObjectUsingNonDefault(BeanDeserializer.java:393)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:289)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121)
at com.fasterxml.jackson.databind.ObjectReader._bind(ObjectReader.java:1169)
at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:625)
at com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider.readFrom(JacksonJsonProvider.java:448)
at org.apache.cxf.jaxrs.utils.JAXRSUtils.readFromMessageBody(JAXRSUtils.java:1038)
at org.apache.cxf.jaxrs.utils.JAXRSUtils.processParameter(JAXRSUtils.java:614)
at org.apache.cxf.jaxrs.utils.JAXRSUtils.processParameters(JAXRSUtils.java:578)
at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.processRequest(JAXRSInInterceptor.java:238)

How can I tell Jackson to ignore a read-only property on deserialization?

Thank you,

Michael

like image 233
Michael Smolyak Avatar asked Mar 22 '13 21:03

Michael Smolyak


People also ask

What is JSON mapping exception?

public class JsonMappingException extends JsonProcessingException. Checked exception used to signal fatal problems with mapping of content, distinct from low-level I/O problems (signaled using simple IOException s) or data encoding/decoding problems (signaled with JsonParseException , JsonGenerationException ).

Does Jackson need default constructor?

Jackson uses default (no argument) constructor to create object and then sets value using setters. so you only need @NoArgsConstructor and @Setter.

How do you tell Jackson to ignore a field during serialization?

If there are fields in Java objects that do not wish to be serialized, we can use the @JsonIgnore annotation in the Jackson library. The @JsonIgnore can be used at the field level, for ignoring fields during the serialization and deserialization.


3 Answers

After many fruitless hours, I have finally found the magic combination of spells that addresses such a seemingly trivial issue. In the mixin I had to create this combination of annotations:

@JsonIgnore
abstract Set<Group> groups

@JsonProperty
abstract Set<Group> getGroups()

@JsonIgnore
abstract void setGroups(Set<Group> groups)

On top of that I had to add two configuration parameters to the ObjectMapper:

mapper.configure(MapperFeature.USE_GETTERS_AS_SETTERS, false)
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)

Isn't there a simpler way to achieve the same?

Michael

like image 109
Michael Smolyak Avatar answered Oct 21 '22 10:10

Michael Smolyak


I had the same issue. Solution was to give the getter the correct name:

List list...
setList(...)

was correct, but my getter was setProductList() which produced the "setterLess" error. changing it to: setList(...) resolved the issue

like image 34
user2693531 Avatar answered Oct 21 '22 11:10

user2693531


I just ran into the same problem, and my solution was to create a private, no-op setter:

public class MyFoo {
    public String getMyStr() {
        return "hello, world";
    }

    private void setMyStr(String ignored) {}
}

Making setMyStr private prevents me from accidentally trying to call it from my code, but Jackson still finds it and invokes it. Little does jackson know -- or care -- that invoking it does nothing.

like image 41
yshavit Avatar answered Oct 21 '22 10:10

yshavit