0

I have this class that I am using to store preferences for a tool. This class uses the toString() to convert itself to JSON. I am getting this infinite recursion error when I am converting the object to JSON, and I cannot figure out why. I do not have any circular references so it is confusing me a bit. Any help would be appreciated.

Here is my class structure:

public class ToolPrefs
{
   private boolean isFloating;
   private ToolPalettePlacement placement; //this is an enum
   private boolean isSelected;
   private int dockLocation;
   private Point dialogLocation;
   private Dimension dialogSize;

   public ToolPrefs(){}

   public boolean isFloating(){return isFloating; }

   public void setFloating(boolean floating){ isFloating = floating; }

   public ToolPalettePlacement getPlacement(){ return placement; }

   public void setPlacement(ToolPalettePlacement placement){ this.placement = placement;}

   public boolean isSelected(){ return isSelected;}

   public void setSelected(boolean selected){isSelected = selected;}

   public int getDockLocation(){return dockLocation;}

   public void setDockLocation(int dockLocation){this.dockLocation = dockLocation; }

   public Point getDialogLocation(){return dialogLocation;}

   public void setDialogLocation(Point dialogLocation){ this.dialogLocation = dialogLocation;}

   public Dimension getDialogSize(){ return dialogSize; }

   public void setDialogSize(Dimension dialogSize){this.dialogSize = dialogSize;}


   @JsonIgnore @Override
   public String toString()
   {
      String json;
      ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
      try
      {
         json = ow.writeValueAsString(this);
      }
      catch (IOException e)
      {
         e.printStackTrace();
         json = "";
      }
      return json;
   }
}

Here is the exception snippet I am receiving:

com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: java.awt.Point["location"]->java.awt.Point["location"]->java.awt.Point["location"]->java.awt.Point["location"]...) at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:518) at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:117) at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:464) at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:504) at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:117) at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:464) at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:504) at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:117) at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:464) at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:504) at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:117)

ShakMan
  • 35
  • 1
  • 8
  • try removing @JsonIgnore from toString(); – Derrick Oct 15 '16 at 20:39
  • It was not there initially, so I added it to see if it would resolve it but it didn't :( – ShakMan Oct 15 '16 at 20:43
  • it looks like your problem is in the `Point` class that you're importing... maybe this could help: http://impossible-is-development.blogspot.co.uk/2012/08/jackson-jsonmappingexception-infinite.html – thoeni Oct 15 '16 at 21:00

1 Answers1

3

The problem you're facing is due to the Point class that your Object is embedding.

To solve this issue, you can instruct Jackson to stop at first level of depth, and to implement this solution you can follow these steps:

1) First of all, you must be running the 2.x version of Jackson, I've tested the solution with this:

<dependencies>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.8.3</version>
    </dependency>
</dependencies>

2) When you initialise a new instance of the ObjectMapper, do this:

ObjectWriter ow = new ObjectMapper().configure(DEFAULT_VIEW_INCLUSION, true).writer().withDefaultPrettyPrinter();

3) Where you have the Point type, use the annotation:

@JsonView(Point.class) Point dialogLocation;

Jackson will stop at the first level, and the result will be:

{
  "dialogLocation" : {
    "x" : 2.0,
    "y" : 3.0
  }
}

For further documentation, you can see this:

Limit Jackson output to only one level

Enable default view inclusion on Jackson 2.x ObjectMapper

I've tested the solution and it works as long as you're using the 2.x version of Jackson. With 1.x I couldn't manage to have it running yet.

Community
  • 1
  • 1
thoeni
  • 4,064
  • 2
  • 14
  • 14
  • Thanks! This seems like it would work too. I will try this later. What I ended up doing was wrapping the Point instance into a "Location" class and that got around the infinite recursion issue. (go figure) – ShakMan Oct 15 '16 at 21:56