Tuesday, August 7, 2012

Jackson JsonMappingException: Infinite recursion

EDIT2: found a solution...see bottom.

EDIT: Ignore (some of) the stuff below :). Just occurred to me that it's not possible to check for circularity when a getter returns a new instance, and if that's the cause of the infinite recursion. And this seems to be the case for java.awt.Point's getLocation().

---- original text follows ----

What did the Jackson programmer/s do here?
org.codehaus.jackson.map.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: java.awt.Point["location"]->java.awt.Point["location"]->java.awt.Point["location"]->java.awt.Point["location"]->java.awt.Point["location"]->java.awt.Point["location"]->java.awt.Point["location"]->java.awt.Point["location"]->java.awt.Point["location"]->java.awt.Point["location"]->java.awt.Point["location"]->jav...
This doesn't help very much.

Wouldn't it be both easier and better feedback to detect circularity directly?

Could be implemented as a [[Identity]Hash]Set, where objects to be serialized are added on entering and removed again on exit (to allow sharing).

Or there might be reasons to use the StackOverflowError; but then the chain should be shown from the root, not from the top, since that would show the path to your problem. If length is a problem, the part just before the cycle is usually the most interesting. Do the hash set thing, and on first hit, you know you have detected the cycle. One might even show both the path leading up to the cycle, and the objects making up the cycle. Very valuable feedback; and almost trivial to implement, if one happens to have the time to do it.

For those of you happen to be coming here in need of a solution: use JsonIgnore, for instance. Like this:

@JsonIgnore
public BufferedImage javaBufferedImage;
If a BufferedImage happens to be the thing that has a java.awt.Point. Or consider a redesign where you don't mix non-serializable types in with serializable stuff.

BTW, the reason Point is not directly Jackson-serializable, is it's getLocation() (also has setLocation()) getter, I think.

EDIT2:

Found a somewhat general way to debug infinite recursion: configure Jackson to output an indented stream. Then check for a reasonable indentation depth, and cut the output at that point, since it's almost guaranteed to be caused by the infinite recursion. This should make it possible to manually inspect the output.

A consideration here is the fact that the Java debug protocol, the Eclipse debugger, and/or the Eclipse console seems fundamentally unable to efficiently handle large amounts of text or lines of text. So you might want to output the text to a file for viewing in your favorite editor. Or suffer.

I don't have the time right now to publish the source code I use; maybe later. Parting gift: a (partial!) java BufferedImage as JSON to admire:

      "bufferedImage" : {
        "type" : 6,
        "data" : {
          "pixelStride" : 4,
          "scanlineStride" : 420,
          "dataOffsets" : [ 3, 2, 1, 0 ],
          "dataStorage" : "/97Mxf/ezMX/3szF/97Mxf/ezMX/3szF/97Mxf/ezMX/3szF/97Mxf/ezMX/3szF/97Mxf/ezMX/3szF/97Mxf/ezMX/3szF/97Mxf/ezMX/3szF/97Mxf/ezMX/3szF/97Mxf/ezMX/3szF/97Mxf/ezMX/3szF/97Mxf/ezMX/3szF/97Mxf/ezMX/3szF/97Mxf/ezMX/3szF/97Mxf/ezMX/3szF/97Mxf/ezMX/3szF/97Mxf/ezMX/3szF/97Mxf/ezMX/3szF/97Mxf/ezMX/3szF/97Mxf/ezMX/3szF/97Mxf/ezMX/3szF/97Mxf/ezMX/3szF/97Mxf/ezMX/3szF/97Mxf/ezMX/3szF/97Mxf/ezMX/3szF/97Mxf/ezMX/3szF/97Mxf/ezMX/3szF/97Mxf/ezMX/3szF/97Mxf/ezMX/3szF/97Mxf
[...]


No comments:

Post a Comment