Skip to content

Consider detecting cycles when constructing JSONObjects #632

@cushon

Description

@cushon

JSONObject.populateMap mentions that "the bean can not be recursive", and attempting to pass a recursive bean to JSONObject results in a StackOverflowError. The StackOverflowError can be hard to debug, because the stack trace is usually truncated before the frames that show where new JSONObject(bean) was called.

It might be worth detecting cycles when constructing JSONObjects to report a better error message for beans containing cycles.

import org.json.JSONObject;

class Json {

  public static void main(String[] args) {
    new JSONObject(new Foo());
  }

  public static class Foo {

    public Bar getBar() {
      return new Bar(this);
    }
  }

  public static class Bar {

    private final Foo foo;

    Bar(Foo foo) {
      this.foo = foo;
    }

    public Foo getFoo() {
      return foo;
    }
  }
}
Exception in thread "main" java.lang.StackOverflowError
	at java.base/java.lang.reflect.Method.getRoot(Method.java:68)
	at java.base/java.lang.reflect.Executable.declaredAnnotations(Executable.java:600)
	at java.base/java.lang.reflect.Executable.getAnnotation(Executable.java:572)
	at java.base/java.lang.reflect.Method.getAnnotation(Method.java:695)
	at java.base/java.lang.reflect.AnnotatedElement.isAnnotationPresent(AnnotatedElement.java:274)
	at java.base/java.lang.reflect.AccessibleObject.isAnnotationPresent(AccessibleObject.java:525)
	at org.json.JSONObject.getAnnotationDepth(JSONObject.java:1674)
	at org.json.JSONObject.getKeyNameFromMethod(JSONObject.java:1568)
	at org.json.JSONObject.populateMap(JSONObject.java:1538)
	at org.json.JSONObject.<init>(JSONObject.java:365)
	at org.json.JSONObject.wrap(JSONObject.java:2475)
	at org.json.JSONObject.populateMap(JSONObject.java:1543)
	at org.json.JSONObject.<init>(JSONObject.java:365)
	at org.json.JSONObject.wrap(JSONObject.java:2475)
	at org.json.JSONObject.populateMap(JSONObject.java:1543)
	at org.json.JSONObject.<init>(JSONObject.java:365)
	at org.json.JSONObject.wrap(JSONObject.java:2475)
	at org.json.JSONObject.populateMap(JSONObject.java:1543)
	at org.json.JSONObject.<init>(JSONObject.java:365)
	at org.json.JSONObject.wrap(JSONObject.java:2475)
	at org.json.JSONObject.populateMap(JSONObject.java:1543)
	at org.json.JSONObject.<init>(JSONObject.java:365)
	at org.json.JSONObject.wrap(JSONObject.java:2475)
	at org.json.JSONObject.populateMap(JSONObject.java:1543)
	at org.json.JSONObject.<init>(JSONObject.java:365)
	at org.json.JSONObject.wrap(JSONObject.java:2475)
	at org.json.JSONObject.populateMap(JSONObject.java:1543)
	at org.json.JSONObject.<init>(JSONObject.java:365)
	at org.json.JSONObject.wrap(JSONObject.java:2475)
	at org.json.JSONObject.populateMap(JSONObject.java:1543)

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions