Skip to content

Commit 8b4f29d

Browse files
collapse empty arrays and objects when print json (#81)
1 parent c35d56d commit 8b4f29d

2 files changed

Lines changed: 145 additions & 8 deletions

File tree

webtau-http/src/main/java/com/twosigma/webtau/http/render/DataNodeAnsiPrinter.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,19 @@ private void printNode(DataNode dataNode, boolean skipIndent) {
6969
}
7070

7171
private void printObject(DataNode dataNode, boolean skipIndent) {
72+
if (dataNode.numberOfChildren() == 0) {
73+
printEmptyObject();
74+
} else {
75+
printNotEmptyObject(dataNode, skipIndent);
76+
}
77+
}
78+
79+
private void printEmptyObject() {
80+
printDelimiter("{");
81+
printDelimiter("}");
82+
}
83+
84+
private void printNotEmptyObject(DataNode dataNode, boolean skipIndent) {
7285
Map<String, DataNode> children = dataNode.asMap();
7386

7487
openScope("{", skipIndent);
@@ -96,10 +109,23 @@ private void printObject(DataNode dataNode, boolean skipIndent) {
96109
}
97110

98111
private void printList(DataNode dataNode, boolean skipIndent) {
112+
if (dataNode.elements().isEmpty()) {
113+
printEmptyList();
114+
} else {
115+
printNonEmptyList(dataNode, skipIndent);
116+
}
117+
}
118+
119+
private void printEmptyList() {
120+
printDelimiter("[");
121+
printDelimiter("]");
122+
}
123+
124+
private void printNonEmptyList(DataNode dataNode, boolean skipIndent) {
99125
openScope("[", skipIndent);
100126

101-
int idx = 0;
102127
int size = dataNode.elements().size();
128+
int idx = 0;
103129
for (DataNode n : dataNode.elements()) {
104130
printNode(n, false);
105131

@@ -216,6 +242,10 @@ private String indentation() {
216242
}
217243

218244
private static String indent(final int nestLevel) {
245+
if (nestLevel == 0) {
246+
return "";
247+
}
248+
219249
return StringUtils.leftPad(" ", nestLevel * 2);
220250
}
221251

webtau-http/src/test/groovy/com/twosigma/webtau/http/render/DataNodeAnsiPrinterTest.groovy

Lines changed: 114 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,23 @@
1616

1717
package com.twosigma.webtau.http.render
1818

19+
import com.twosigma.webtau.console.ConsoleOutput
1920
import com.twosigma.webtau.console.ConsoleOutputs
2021
import com.twosigma.webtau.console.ansi.AnsiConsoleOutput
22+
import com.twosigma.webtau.console.ansi.Color
23+
import com.twosigma.webtau.console.ansi.FontStyle
2124
import com.twosigma.webtau.http.datanode.DataNodeBuilder
2225
import com.twosigma.webtau.http.datanode.DataNodeId
2326
import org.junit.AfterClass
27+
import org.junit.Assert
2428
import org.junit.BeforeClass
2529
import org.junit.Test
2630

2731
import static com.twosigma.webtau.Ddjt.equal
2832

2933
class DataNodeAnsiPrinterTest {
3034
private static def ansiConsoleOutput = new AnsiConsoleOutput()
35+
3136
@BeforeClass
3237
static void init() {
3338
ConsoleOutputs.add(ansiConsoleOutput)
@@ -40,16 +45,44 @@ class DataNodeAnsiPrinterTest {
4045

4146
@Test
4247
void "should print list data node with indentation and using different colors"() {
43-
new DataNodeAnsiPrinter().print(DataNodeBuilder.fromList(new DataNodeId("root"), [1, 2, 3, 4]))
48+
def textOnly = withCapturedOutput {
49+
new DataNodeAnsiPrinter().print(DataNodeBuilder.fromList(new DataNodeId("root"), [1, 2, 3, 4]))
50+
}
51+
52+
Assert.assertEquals('[\n' +
53+
' 1,\n' +
54+
' 2,\n' +
55+
' 3,\n' +
56+
' 4\n' +
57+
']', textOnly)
4458
}
4559

4660
@Test
4761
void "should print object data node"() {
48-
new DataNodeAnsiPrinter().print(DataNodeBuilder.fromMap(new DataNodeId("root"), [
49-
key1: 'value1',
50-
key2: 'value2',
51-
key3: [key31: 'value31', key32: [5, 6, 8]],
52-
key4: [key41: 'value41', key42: 'value42']]))
62+
def textOnly = withCapturedOutput {
63+
new DataNodeAnsiPrinter().print(DataNodeBuilder.fromMap(new DataNodeId("root"), [
64+
key1: 'value1',
65+
key2: 'value2',
66+
key3: [key31: 'value31', key32: [5, 6, 8]],
67+
key4: [key41: 'value41', key42: 'value42']]))
68+
}
69+
70+
Assert.assertEquals('{\n' +
71+
' "key1": "value1",\n' +
72+
' "key2": "value2",\n' +
73+
' "key3": {\n' +
74+
' "key31": "value31",\n' +
75+
' "key32": [\n' +
76+
' 5,\n' +
77+
' 6,\n' +
78+
' 8\n' +
79+
' ]\n' +
80+
' },\n' +
81+
' "key4": {\n' +
82+
' "key41": "value41",\n' +
83+
' "key42": "value42"\n' +
84+
' }\n' +
85+
'}', textOnly)
5386
}
5487

5588
@Test
@@ -71,6 +104,80 @@ class DataNodeAnsiPrinterTest {
71104
// catch as it is an expected here and serves to check if the value will be rendered as failed
72105
}
73106

74-
new DataNodeAnsiPrinter().print(dataNode)
107+
def textOnly = withCapturedOutput {
108+
new DataNodeAnsiPrinter().print(dataNode)
109+
}
110+
111+
Assert.assertEquals('[\n' +
112+
' {\n' +
113+
' "key1": "value1",\n' +
114+
' "key2": __"value2"__,\n' +
115+
' "key3": {\n' +
116+
' "key31": **"value31"**,\n' +
117+
' "key32": [\n' +
118+
' 5,\n' +
119+
' 6,\n' +
120+
' 8\n' +
121+
' ]\n' +
122+
' }\n' +
123+
' },\n' +
124+
' {\n' +
125+
' "key4": "value4",\n' +
126+
' "key5": "value5"\n' +
127+
' }\n' +
128+
']', textOnly)
129+
}
130+
131+
@Test
132+
void "should collapse empty list and object"() {
133+
def textOnly = withCapturedOutput {
134+
new DataNodeAnsiPrinter().print(DataNodeBuilder.fromMap(new DataNodeId("root"), [
135+
key1: 'value1',
136+
key2: 'value2',
137+
key3: [],
138+
key4: [:]]))
139+
}
140+
141+
Assert.assertEquals('{\n' +
142+
' "key1": "value1",\n' +
143+
' "key2": "value2",\n' +
144+
' "key3": [],\n' +
145+
' "key4": {}\n' +
146+
'}', textOnly)
147+
}
148+
149+
private static String withCapturedOutput(Closure code) {
150+
def capture = new CaptureOutput()
151+
try {
152+
ConsoleOutputs.add(capture)
153+
code()
154+
155+
return capture.textOnly
156+
} finally {
157+
ConsoleOutputs.remove(capture)
158+
}
159+
}
160+
161+
private static class CaptureOutput implements ConsoleOutput {
162+
private def stylesAndOutput = []
163+
private def textLInes = []
164+
165+
@Override
166+
void out(Object... styleOrValues) {
167+
def line = Arrays.asList(styleOrValues).findAll {
168+
!(it instanceof Color) && !(it instanceof FontStyle)
169+
}.join('')
170+
171+
textLInes.add(line)
172+
stylesAndOutput.addAll(Arrays.asList(styleOrValues))
173+
}
174+
175+
String getTextOnly() {
176+
return textLInes.join('\n')
177+
}
178+
179+
@Override
180+
void err(Object... styleOrValues) {
181+
}
75182
}
76183
}

0 commit comments

Comments
 (0)