Skip to content

Should never call set() on setterless property during deserialization #2692

Description

@lbonco

Hi,
I have something like the following code:

public class DataBean {

   private final String val;

   @JsonCreator
   public DataBean(
   		@JsonProperty(value = "val")
   		String val) {
   	super();
   	this.val = val;
   }

   public String getVal() {
   	return val;
   }
   
   public List<String> getList(){
   	return new ArrayList<>();
   }

   @Override
   public String toString() {
   	return "DataBean [val=" + val + "]";
   }
   public static void main(String[] args) throws Exception {
   	ObjectMapper om = new ObjectMapper();
   	String json;
   	DataBean out;
   	json = "{\"list\":[\"11\"],\"val\":\"VAL2\"}";
   	out = om.readerFor(DataBean.class).readValue(json);
   	System.out.println("this is ko" + out);
   }
}

When I run the test, I get:

Exception in thread "main" com.fasterxml.jackson.databind.exc.ValueInstantiationException: Cannot construct instance of `DataBean`, problem: Should never call `set()` on setterless property ('list')
at [Source: (String)"{"list":["11"],"val":"VAL2"}"; line: 1, column: 28]
   at com.fasterxml.jackson.databind.exc.ValueInstantiationException.from(ValueInstantiationException.java:47)
   at com.fasterxml.jackson.databind.DeserializationContext.instantiationException(DeserializationContext.java:1735)
   at com.fasterxml.jackson.databind.DeserializationContext.handleInstantiationProblem(DeserializationContext.java:1109)
   at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.wrapInstantiationProblem(BeanDeserializerBase.java:1757)
   at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:424)
   at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1287)
   at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:326)
   at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159)
   at com.fasterxml.jackson.databind.ObjectReader._bindAndClose(ObjectReader.java:1719)
   at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:1261)
   at DataBean.main(DataBean.java:53)
Caused by: java.lang.UnsupportedOperationException: Should never call `set()` on setterless property ('list')
   at com.fasterxml.jackson.databind.deser.impl.SetterlessProperty.set(SetterlessProperty.java:147)
   at com.fasterxml.jackson.databind.deser.impl.PropertyValue$Regular.assign(PropertyValue.java:62)
   at com.fasterxml.jackson.databind.deser.impl.PropertyBasedCreator.build(PropertyBasedCreator.java:207)
   at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:422)

If I modify the JSON, having the value of the constructor as first field, it runs OK.

In order to solve the issue, I try the following horrible patch:

diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/impl/SetterlessProperty.java b/src/main/java/com/fasterxml/jackson/databind/deser/impl/SetterlessProperty.java
index 9c80e49..ca7ec85 100644
--- a/src/main/java/com/fasterxml/jackson/databind/deser/impl/SetterlessProperty.java
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/impl/SetterlessProperty.java
@@ -3,6 +3,8 @@
 import java.io.IOException;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.List;
 
 import com.fasterxml.jackson.core.JsonParser;
 import com.fasterxml.jackson.core.JsonToken;
@@ -144,7 +146,21 @@
 
     @Override
     public final void set(Object instance, Object value) throws IOException {
-        throw new UnsupportedOperationException("Should never call `set()` on setterless property ('"+getName()+"')");
+    	if(value instanceof Collection) {
+    		
+    		Collection<Object> collection = (Collection<Object>) value;
+			Collection<Object> toModify;
+    		try {
+    			toModify = (Collection<Object> )_getter.invoke(instance, (Object[]) null);
+    			toModify.addAll(collection);
+    		} catch (Exception e) {
+    			_throwAsIOE((JsonParser)null, e);
+    			return; // never gets here
+    		}
+    		
+    	} else {
+    		throw new UnsupportedOperationException("Should never call `set()` on setterless property ('"+getName()+"')");
+    	}
     }
 
     @Override+    Collection<Object> collection = (Collection<Object>) value;

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    2.20Issues planned at 2.20 or laterhas-failing-testIndicates that there exists a test case (under `failing/`) to reproduce the issue

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions