Skip to content

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

@lbonco

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;

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

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions