Skip to content

Commit abfd201

Browse files
authored
Second attempt at solving #1173 (#1223)
1 parent f1d5ff0 commit abfd201

File tree

8 files changed

+64
-9
lines changed

8 files changed

+64
-9
lines changed

release-notes/VERSION-2.x

+3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ a pure JSON library.
3030
(contributed by @pjfanning)
3131
#1169: `ArrayIndexOutOfBoundsException` for specific invalid content,
3232
with Reader-based parser
33+
#1173: `JsonLocation` consistently off by one character for many
34+
invalid JSON parsing cases
35+
(reported by Paul B)
3336
#1179: Allow configuring `DefaultPrettyPrinter` separators for empty
3437
Arrays and Objects
3538
(contributed by Guillaume L)

src/main/java/com/fasterxml/jackson/core/base/ParserBase.java

+7-6
Original file line numberDiff line numberDiff line change
@@ -1373,16 +1373,17 @@ protected char _handleUnrecognizedCharacterEscape(char ch) throws JsonProcessing
13731373
if (ch == '\'' && isEnabled(Feature.ALLOW_SINGLE_QUOTES)) {
13741374
return ch;
13751375
}
1376-
_reportError("Unrecognized character escape "+_getCharDesc(ch));
1377-
return ch;
1376+
throw _constructReadException("Unrecognized character escape "+_getCharDesc(ch),
1377+
_currentLocationMinusOne());
13781378
}
13791379

13801380
protected void _reportMismatchedEndMarker(int actCh, char expCh) throws JsonParseException {
1381-
JsonReadContext ctxt = getParsingContext();
1382-
_reportError(String.format(
1381+
final JsonReadContext ctxt = getParsingContext();
1382+
final String msg = String.format(
13831383
"Unexpected close marker '%s': expected '%c' (for %s starting at %s)",
13841384
(char) actCh, expCh, ctxt.typeDesc(),
1385-
ctxt.startLocation(_contentReference())));
1385+
ctxt.startLocation(_contentReference()));
1386+
throw _constructReadException(msg, _currentLocationMinusOne());
13861387
}
13871388

13881389
/**
@@ -1402,7 +1403,7 @@ protected void _throwUnquotedSpace(int i, String ctxtDesc) throws JsonParseExcep
14021403
if (!isEnabled(Feature.ALLOW_UNQUOTED_CONTROL_CHARS) || i > INT_SPACE) {
14031404
char c = (char) i;
14041405
String msg = "Illegal unquoted character ("+_getCharDesc(c)+"): has to be escaped using backslash to be included in "+ctxtDesc;
1405-
_reportError(msg);
1406+
throw _constructReadException(msg, _currentLocationMinusOne());
14061407
}
14071408
}
14081409

src/main/java/com/fasterxml/jackson/core/base/ParserMinimalBase.java

+19-2
Original file line numberDiff line numberDiff line change
@@ -682,7 +682,7 @@ protected void _reportUnexpectedChar(int ch, String comment) throws JsonParseExc
682682
if (comment != null) {
683683
msg += ": "+comment;
684684
}
685-
throw _constructReadException(msg, currentLocation());
685+
throw _constructReadException(msg, _currentLocationMinusOne());
686686
}
687687

688688
/**
@@ -698,7 +698,7 @@ protected <T> T _reportUnexpectedNumberChar(int ch, String comment) throws JsonP
698698
if (comment != null) {
699699
msg += ": "+comment;
700700
}
701-
throw _constructReadException(msg, currentLocation());
701+
throw _constructReadException(msg, _currentLocationMinusOne());
702702
}
703703

704704
@Deprecated // @since 2.14
@@ -722,6 +722,23 @@ protected final JsonParseException _constructError(String msg, Throwable t) {
722722
return _constructReadException(msg, t);
723723
}
724724

725+
/**
726+
* Factory method used to provide location for cases where we must read
727+
* and consume a single "wrong" character (to possibly allow error recovery),
728+
* but need to report accurate location for that character: if so, the
729+
* current location is past location we want, and location we want will be
730+
* "one location earlier".
731+
*<p>
732+
* Default implementation simply returns {@link #currentLocation()}
733+
*
734+
* @since 2.17
735+
*
736+
* @return Same as {@link #currentLocation()} except offset by -1
737+
*/
738+
protected JsonLocation _currentLocationMinusOne() {
739+
return currentLocation();
740+
}
741+
725742
protected final static String _getCharDesc(int ch)
726743
{
727744
char c = (char) ch;

src/main/java/com/fasterxml/jackson/core/json/ReaderBasedJsonParser.java

+9
Original file line numberDiff line numberDiff line change
@@ -2979,6 +2979,15 @@ public JsonLocation currentLocation() {
29792979
_currInputRow, col);
29802980
}
29812981

