Deserializing JSON into object with overloaded methods using Jackson

JavaJsonJackson

Java Problem Overview


I am attempting to deserialize a JSON object stored in CouchDb using Jackson. This object needs to deserialize into a pojo that contains overloaded methods. When I attempt to retrieve the object from couch and do the deserialization I get the following exception:

> org.ektorp.DbAccessException: > org.codehaus.jackson.map.JsonMappingException: > Conflicting setter definitions for > property "multiplier": > com.db.commodities.framework.sdos.model.security.EqOpt#setMultiplier(1 > params) vs > com.db.commodities.framework.sdos.model.security.EqOpt#setMultiplier(1 > params)

I tried to annotate the setter I would like Jackson to use, but that appears to not have worked.

@JsonProperty("multiplier")
public void setMultiplier(SDOSAttribute multiplier) {
     this.multiplier = multiplier;
}

public void setMultiplier(double multiplier) {
     this.multiplier.setValue(String.valueOf(multiplier));
}

How do I configure Jackson to properly deserialize using a specific method? Or am I approaching this problem the wrong way?

EDIT:

I have made the following changes. This seems to work, but is a little uglier. If anyone has a better way to do this please feel free to share and I will gladly accept.

@JsonProperty("multiplier")
protected void setMultiplierAttribute(SDOSAttribute multiplier) {
	this.multiplier = multiplier;
}

@JsonIgnore
public void setMultiplier(double multiplier) {
	this.multiplier.setValue(String.valueOf(multiplier));
}

Java Solutions


Solution 1 - Java

It's not necessary to change the name of the setter method to avoid ambiguity. You're otherwise on the right track with @JsonIgnore. With @JsonIgnore on all of the same-named methods to be ignored, the one to use does not need the @JsonProperty annotation.

Here's a simple example to demonstrate this point.

input.json: {"value":"forty-two"}

Foo.java:

import java.io.File;

import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.map.ObjectMapper;

public class Foo
{
  String value;
  
  public String getValue() {return value;}
  public void setValue(String value) {this.value = value;}
  
  @JsonIgnore
  public void setValue(int value) {this.value = String.valueOf(value);}
  
  public static void main(String[] args) throws Exception
  {
    ObjectMapper mapper = new ObjectMapper();
    Foo foo = mapper.readValue(new File("input.json"), Foo.class);
    System.out.println(mapper.writeValueAsString(foo));
  }
}

If you don't want to alter the pristine POJO defs with a Jackson annotation, then you can use a MixIn.

import java.io.File;

import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.map.ObjectMapper;

public class Foo
{
  String value;
  
  public String getValue() {return value;}
  public void setValue(String value) {this.value = value;}
  public void setValue(int value) {this.value = String.valueOf(value);}
  
  public static void main(String[] args) throws Exception
  {
    ObjectMapper mapper = new ObjectMapper();
    mapper.getDeserializationConfig().addMixInAnnotations(Foo.class, IgnoreFooSetValueIntMixIn.class);
    Foo foo = mapper.readValue(new File("input.json"), Foo.class);
    System.out.println(mapper.writeValueAsString(foo));
  }
}

abstract class IgnoreFooSetValueIntMixIn
{
  @JsonIgnore public abstract void setValue(int value);
}

Solution 2 - Java

In Jackson > 2.4 use directly :

mapper.addMixIn(Foo.class, IgnoreFooSetValueIntMixIn.class);

Solution 3 - Java

In cases where @JsonIgnore doesn't help (I currently have such a case, but am still unsure of the reason), it is also possible to use @XmlTransient instead.

Solution 4 - Java

@JsonSetter
public void setMultiplier(SDOSAttribute multiplier) {
     this.multiplier = multiplier;
}

public void setMultiplier(double multiplier) {
     this.multiplier.setValue(String.valueOf(multiplier));
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiongregwhitakerView Question on Stackoverflow
Solution 1 - JavaProgrammer BruceView Answer on Stackoverflow
Solution 2 - JavagriboView Answer on Stackoverflow
Solution 3 - JavalilalinuxView Answer on Stackoverflow
Solution 4 - Javauser17754330View Answer on Stackoverflow