Skip to content

Commit b71146b

Browse files
author
alwinsanil
committed
Broken Hierarchy: JSONStringer-JSONWriter code smell fix
1 parent 7b47c41 commit b71146b

1 file changed

Lines changed: 121 additions & 27 deletions

File tree

src/main/java/org/json/JSONStringer.java

Lines changed: 121 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,53 +7,147 @@
77
import java.io.StringWriter;
88

99
/**
10-
* JSONStringer provides a quick and convenient way of producing JSON text.
11-
* The texts produced strictly conform to JSON syntax rules. No whitespace is
12-
* added, so the results are ready for transmission or storage. Each instance of
13-
* JSONStringer can produce one JSON text.
10+
* JSONStringer provides a quick and convenient way of producing JSON text
11+
* using a StringWriter. The texts produced strictly conform to JSON syntax rules.
12+
* No whitespace is added, so the results are ready for transmission or storage.
13+
* Each instance of JSONStringer can produce one JSON text.
14+
* <p>
15+
* This class delegates to a {@link JSONWriter} instance while providing a
16+
* simplified interface for string-based JSON generation. It maintains the same
17+
* fluent API as JSONWriter but removes direct inheritance where it wasn't fully
18+
* utilized.
1419
* <p>
1520
* A JSONStringer instance provides a <code>value</code> method for appending
16-
* values to the
17-
* text, and a <code>key</code>
18-
* method for adding keys before values in objects. There are <code>array</code>
19-
* and <code>endArray</code> methods that make and bound array values, and
20-
* <code>object</code> and <code>endObject</code> methods which make and bound
21-
* object values. All of these methods return the JSONWriter instance,
22-
* permitting cascade style. For example, <pre>
21+
* values to the text, and a <code>key</code> method for adding keys before
22+
* values in objects. There are <code>array</code> and <code>endArray</code>
23+
* methods that make and bound array values, and <code>object</code> and
24+
* <code>endObject</code> methods which make and bound object values. All of
25+
* these methods return the JSONStringer instance, permitting cascade style.
26+
* For example:
27+
* <pre>
2328
* myString = new JSONStringer()
2429
* .object()
2530
* .key("JSON")
2631
* .value("Hello, World!")
2732
* .endObject()
28-
* .toString();</pre> which produces the string <pre>
33+
* .toString();</pre>
34+
* produces the string:
35+
* <pre>
2936
* {"JSON":"Hello, World!"}</pre>
3037
* <p>
3138
* The first method called must be <code>array</code> or <code>object</code>.
32-
* There are no methods for adding commas or colons. JSONStringer adds them for
33-
* you. Objects and arrays can be nested up to 200 levels deep.
39+
* Commas and colons are automatically added by the delegate JSONWriter.
40+
* Objects and arrays can be nested up to 200 levels deep.
3441
* <p>
35-
* This can sometimes be easier than using a JSONObject to build a string.
42+
* This is often simpler than using JSONObject directly for string generation.
43+
*
3644
* @author JSON.org
37-
* @version 2015-12-09
45+
* @version 2023-07-20 (Refactored to use delegation)
3846
*/
39-
public class JSONStringer extends JSONWriter {
47+
public class JSONStringer {
48+
private final JSONWriter writer;
49+
private final StringWriter stringWriter;
50+
4051
/**
41-
* Make a fresh JSONStringer. It can be used to build one JSON text.
52+
* Constructs a fresh JSONStringer instance. Each instance can build one
53+
* complete JSON text. The underlying StringWriter and JSONWriter are
54+
* initialized automatically.
4255
*/
4356
public JSONStringer() {
44-
super(new StringWriter());
57+
this.stringWriter = new StringWriter();
58+
this.writer = new JSONWriter(stringWriter);
59+
}
60+
61+
/**
62+
* Begins appending a new array. All values until the balancing
63+
* {@link #endArray()} will be appended to this array.
64+
*
65+
* @return this JSONStringer for method chaining
66+
* @throws JSONException If nesting is too deep or called in invalid context
67+
* @see JSONWriter#array()
68+
*/
69+
public JSONStringer array() throws JSONException {
70+
writer.array();
71+
return this;
72+
}
73+
74+
/**
75+
* Ends the current array. Must be called to balance array starts.
76+
*
77+
* @return this JSONStringer for method chaining
78+
* @throws JSONException If incorrectly nested
79+
* @see JSONWriter#endArray()
80+
*/
81+
public JSONStringer endArray() throws JSONException {
82+
writer.endArray();
83+
return this;
84+
}
85+
86+
/**
87+
* Begins appending a new object. All keys and values until {@link #endObject()}
88+
* will be appended to this object.
89+
*
90+
* @return this JSONStringer for method chaining
91+
* @throws JSONException If nesting is too deep or called in invalid context
92+
* @see JSONWriter#object()
93+
*/
94+
public JSONStringer object() throws JSONException {
95+
writer.object();
96+
return this;
97+
}
98+
99+
/**
100+
* Ends the current object. Must be called to balance object starts.
101+
*
102+
* @return this JSONStringer for method chaining
103+
* @throws JSONException If incorrectly nested
104+
* @see JSONWriter#endObject()
105+
*/
106+
public JSONStringer endObject() throws JSONException {
107+
writer.endObject();
108+
return this;
109+
}
110+
111+
/**
112+
* Appends a key to the current object. The next value will be associated
113+
* with this key.
114+
*
115+
* @param key The key string (must not be null)
116+
* @return this JSONStringer for method chaining
117+
* @throws JSONException If key is null or called in invalid context
118+
* @see JSONWriter#key(String)
119+
*/
120+
public JSONStringer key(String key) throws JSONException {
121+
writer.key(key);
122+
return this;
123+
}
124+
125+
/**
126+
* Appends a value to the current array or object.
127+
*
128+
* @param value The value to append (may be null, Boolean, Number, String,
129+
* JSONObject, JSONArray, or JSONString)
130+
* @return this JSONStringer for method chaining
131+
* @throws JSONException If value is invalid or called in wrong context
132+
* @see JSONWriter#value(Object)
133+
*/
134+
public JSONStringer value(Object value) throws JSONException {
135+
writer.value(value);
136+
return this;
45137
}
46138

47139
/**
48-
* Return the JSON text. This method is used to obtain the product of the
49-
* JSONStringer instance. It will return <code>null</code> if there was a
50-
* problem in the construction of the JSON text (such as the calls to
51-
* <code>array</code> were not properly balanced with calls to
52-
* <code>endArray</code>).
53-
* @return The JSON text.
140+
* Returns the generated JSON text. Returns null if:
141+
* <ul>
142+
* <li>No array/object was started
143+
* <li>The JSON structure is incomplete (unbalanced arrays/objects)
144+
* </ul>
145+
*
146+
* @return The JSON text or null if incomplete
147+
* @see JSONWriter#mode
54148
*/
55149
@Override
56150
public String toString() {
57-
return this.mode == 'd' ? this.writer.toString() : null;
151+
return writer.mode == 'd' ? stringWriter.toString() : null;
58152
}
59-
}
153+
}

0 commit comments

Comments
 (0)