2982+
@Override // @since 2.17
2983+
protected JsonLocation _currentLocationMinusOne() {
2984+
final int prevInputPtr = _inputPtr - 1;
2985+
final int col = prevInputPtr - _currInputRowStart + 1; // 1-based
2986+
return new JsonLocation(_contentReference(),
2987+
-1L, _currInputProcessed + prevInputPtr,
2988+
_currInputRow, col);
2989+
}
2990+
29822991
@Override
29832992
public JsonLocation currentTokenLocation()
29842993
{

src/main/java/com/fasterxml/jackson/core/json/UTF8DataInputJsonParser.java

+6
Original file line numberDiff line numberDiff line change
@@ -2975,6 +2975,12 @@ public JsonLocation currentLocation() {
29752975
_currInputRow, col);
29762976
}
29772977

2978+
// Since we only know row, may as well return currentLocation()
2979+
@Override // @since 2.17
2980+
protected JsonLocation _currentLocationMinusOne() {
2981+
return currentLocation();
2982+
}
2983+
29782984
@Override
29792985
public JsonLocation currentTokenLocation() {
29802986
// 03-Jan-2020, tatu: Should probably track this, similar to how

src/main/java/com/fasterxml/jackson/core/json/UTF8StreamJsonParser.java

+9
Original file line numberDiff line numberDiff line change
@@ -3873,6 +3873,15 @@ public JsonLocation currentLocation()
38733873
_currInputRow, col);
38743874
}
38753875

3876+
@Override // @since 2.17
3877+
protected JsonLocation _currentLocationMinusOne() {
3878+
final int prevInputPtr = _inputPtr - 1;
3879+
final int col = prevInputPtr - _currInputRowStart + 1; // 1-based
3880+
return new JsonLocation(_contentReference(),
3881+
_currInputProcessed + prevInputPtr, -1L, // bytes, chars
3882+
_currInputRow, col);
3883+
}
3884+
38763885
@Override
38773886
public JsonLocation currentTokenLocation()
38783887
{

src/main/java/com/fasterxml/jackson/core/json/async/NonBlockingJsonParserBase.java

+10
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,16 @@ public JsonLocation currentLocation()
355355
row, col);
356356
}
357357

358+
@Override // @since 2.17
359+
protected JsonLocation _currentLocationMinusOne() {
360+
final int prevInputPtr = _inputPtr - 1;
361+
int row = Math.max(_currInputRow, _currInputRowAlt);
362+
final int col = prevInputPtr - _currInputRowStart + 1; // 1-based
363+
return new JsonLocation(_contentReference(),
364+
_currInputProcessed + (prevInputPtr - _currBufferStart), -1L, // bytes, chars
365+
row, col);
366+
}
367+
358368
@Override
359369
public JsonLocation currentTokenLocation()
360370
{

src/test/java/com/fasterxml/jackson/failing/LocationOfError1173Test.java renamed to src/test/java/com/fasterxml/jackson/core/read/loc/LocationOfError1173Test.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.fasterxml.jackson.failing;
1+
package com.fasterxml.jackson.core.read.loc;
22

33
import java.io.*;
44
import java.nio.charset.StandardCharsets;

0 commit comments

Comments
 (0)