1717package com .google .gson .stream ;
1818
1919import com .google .gson .internal .JsonReaderInternalAccess ;
20+ import com .google .gson .internal .TroubleshootingGuide ;
2021import com .google .gson .internal .bind .JsonTreeReader ;
2122import java .io .Closeable ;
2223import java .io .EOFException ;
@@ -355,7 +356,7 @@ public void beginArray() throws IOException {
355356 pathIndices [stackSize - 1 ] = 0 ;
356357 peeked = PEEKED_NONE ;
357358 } else {
358- throw new IllegalStateException ( "Expected BEGIN_ARRAY but was " + peek () + locationString () );
359+ throw unexpectedTokenError ( " BEGIN_ARRAY" );
359360 }
360361 }
361362
@@ -373,7 +374,7 @@ public void endArray() throws IOException {
373374 pathIndices [stackSize - 1 ]++;
374375 peeked = PEEKED_NONE ;
375376 } else {
376- throw new IllegalStateException ( "Expected END_ARRAY but was " + peek () + locationString () );
377+ throw unexpectedTokenError ( " END_ARRAY" );
377378 }
378379 }
379380
@@ -390,7 +391,7 @@ public void beginObject() throws IOException {
390391 push (JsonScope .EMPTY_OBJECT );
391392 peeked = PEEKED_NONE ;
392393 } else {
393- throw new IllegalStateException ( "Expected BEGIN_OBJECT but was " + peek () + locationString () );
394+ throw unexpectedTokenError ( " BEGIN_OBJECT" );
394395 }
395396 }
396397
@@ -409,7 +410,7 @@ public void endObject() throws IOException {
409410 pathIndices [stackSize - 1 ]++;
410411 peeked = PEEKED_NONE ;
411412 } else {
412- throw new IllegalStateException ( "Expected END_OBJECT but was " + peek () + locationString () );
413+ throw unexpectedTokenError ( " END_OBJECT" );
413414 }
414415 }
415416
@@ -797,7 +798,7 @@ public String nextName() throws IOException {
797798 } else if (p == PEEKED_DOUBLE_QUOTED_NAME ) {
798799 result = nextQuotedValue ('"' );
799800 } else {
800- throw new IllegalStateException ( "Expected a name but was " + peek () + locationString () );
801+ throw unexpectedTokenError ( " a name" );
801802 }
802803 peeked = PEEKED_NONE ;
803804 pathNames [stackSize - 1 ] = result ;
@@ -833,7 +834,7 @@ public String nextString() throws IOException {
833834 result = new String (buffer , pos , peekedNumberLength );
834835 pos += peekedNumberLength ;
835836 } else {
836- throw new IllegalStateException ( "Expected a string but was " + peek () + locationString () );
837+ throw unexpectedTokenError ( " a string" );
837838 }
838839 peeked = PEEKED_NONE ;
839840 pathIndices [stackSize - 1 ]++;
@@ -861,7 +862,7 @@ public boolean nextBoolean() throws IOException {
861862 pathIndices [stackSize - 1 ]++;
862863 return false ;
863864 }
864- throw new IllegalStateException ( "Expected a boolean but was " + peek () + locationString () );
865+ throw unexpectedTokenError ( " a boolean" );
865866 }
866867
867868 /**
@@ -880,7 +881,7 @@ public void nextNull() throws IOException {
880881 peeked = PEEKED_NONE ;
881882 pathIndices [stackSize - 1 ]++;
882883 } else {
883- throw new IllegalStateException ( "Expected null but was " + peek () + locationString () );
884+ throw unexpectedTokenError ( " null" );
884885 }
885886 }
886887
@@ -915,14 +916,13 @@ public double nextDouble() throws IOException {
915916 } else if (p == PEEKED_UNQUOTED ) {
916917 peekedString = nextUnquotedValue ();
917918 } else if (p != PEEKED_BUFFERED ) {
918- throw new IllegalStateException ( "Expected a double but was " + peek () + locationString () );
919+ throw unexpectedTokenError ( " a double" );
919920 }
920921
921922 peeked = PEEKED_BUFFERED ;
922923 double result = Double .parseDouble (peekedString ); // don't catch this NumberFormatException.
923924 if (!lenient && (Double .isNaN (result ) || Double .isInfinite (result ))) {
924- throw new MalformedJsonException (
925- "JSON forbids NaN and infinities: " + result + locationString ());
925+ throw syntaxError ("JSON forbids NaN and infinities: " + result );
926926 }
927927 peekedString = null ;
928928 peeked = PEEKED_NONE ;
@@ -970,7 +970,7 @@ public long nextLong() throws IOException {
970970 // Fall back to parse as a double below.
971971 }
972972 } else {
973- throw new IllegalStateException ( "Expected a long but was " + peek () + locationString () );
973+ throw unexpectedTokenError ( " a long" );
974974 }
975975
976976 peeked = PEEKED_BUFFERED ;
@@ -1208,7 +1208,7 @@ public int nextInt() throws IOException {
12081208 // Fall back to parse as a double below.
12091209 }
12101210 } else {
1211- throw new IllegalStateException ( "Expected an int but was " + peek () + locationString () );
1211+ throw unexpectedTokenError ( " an int" );
12121212 }
12131213
12141214 peeked = PEEKED_BUFFERED ;
@@ -1584,10 +1584,10 @@ public String getPath() {
15841584 /**
15851585 * Unescapes the character identified by the character or characters that
15861586 * immediately follow a backslash. The backslash '\' should have already
1587- * been read. This supports both unicode escapes "u000A" and two-character
1587+ * been read. This supports both Unicode escapes "u000A" and two-character
15881588 * escapes "\n".
15891589 *
1590- * @throws MalformedJsonException if any unicode escape sequences are
1590+ * @throws MalformedJsonException if any Unicode escape sequences are
15911591 * malformed.
15921592 */
15931593 @ SuppressWarnings ("fallthrough" )
@@ -1614,7 +1614,7 @@ private char readEscapeCharacter() throws IOException {
16141614 } else if (c >= 'A' && c <= 'F' ) {
16151615 result += (c - 'A' + 10 );
16161616 } else {
1617- throw new MalformedJsonException ( " \\ u" + new String (buffer , pos , 4 ));
1617+ throw syntaxError ( "Malformed Unicode escape \\ u" + new String (buffer , pos , 4 ));
16181618 }
16191619 }
16201620 pos += 4 ;
@@ -1656,7 +1656,16 @@ private char readEscapeCharacter() throws IOException {
16561656 * with this reader's content.
16571657 */
16581658 private IOException syntaxError (String message ) throws IOException {
1659- throw new MalformedJsonException (message + locationString ());
1659+ throw new MalformedJsonException (message + locationString ()
1660+ + "\n See " + TroubleshootingGuide .createUrl ("malformed-json" ));
1661+ }
1662+
1663+ private IllegalStateException unexpectedTokenError (String expected ) throws IOException {
1664+ JsonToken peeked = peek ();
1665+ String troubleshootingId = peeked == JsonToken .NULL
1666+ ? "adapter-not-null-safe" : "unexpected-json-structure" ;
1667+ return new IllegalStateException ("Expected " + expected + " but was " + peek () + locationString ()
1668+ + "\n See " + TroubleshootingGuide .createUrl (troubleshootingId ));
16601669 }
16611670
16621671 /**
@@ -1699,8 +1708,7 @@ private void consumeNonExecutePrefix() throws IOException {
16991708 } else if (p == PEEKED_UNQUOTED_NAME ) {
17001709 reader .peeked = PEEKED_UNQUOTED ;
17011710 } else {
1702- throw new IllegalStateException (
1703- "Expected a name but was " + reader .peek () + reader .locationString ());
1711+ throw reader .unexpectedTokenError ("a name" );
17041712 }
17051713 }
17061714 };
0 commit comments