@@ -96,53 +96,83 @@ public JSONArray(JSONTokener x) throws JSONException {
9696 */
9797 public JSONArray (JSONTokener x , JSONParserConfiguration jsonParserConfiguration ) throws JSONException {
9898 this ();
99- if (x .nextClean () != '[' ) {
99+ char nextChar = x .nextClean ();
100+
101+ // check first character, if not '[' throw JSONException
102+ if (nextChar != '[' ) {
100103 throw x .syntaxError ("A JSONArray text must start with '['" );
101104 }
102105
103- char nextChar = x .nextClean ();
104- if (nextChar == 0 ) {
105- // array is unclosed. No ']' found, instead EOF
106- throw x .syntaxError ("Expected a ',' or ']'" );
107- }
108- if (nextChar != ']' ) {
109- x .back ();
110- for (;;) {
111- if (x .nextClean () == ',' ) {
112- x .back ();
113- this .myArrayList .add (JSONObject .NULL );
114- } else {
115- x .back ();
116- this .myArrayList .add (x .nextValue (jsonParserConfiguration ));
106+ parseTokener (x , jsonParserConfiguration ); // runs recursively
107+
108+ }
109+
110+ private void parseTokener (JSONTokener x , JSONParserConfiguration jsonParserConfiguration ) {
111+ boolean strictMode = jsonParserConfiguration .isStrictMode ();
112+
113+ char cursor = x .nextClean ();
114+
115+ switch (cursor ) {
116+ case 0 :
117+ throwErrorIfEoF (x );
118+ break ;
119+ case ',' :
120+ cursor = x .nextClean ();
121+
122+ throwErrorIfEoF (x );
123+
124+ if (strictMode && cursor == ']' ){
125+ throw x .syntaxError (getInvalidCharErrorMsg (cursor ));
117126 }
118- switch (x .nextClean ()) {
119- case 0 :
120- // array is unclosed. No ']' found, instead EOF
121- throw x .syntaxError ("Expected a ',' or ']'" );
122- case ',' :
123- nextChar = x .nextClean ();
124- if (nextChar == 0 ) {
125- // array is unclosed. No ']' found, instead EOF
126- throw x .syntaxError ("Expected a ',' or ']'" );
127- }
128- if (nextChar == ']' ) {
129- return ;
130- }
131- x .back ();
127+
128+ if (cursor == ']' ) {
129+ break ;
130+ }
131+
132+ x .back ();
133+
134+ parseTokener (x , jsonParserConfiguration );
135+ break ;
136+ case ']' :
137+ if (strictMode ) {
138+ cursor = x .nextClean ();
139+ boolean isEoF = x .end ();
140+
141+ if (isEoF ) {
132142 break ;
133- case ']' :
134- if (jsonParserConfiguration .isStrictMode ()) {
135- nextChar = x .nextClean ();
136- if (nextChar != 0 ) {
137- throw x .syntaxError ("invalid character found after end of array: " + nextChar );
138- }
139- }
140-
141- return ;
142- default :
143- throw x .syntaxError ("Expected a ',' or ']'" );
143+ }
144+
145+ if (x .getArrayLevel () == 0 ) {
146+ throw x .syntaxError (getInvalidCharErrorMsg (cursor ));
147+ }
148+
149+ x .back ();
144150 }
145- }
151+ break ;
152+ default :
153+ x .back ();
154+ boolean currentCharIsQuote = x .getPrevious () == '"' ;
155+ boolean quoteIsNotNextToValidChar = x .getPreviousChar () != ',' && x .getPreviousChar () != '[' ;
156+
157+ if (strictMode && currentCharIsQuote && quoteIsNotNextToValidChar ) {
158+ throw x .syntaxError (getInvalidCharErrorMsg (cursor ));
159+ }
160+
161+ this .myArrayList .add (x .nextValue (jsonParserConfiguration ));
162+ parseTokener (x , jsonParserConfiguration );
163+ }
164+ }
165+
166+ /**
167+ * Throws JSONException if JSONTokener has reached end of file, usually when array is unclosed. No ']' found,
168+ * instead EoF.
169+ *
170+ * @param x the JSONTokener being evaluated.
171+ * @throws JSONException if JSONTokener has reached end of file.
172+ */
173+ private void throwErrorIfEoF (JSONTokener x ) {
174+ if (x .end ()) {
175+ throw x .syntaxError (String .format ("Expected a ',' or ']' but instead found '%s'" , x .getPrevious ()));
146176 }
147177 }
148178
@@ -1932,6 +1962,7 @@ private void addAll(Object array, boolean wrap) throws JSONException {
19321962 private void addAll (Object array , boolean wrap , int recursionDepth ) {
19331963 addAll (array , wrap , recursionDepth , new JSONParserConfiguration ());
19341964 }
1965+
19351966 /**
19361967 * Add an array's elements to the JSONArray.
19371968 *`
@@ -1978,7 +2009,6 @@ private void addAll(Object array, boolean wrap, int recursionDepth, JSONParserCo
19782009 "JSONArray initial value should be a string or collection or array." );
19792010 }
19802011 }
1981-
19822012 /**
19832013 * Create a new JSONException in a common format for incorrect conversions.
19842014 * @param idx index of the item
@@ -2007,4 +2037,7 @@ private static JSONException wrongValueFormatException(
20072037 , cause );
20082038 }
20092039
2040+ private static String getInvalidCharErrorMsg (char cursor ) {
2041+ return String .format ("invalid character '%s' found after end of array" , cursor );
2042+ }
20102043}
0 commit comments