Skip to content

Commit 126c8fd

Browse files
committed
F!! Better help message for circular references in Gson
1 parent 5ae01ce commit 126c8fd

File tree

10 files changed

+69
-29
lines changed

10 files changed

+69
-29
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package org.approvaltests;
2+
3+
public class Circular {
4+
Circular parent;
5+
String label;
6+
7+
public Circular(Circular parent, String label) {
8+
this.parent = parent;
9+
this.label = label;
10+
}
11+
12+
public static Circular getIndirectCircularReference() {
13+
Circular level1 = new Circular(null, "middle");
14+
Circular level2 = new Circular(level1, "child");
15+
level1.parent = level2;
16+
return level1;
17+
}
18+
}

approvaltests-tests/src/test/java/org/approvaltests/DocumentHelpersTest.listAllVerifyFunctions.approved.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@
5050
* CombinationApprovals. [verifyBestCoveringPairs ](https://github.com/approvals/ApprovalTests.Java/blob/master/approvaltests/src/main/java/org/approvaltests/combinations/CombinationApprovals.java#L290-L293) (Function7,Object[],Object[],Object[],Object[],Object[],Object[],Object[])
5151
* CombinationApprovals. [verifyBestCoveringPairs ](https://github.com/approvals/ApprovalTests.Java/blob/master/approvaltests/src/main/java/org/approvaltests/combinations/CombinationApprovals.java#L308-L311) (Function8,Object[],Object[],Object[],Object[],Object[],Object[],Object[],Object[])
5252
* CombinationApprovals. [verifyBestCoveringPairs ](https://github.com/approvals/ApprovalTests.Java/blob/master/approvaltests/src/main/java/org/approvaltests/combinations/CombinationApprovals.java#L326-L329) (Function9,Object[],Object[],Object[],Object[],Object[],Object[],Object[],Object[],Object[])
53-
* JsonApprovals. [verifyAsJson ](https://github.com/approvals/ApprovalTests.Java/blob/master/approvaltests/src/main/java/org/approvaltests/JsonApprovals.java#L25-L28) (Object)
54-
* JsonApprovals. [verifyAsJson ](https://github.com/approvals/ApprovalTests.Java/blob/master/approvaltests/src/main/java/org/approvaltests/JsonApprovals.java#L29-L32) (Object,Function1)
55-
* JsonApprovals. [verifyJson ](https://github.com/approvals/ApprovalTests.Java/blob/master/approvaltests/src/main/java/org/approvaltests/JsonApprovals.java#L17-L20) (String)
53+
* JsonApprovals. [verifyAsJson ](https://github.com/approvals/ApprovalTests.Java/blob/master/approvaltests/src/main/java/org/approvaltests/JsonApprovals.java#L26-L29) (Object)
54+
* JsonApprovals. [verifyAsJson ](https://github.com/approvals/ApprovalTests.Java/blob/master/approvaltests/src/main/java/org/approvaltests/JsonApprovals.java#L30-L33) (Object,Function1)
55+
* JsonApprovals. [verifyJson ](https://github.com/approvals/ApprovalTests.Java/blob/master/approvaltests/src/main/java/org/approvaltests/JsonApprovals.java#L18-L21) (String)
5656
* JsonJacksonApprovals. [verifyAsJson ](https://github.com/approvals/ApprovalTests.Java/blob/master/approvaltests/src/main/java/org/approvaltests/JsonJacksonApprovals.java#L10-L13) (Object)
5757
* VelocityApprovals. [verify ](https://github.com/approvals/ApprovalTests.Java/blob/master/approvaltests/src/main/java/org/approvaltests/velocity/VelocityApprovals.java#L16-L19) (ContextAware)

approvaltests-tests/src/test/java/org/approvaltests/JsonFormattingTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@
77

88
public class JsonFormattingTest
99
{
10+
@Test
11+
public void testGsonCircular()
12+
{
13+
Approvals.verifyException(() -> {
14+
JsonApprovals.verifyAsJson(Circular.getIndirectCircularReference());
15+
});
16+
}
17+
1018
@Test
1119
public void testBasicFormatting()
1220
{
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
java.lang.RuntimeException: Circular reference found.
2+
Gson does not handle circular references.
3+
Consider:
4+
1. Using XStream (JsonXstreamApprovals)
5+
2. Remove the circular reference.

approvaltests-tests/src/test/java/org/approvaltests/JsonXstreamApprovalTest.java

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,20 @@
22

33
import org.junit.jupiter.api.Test;
44

5-
import java.time.Instant;
6-
75
public class JsonXstreamApprovalTest
86
{
7+
@Test
8+
public void testXstreamCircular()
9+
{
10+
Circular middle = Circular.getIndirectCircularReference();
11+
JsonXstreamApprovals.verifyAsJson(middle);
12+
}
913
@Test
1014
public void testBasicFormatting()
1115
{
12-
Circular c = new Circular();
13-
JsonXtreamApprovals.verifyAsJson(c);
16+
Circular c = new Circular(null, "Label");
17+
c.parent = c;
18+
JsonXstreamApprovals.verifyAsJson(c);
1419
}
1520

16-
public static class Circular {
17-
Circular parent;
18-
String label;
19-
20-
public Circular() {
21-
this.parent = this;
22-
this.label = "Label";
23-
}
24-
}
2521
}

approvaltests-tests/src/test/java/org/approvaltests/JsonXstreamApprovalTest.testBasicFormatting.approved.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{"org.approvaltests.JsonXstreamApprovalTest$Circular": {
1+
{"org.approvaltests.Circular": {
22
"parent": {
33
"@reference": ".."
44
},
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{"org.approvaltests.Circular": {
2+
"parent": {
3+
"parent": {
4+
"@reference": "../.."
5+
},
6+
"label": "child"
7+
},
8+
"label": "middle"
9+
}}

approvaltests-util/src/main/java/com/spun/util/JsonUtils.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,14 @@ public static <T> String asJsonWithBuilder(Object o, Function1<T, T> gsonBuilder
4141
}
4242
public static <T> String asJson(Object o, Function1<GsonBuilder, GsonBuilder> gsonBuilder)
4343
{
44-
GsonBuilder builder = new GsonBuilder().setPrettyPrinting();
45-
builder = addHandlingForDateObjects(builder);
46-
Gson gson = gsonBuilder.call(builder).create();
47-
return gson.toJson(o);
44+
try {
45+
GsonBuilder builder = new GsonBuilder().setPrettyPrinting();
46+
builder = addHandlingForDateObjects(builder);
47+
Gson gson = gsonBuilder.call(builder).create();
48+
return gson.toJson(o);
49+
} catch (StackOverflowError e) {
50+
throw new RuntimeException("Circular reference found.\nGson does not handle circular references.\nConsider:\n 1. Using XStream (JsonXstreamApprovals)\n 2. Remove the circular reference.", e);
51+
}
4852
}
4953
private static GsonBuilder addHandlingForDateObjects(GsonBuilder builder)
5054
{

approvaltests/src/main/java/org/approvaltests/JsonApprovals.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.approvaltests;
22

33
import com.google.gson.GsonBuilder;
4+
import com.spun.util.FormattedException;
45
import com.spun.util.JsonUtils;
56
import org.approvaltests.core.Options;
67
import org.lambda.functions.Function1;
@@ -28,7 +29,7 @@ public static void verifyAsJson(Object o, Function1<GsonBuilder, GsonBuilder> gs
2829
}
2930
public static void verifyAsJson(Object o, Function1<GsonBuilder, GsonBuilder> gsonBuilder, Options options)
3031
{
31-
Approvals.verify(JsonUtils.asJson(o, gsonBuilder), options.forFile().withExtension(".json"));
32+
Approvals.verify(JsonUtils.asJson(o, gsonBuilder), options.forFile().withExtension(".json"));
3233
}
3334
// begin-snippet: verify_as_json
3435
public static void verifyAsJson(Object o, Options options)

approvaltests/src/main/java/org/approvaltests/JsonXtreamApprovals.java renamed to approvaltests/src/main/java/org/approvaltests/JsonXstreamApprovals.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
package org.approvaltests;
22

33
import com.thoughtworks.xstream.XStream;
4-
import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver;
54
import com.thoughtworks.xstream.io.json.JsonHierarchicalStreamDriver;
6-
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
75
import org.approvaltests.core.Options;
86

9-
import java.io.BufferedOutputStream;
10-
import java.io.BufferedWriter;
11-
import java.io.StringWriter;
12-
13-
public class JsonXtreamApprovals
7+
/**
8+
* Requires (XStream)[https://mvnrepository.com/artifact/com.thoughtworks.xstream/xstream]
9+
* Requires (Jettison)[https://mvnrepository.com/artifact/org.codehaus.jettison/jettison]
10+
* Requires (Camel-XStream)[https://mvnrepository.com/artifact/org.apache.camel/camel-xstream]
11+
*/
12+
public class JsonXstreamApprovals
1413
{
1514
public static void verifyAsJson(Object o)
1615
{

0 commit comments

Comments
 (0)