Make default adapters stricter; improve exception messages (#2000)
* Make default adapters stricter; improve exception messages * Reduce scope of synchronized blocks * Improve JsonReader.getPath / getPreviousPath Javadoc
This commit is contained in:
parent
b3188c1132
commit
b4dab86b10
@ -71,11 +71,11 @@ public enum ToNumberPolicy implements ToNumberStrategy {
|
|||||||
try {
|
try {
|
||||||
Double d = Double.valueOf(value);
|
Double d = Double.valueOf(value);
|
||||||
if ((d.isInfinite() || d.isNaN()) && !in.isLenient()) {
|
if ((d.isInfinite() || d.isNaN()) && !in.isLenient()) {
|
||||||
throw new MalformedJsonException("JSON forbids NaN and infinities: " + d + "; at path " + in.getPath());
|
throw new MalformedJsonException("JSON forbids NaN and infinities: " + d + "; at path " + in.getPreviousPath());
|
||||||
}
|
}
|
||||||
return d;
|
return d;
|
||||||
} catch (NumberFormatException doubleE) {
|
} catch (NumberFormatException doubleE) {
|
||||||
throw new JsonParseException("Cannot parse " + value + "; at path " + in.getPath(), doubleE);
|
throw new JsonParseException("Cannot parse " + value + "; at path " + in.getPreviousPath(), doubleE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,7 +91,7 @@ public enum ToNumberPolicy implements ToNumberStrategy {
|
|||||||
try {
|
try {
|
||||||
return new BigDecimal(value);
|
return new BigDecimal(value);
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
throw new JsonParseException("Cannot parse " + value + "; at path " + in.getPath(), e);
|
throw new JsonParseException("Cannot parse " + value + "; at path " + in.getPreviousPath(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,30 +72,36 @@ public final class DateTypeAdapter extends TypeAdapter<Date> {
|
|||||||
in.nextNull();
|
in.nextNull();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return deserializeToDate(in.nextString());
|
return deserializeToDate(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized Date deserializeToDate(String json) {
|
private Date deserializeToDate(JsonReader in) throws IOException {
|
||||||
for (DateFormat dateFormat : dateFormats) {
|
String s = in.nextString();
|
||||||
try {
|
synchronized (dateFormats) {
|
||||||
return dateFormat.parse(json);
|
for (DateFormat dateFormat : dateFormats) {
|
||||||
} catch (ParseException ignored) {}
|
try {
|
||||||
|
return dateFormat.parse(s);
|
||||||
|
} catch (ParseException ignored) {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return ISO8601Utils.parse(json, new ParsePosition(0));
|
return ISO8601Utils.parse(s, new ParsePosition(0));
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
throw new JsonSyntaxException(json, e);
|
throw new JsonSyntaxException("Failed parsing '" + s + "' as Date; at path " + in.getPreviousPath(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public synchronized void write(JsonWriter out, Date value) throws IOException {
|
@Override public void write(JsonWriter out, Date value) throws IOException {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
out.nullValue();
|
out.nullValue();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String dateFormatAsString = dateFormats.get(0).format(value);
|
|
||||||
|
DateFormat dateFormat = dateFormats.get(0);
|
||||||
|
String dateFormatAsString;
|
||||||
|
synchronized (dateFormats) {
|
||||||
|
dateFormatAsString = dateFormat.format(value);
|
||||||
|
}
|
||||||
out.value(dateFormatAsString);
|
out.value(dateFormatAsString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -130,10 +130,13 @@ public final class DefaultDateTypeAdapter<T extends Date> extends TypeAdapter<T>
|
|||||||
out.nullValue();
|
out.nullValue();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
synchronized(dateFormats) {
|
|
||||||
String dateFormatAsString = dateFormats.get(0).format(value);
|
DateFormat dateFormat = dateFormats.get(0);
|
||||||
out.value(dateFormatAsString);
|
String dateFormatAsString;
|
||||||
|
synchronized (dateFormats) {
|
||||||
|
dateFormatAsString = dateFormat.format(value);
|
||||||
}
|
}
|
||||||
|
out.value(dateFormatAsString);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -142,11 +145,12 @@ public final class DefaultDateTypeAdapter<T extends Date> extends TypeAdapter<T>
|
|||||||
in.nextNull();
|
in.nextNull();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Date date = deserializeToDate(in.nextString());
|
Date date = deserializeToDate(in);
|
||||||
return dateType.deserialize(date);
|
return dateType.deserialize(date);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Date deserializeToDate(String s) {
|
private Date deserializeToDate(JsonReader in) throws IOException {
|
||||||
|
String s = in.nextString();
|
||||||
synchronized (dateFormats) {
|
synchronized (dateFormats) {
|
||||||
for (DateFormat dateFormat : dateFormats) {
|
for (DateFormat dateFormat : dateFormats) {
|
||||||
try {
|
try {
|
||||||
@ -158,7 +162,7 @@ public final class DefaultDateTypeAdapter<T extends Date> extends TypeAdapter<T>
|
|||||||
try {
|
try {
|
||||||
return ISO8601Utils.parse(s, new ParsePosition(0));
|
return ISO8601Utils.parse(s, new ParsePosition(0));
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
throw new JsonSyntaxException(s, e);
|
throw new JsonSyntaxException("Failed parsing '" + s + "' as Date; at path " + in.getPreviousPath(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,12 +304,19 @@ public final class JsonTreeReader extends JsonReader {
|
|||||||
stack[stackSize++] = newTop;
|
stack[stackSize++] = newTop;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public String getPath() {
|
private String getPath(boolean usePreviousPath) {
|
||||||
StringBuilder result = new StringBuilder().append('$');
|
StringBuilder result = new StringBuilder().append('$');
|
||||||
for (int i = 0; i < stackSize; i++) {
|
for (int i = 0; i < stackSize; i++) {
|
||||||
if (stack[i] instanceof JsonArray) {
|
if (stack[i] instanceof JsonArray) {
|
||||||
if (++i < stackSize && stack[i] instanceof Iterator) {
|
if (++i < stackSize && stack[i] instanceof Iterator) {
|
||||||
result.append('[').append(pathIndices[i]).append(']');
|
int pathIndex = pathIndices[i];
|
||||||
|
// If index is last path element it points to next array element; have to decrement
|
||||||
|
// `- 1` covers case where iterator for next element is on stack
|
||||||
|
// `- 2` covers case where peek() already pushed next element onto stack
|
||||||
|
if (usePreviousPath && pathIndex > 0 && (i == stackSize - 1 || i == stackSize - 2)) {
|
||||||
|
pathIndex--;
|
||||||
|
}
|
||||||
|
result.append('[').append(pathIndex).append(']');
|
||||||
}
|
}
|
||||||
} else if (stack[i] instanceof JsonObject) {
|
} else if (stack[i] instanceof JsonObject) {
|
||||||
if (++i < stackSize && stack[i] instanceof Iterator) {
|
if (++i < stackSize && stack[i] instanceof Iterator) {
|
||||||
@ -323,6 +330,14 @@ public final class JsonTreeReader extends JsonReader {
|
|||||||
return result.toString();
|
return result.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override public String getPreviousPath() {
|
||||||
|
return getPath(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public String getPath() {
|
||||||
|
return getPath(false);
|
||||||
|
}
|
||||||
|
|
||||||
private String locationString() {
|
private String locationString() {
|
||||||
return " at path " + getPath();
|
return " at path " + getPath();
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ public final class NumberTypeAdapter extends TypeAdapter<Number> {
|
|||||||
case STRING:
|
case STRING:
|
||||||
return toNumberStrategy.readNumber(in);
|
return toNumberStrategy.readNumber(in);
|
||||||
default:
|
default:
|
||||||
throw new JsonSyntaxException("Expecting number, got: " + jsonToken);
|
throw new JsonSyntaxException("Expecting number, got: " + jsonToken + "; at path " + in.getPath());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,22 +92,21 @@ public final class TypeAdapters {
|
|||||||
boolean set;
|
boolean set;
|
||||||
switch (tokenType) {
|
switch (tokenType) {
|
||||||
case NUMBER:
|
case NUMBER:
|
||||||
set = in.nextInt() != 0;
|
case STRING:
|
||||||
|
int intValue = in.nextInt();
|
||||||
|
if (intValue == 0) {
|
||||||
|
set = false;
|
||||||
|
} else if (intValue == 1) {
|
||||||
|
set = true;
|
||||||
|
} else {
|
||||||
|
throw new JsonSyntaxException("Invalid bitset value " + intValue + ", expected 0 or 1; at path " + in.getPreviousPath());
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case BOOLEAN:
|
case BOOLEAN:
|
||||||
set = in.nextBoolean();
|
set = in.nextBoolean();
|
||||||
break;
|
break;
|
||||||
case STRING:
|
|
||||||
String stringValue = in.nextString();
|
|
||||||
try {
|
|
||||||
set = Integer.parseInt(stringValue) != 0;
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
throw new JsonSyntaxException(
|
|
||||||
"Error: Expecting: bitset number value (1, 0), Found: " + stringValue);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
throw new JsonSyntaxException("Invalid bitset value type: " + tokenType);
|
throw new JsonSyntaxException("Invalid bitset value type: " + tokenType + "; at path " + in.getPath());
|
||||||
}
|
}
|
||||||
if (set) {
|
if (set) {
|
||||||
bitset.set(i);
|
bitset.set(i);
|
||||||
@ -178,12 +177,18 @@ public final class TypeAdapters {
|
|||||||
in.nextNull();
|
in.nextNull();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int intValue;
|
||||||
try {
|
try {
|
||||||
int intValue = in.nextInt();
|
intValue = in.nextInt();
|
||||||
return (byte) intValue;
|
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
throw new JsonSyntaxException(e);
|
throw new JsonSyntaxException(e);
|
||||||
}
|
}
|
||||||
|
// Allow up to 255 to support unsigned values
|
||||||
|
if (intValue > 255 || intValue < Byte.MIN_VALUE) {
|
||||||
|
throw new JsonSyntaxException("Lossy conversion from " + intValue + " to byte; at path " + in.getPreviousPath());
|
||||||
|
}
|
||||||
|
return (byte) intValue;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void write(JsonWriter out, Number value) throws IOException {
|
public void write(JsonWriter out, Number value) throws IOException {
|
||||||
@ -201,11 +206,18 @@ public final class TypeAdapters {
|
|||||||
in.nextNull();
|
in.nextNull();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int intValue;
|
||||||
try {
|
try {
|
||||||
return (short) in.nextInt();
|
intValue = in.nextInt();
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
throw new JsonSyntaxException(e);
|
throw new JsonSyntaxException(e);
|
||||||
}
|
}
|
||||||
|
// Allow up to 65535 to support unsigned values
|
||||||
|
if (intValue > 65535 || intValue < Short.MIN_VALUE) {
|
||||||
|
throw new JsonSyntaxException("Lossy conversion from " + intValue + " to short; at path " + in.getPreviousPath());
|
||||||
|
}
|
||||||
|
return (short) intValue;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void write(JsonWriter out, Number value) throws IOException {
|
public void write(JsonWriter out, Number value) throws IOException {
|
||||||
@ -352,7 +364,7 @@ public final class TypeAdapters {
|
|||||||
}
|
}
|
||||||
String str = in.nextString();
|
String str = in.nextString();
|
||||||
if (str.length() != 1) {
|
if (str.length() != 1) {
|
||||||
throw new JsonSyntaxException("Expecting character, got: " + str);
|
throw new JsonSyntaxException("Expecting character, got: " + str + "; at " + in.getPreviousPath());
|
||||||
}
|
}
|
||||||
return str.charAt(0);
|
return str.charAt(0);
|
||||||
}
|
}
|
||||||
@ -391,10 +403,11 @@ public final class TypeAdapters {
|
|||||||
in.nextNull();
|
in.nextNull();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
String s = in.nextString();
|
||||||
try {
|
try {
|
||||||
return new BigDecimal(in.nextString());
|
return new BigDecimal(s);
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
throw new JsonSyntaxException(e);
|
throw new JsonSyntaxException("Failed parsing '" + s + "' as BigDecimal; at path " + in.getPreviousPath(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -409,10 +422,11 @@ public final class TypeAdapters {
|
|||||||
in.nextNull();
|
in.nextNull();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
String s = in.nextString();
|
||||||
try {
|
try {
|
||||||
return new BigInteger(in.nextString());
|
return new BigInteger(s);
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
throw new JsonSyntaxException(e);
|
throw new JsonSyntaxException("Failed parsing '" + s + "' as BigInteger; at path " + in.getPreviousPath(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -525,7 +539,12 @@ public final class TypeAdapters {
|
|||||||
in.nextNull();
|
in.nextNull();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return java.util.UUID.fromString(in.nextString());
|
String s = in.nextString();
|
||||||
|
try {
|
||||||
|
return java.util.UUID.fromString(s);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new JsonSyntaxException("Failed parsing '" + s + "' as UUID; at path " + in.getPreviousPath(), e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void write(JsonWriter out, UUID value) throws IOException {
|
public void write(JsonWriter out, UUID value) throws IOException {
|
||||||
@ -538,7 +557,12 @@ public final class TypeAdapters {
|
|||||||
public static final TypeAdapter<Currency> CURRENCY = new TypeAdapter<Currency>() {
|
public static final TypeAdapter<Currency> CURRENCY = new TypeAdapter<Currency>() {
|
||||||
@Override
|
@Override
|
||||||
public Currency read(JsonReader in) throws IOException {
|
public Currency read(JsonReader in) throws IOException {
|
||||||
return Currency.getInstance(in.nextString());
|
String s = in.nextString();
|
||||||
|
try {
|
||||||
|
return Currency.getInstance(s);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new JsonSyntaxException("Failed parsing '" + s + "' as Currency; at path " + in.getPreviousPath(), e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void write(JsonWriter out, Currency value) throws IOException {
|
public void write(JsonWriter out, Currency value) throws IOException {
|
||||||
@ -866,7 +890,7 @@ public final class TypeAdapters {
|
|||||||
T1 result = typeAdapter.read(in);
|
T1 result = typeAdapter.read(in);
|
||||||
if (result != null && !requestedType.isInstance(result)) {
|
if (result != null && !requestedType.isInstance(result)) {
|
||||||
throw new JsonSyntaxException("Expected a " + requestedType.getName()
|
throw new JsonSyntaxException("Expected a " + requestedType.getName()
|
||||||
+ " but was " + result.getClass().getName());
|
+ " but was " + result.getClass().getName() + "; at path " + in.getPreviousPath());
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ import java.io.IOException;
|
|||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapter for java.sql.Date. Although this class appears stateless, it is not.
|
* Adapter for java.sql.Date. Although this class appears stateless, it is not.
|
||||||
@ -50,21 +51,33 @@ final class SqlDateTypeAdapter extends TypeAdapter<java.sql.Date> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized java.sql.Date read(JsonReader in) throws IOException {
|
public java.sql.Date read(JsonReader in) throws IOException {
|
||||||
if (in.peek() == JsonToken.NULL) {
|
if (in.peek() == JsonToken.NULL) {
|
||||||
in.nextNull();
|
in.nextNull();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
String s = in.nextString();
|
||||||
try {
|
try {
|
||||||
final long utilDate = format.parse(in.nextString()).getTime();
|
Date utilDate;
|
||||||
return new java.sql.Date(utilDate);
|
synchronized (this) {
|
||||||
|
utilDate = format.parse(s);
|
||||||
|
}
|
||||||
|
return new java.sql.Date(utilDate.getTime());
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
throw new JsonSyntaxException(e);
|
throw new JsonSyntaxException("Failed parsing '" + s + "' as SQL Date; at path " + in.getPreviousPath(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void write(JsonWriter out, java.sql.Date value) throws IOException {
|
public void write(JsonWriter out, java.sql.Date value) throws IOException {
|
||||||
out.value(value == null ? null : format.format(value));
|
if (value == null) {
|
||||||
|
out.nullValue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String dateString;
|
||||||
|
synchronized (this) {
|
||||||
|
dateString = format.format(value);
|
||||||
|
}
|
||||||
|
out.value(dateString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,20 +50,31 @@ final class SqlTimeTypeAdapter extends TypeAdapter<Time> {
|
|||||||
private SqlTimeTypeAdapter() {
|
private SqlTimeTypeAdapter() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public synchronized Time read(JsonReader in) throws IOException {
|
@Override public Time read(JsonReader in) throws IOException {
|
||||||
if (in.peek() == JsonToken.NULL) {
|
if (in.peek() == JsonToken.NULL) {
|
||||||
in.nextNull();
|
in.nextNull();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
String s = in.nextString();
|
||||||
try {
|
try {
|
||||||
Date date = format.parse(in.nextString());
|
synchronized (this) {
|
||||||
return new Time(date.getTime());
|
Date date = format.parse(s);
|
||||||
|
return new Time(date.getTime());
|
||||||
|
}
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
throw new JsonSyntaxException(e);
|
throw new JsonSyntaxException("Failed parsing '" + s + "' as SQL Time; at path " + in.getPreviousPath(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public synchronized void write(JsonWriter out, Time value) throws IOException {
|
@Override public void write(JsonWriter out, Time value) throws IOException {
|
||||||
out.value(value == null ? null : format.format(value));
|
if (value == null) {
|
||||||
|
out.nullValue();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String timeString;
|
||||||
|
synchronized (this) {
|
||||||
|
timeString = format.format(value);
|
||||||
|
}
|
||||||
|
out.value(timeString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1085,7 +1085,7 @@ public class JsonReader implements Closeable {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String result = (null == builder) ? new String(buffer, pos, i) : builder.append(buffer, pos, i).toString();
|
String result = (null == builder) ? new String(buffer, pos, i) : builder.append(buffer, pos, i).toString();
|
||||||
pos += i;
|
pos += i;
|
||||||
return result;
|
return result;
|
||||||
@ -1454,19 +1454,19 @@ public class JsonReader implements Closeable {
|
|||||||
return " at line " + line + " column " + column + " path " + getPath();
|
return " at line " + line + " column " + column + " path " + getPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private String getPath(boolean usePreviousPath) {
|
||||||
* Returns a <a href="http://goessner.net/articles/JsonPath/">JsonPath</a> to
|
|
||||||
* the current location in the JSON value.
|
|
||||||
*/
|
|
||||||
public String getPath() {
|
|
||||||
StringBuilder result = new StringBuilder().append('$');
|
StringBuilder result = new StringBuilder().append('$');
|
||||||
for (int i = 0, size = stackSize; i < size; i++) {
|
for (int i = 0; i < stackSize; i++) {
|
||||||
switch (stack[i]) {
|
switch (stack[i]) {
|
||||||
case JsonScope.EMPTY_ARRAY:
|
case JsonScope.EMPTY_ARRAY:
|
||||||
case JsonScope.NONEMPTY_ARRAY:
|
case JsonScope.NONEMPTY_ARRAY:
|
||||||
result.append('[').append(pathIndices[i]).append(']');
|
int pathIndex = pathIndices[i];
|
||||||
|
// If index is last path element it points to next array element; have to decrement
|
||||||
|
if (usePreviousPath && pathIndex > 0 && i == stackSize - 1) {
|
||||||
|
pathIndex--;
|
||||||
|
}
|
||||||
|
result.append('[').append(pathIndex).append(']');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case JsonScope.EMPTY_OBJECT:
|
case JsonScope.EMPTY_OBJECT:
|
||||||
case JsonScope.DANGLING_NAME:
|
case JsonScope.DANGLING_NAME:
|
||||||
case JsonScope.NONEMPTY_OBJECT:
|
case JsonScope.NONEMPTY_OBJECT:
|
||||||
@ -1475,7 +1475,6 @@ public class JsonReader implements Closeable {
|
|||||||
result.append(pathNames[i]);
|
result.append(pathNames[i]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case JsonScope.NONEMPTY_DOCUMENT:
|
case JsonScope.NONEMPTY_DOCUMENT:
|
||||||
case JsonScope.EMPTY_DOCUMENT:
|
case JsonScope.EMPTY_DOCUMENT:
|
||||||
case JsonScope.CLOSED:
|
case JsonScope.CLOSED:
|
||||||
@ -1485,6 +1484,41 @@ public class JsonReader implements Closeable {
|
|||||||
return result.toString();
|
return result.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a <a href="https://goessner.net/articles/JsonPath/">JsonPath</a>
|
||||||
|
* in <i>dot-notation</i> to the previous (or current) location in the JSON document:
|
||||||
|
* <ul>
|
||||||
|
* <li>For JSON arrays the path points to the index of the previous element.<br>
|
||||||
|
* If no element has been consumed yet it uses the index 0 (even if there are no elements).</li>
|
||||||
|
* <li>For JSON objects the path points to the last property, or to the current
|
||||||
|
* property if its value has not been consumed yet.</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <p>This method can be useful to add additional context to exception messages
|
||||||
|
* <i>after</i> a value has been consumed.
|
||||||
|
*/
|
||||||
|
public String getPreviousPath() {
|
||||||
|
return getPath(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a <a href="https://goessner.net/articles/JsonPath/">JsonPath</a>
|
||||||
|
* in <i>dot-notation</i> to the next (or current) location in the JSON document:
|
||||||
|
* <ul>
|
||||||
|
* <li>For JSON arrays the path points to the index of the next element (even
|
||||||
|
* if there are no further elements).</li>
|
||||||
|
* <li>For JSON objects the path points to the last property, or to the current
|
||||||
|
* property if its value has not been consumed yet.</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <p>This method can be useful to add additional context to exception messages
|
||||||
|
* <i>before</i> a value is consumed, for example when the {@linkplain #peek() peeked}
|
||||||
|
* token is unexpected.
|
||||||
|
*/
|
||||||
|
public String getPath() {
|
||||||
|
return getPath(false);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unescapes the character identified by the character or characters that
|
* Unescapes the character identified by the character or characters that
|
||||||
* immediately follow a backslash. The backslash '\' should have already
|
* immediately follow a backslash. The backslash '\' should have already
|
||||||
@ -1546,11 +1580,11 @@ public class JsonReader implements Closeable {
|
|||||||
case '\'':
|
case '\'':
|
||||||
case '"':
|
case '"':
|
||||||
case '\\':
|
case '\\':
|
||||||
case '/':
|
case '/':
|
||||||
return escaped;
|
return escaped;
|
||||||
default:
|
default:
|
||||||
// throw error when none of the above cases are matched
|
// throw error when none of the above cases are matched
|
||||||
throw syntaxError("Invalid escape sequence");
|
throw syntaxError("Invalid escape sequence");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,6 +332,20 @@ public class DefaultTypeAdaptersTest extends TestCase {
|
|||||||
|
|
||||||
json = "[true,false,true,true,true,true,false,false,true,false,false]";
|
json = "[true,false,true,true,true,true,false,false,true,false,false]";
|
||||||
assertEquals(expected, gson.fromJson(json, BitSet.class));
|
assertEquals(expected, gson.fromJson(json, BitSet.class));
|
||||||
|
|
||||||
|
try {
|
||||||
|
gson.fromJson("[1, []]", BitSet.class);
|
||||||
|
fail();
|
||||||
|
} catch (JsonSyntaxException e) {
|
||||||
|
assertEquals("Invalid bitset value type: BEGIN_ARRAY; at path $[1]", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
gson.fromJson("[1, 2]", BitSet.class);
|
||||||
|
fail();
|
||||||
|
} catch (JsonSyntaxException e) {
|
||||||
|
assertEquals("Invalid bitset value 2, expected 0 or 1; at path $[1]", e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testDefaultDateSerialization() {
|
public void testDefaultDateSerialization() {
|
||||||
@ -567,7 +581,7 @@ public class DefaultTypeAdaptersTest extends TestCase {
|
|||||||
gson.fromJson("\"abc\"", JsonObject.class);
|
gson.fromJson("\"abc\"", JsonObject.class);
|
||||||
fail();
|
fail();
|
||||||
} catch (JsonSyntaxException expected) {
|
} catch (JsonSyntaxException expected) {
|
||||||
assertEquals("Expected a com.google.gson.JsonObject but was com.google.gson.JsonPrimitive",
|
assertEquals("Expected a com.google.gson.JsonObject but was com.google.gson.JsonPrimitive; at path $",
|
||||||
expected.getMessage());
|
expected.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package com.google.gson.functional;
|
package com.google.gson.functional;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import com.google.gson.JsonPrimitive;
|
import com.google.gson.JsonPrimitive;
|
||||||
@ -63,16 +65,75 @@ public class PrimitiveTest extends TestCase {
|
|||||||
assertEquals("1", gson.toJson(1, Byte.class));
|
assertEquals("1", gson.toJson(1, Byte.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testByteDeserialization() {
|
||||||
|
Byte boxed = gson.fromJson("1", Byte.class);
|
||||||
|
assertEquals(1, (byte)boxed);
|
||||||
|
byte primitive = gson.fromJson("1", byte.class);
|
||||||
|
assertEquals(1, primitive);
|
||||||
|
|
||||||
|
byte[] bytes = gson.fromJson("[-128, 0, 127, 255]", byte[].class);
|
||||||
|
assertArrayEquals(new byte[] {-128, 0, 127, -1}, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testByteDeserializationLossy() {
|
||||||
|
try {
|
||||||
|
gson.fromJson("-129", byte.class);
|
||||||
|
fail();
|
||||||
|
} catch (JsonSyntaxException e) {
|
||||||
|
assertEquals("Lossy conversion from -129 to byte; at path $", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
gson.fromJson("256", byte.class);
|
||||||
|
fail();
|
||||||
|
} catch (JsonSyntaxException e) {
|
||||||
|
assertEquals("Lossy conversion from 256 to byte; at path $", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
gson.fromJson("2147483648", byte.class);
|
||||||
|
fail();
|
||||||
|
} catch (JsonSyntaxException e) {
|
||||||
|
assertEquals("java.lang.NumberFormatException: Expected an int but was 2147483648 at line 1 column 11 path $", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void testShortSerialization() {
|
public void testShortSerialization() {
|
||||||
assertEquals("1", gson.toJson(1, short.class));
|
assertEquals("1", gson.toJson(1, short.class));
|
||||||
assertEquals("1", gson.toJson(1, Short.class));
|
assertEquals("1", gson.toJson(1, Short.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testByteDeserialization() {
|
public void testShortDeserialization() {
|
||||||
Byte target = gson.fromJson("1", Byte.class);
|
Short boxed = gson.fromJson("1", Short.class);
|
||||||
assertEquals(1, (byte)target);
|
assertEquals(1, (short)boxed);
|
||||||
byte primitive = gson.fromJson("1", byte.class);
|
short primitive = gson.fromJson("1", short.class);
|
||||||
assertEquals(1, primitive);
|
assertEquals(1, primitive);
|
||||||
|
|
||||||
|
short[] shorts = gson.fromJson("[-32768, 0, 32767, 65535]", short[].class);
|
||||||
|
assertArrayEquals(new short[] {-32768, 0, 32767, -1}, shorts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testShortDeserializationLossy() {
|
||||||
|
try {
|
||||||
|
gson.fromJson("-32769", short.class);
|
||||||
|
fail();
|
||||||
|
} catch (JsonSyntaxException e) {
|
||||||
|
assertEquals("Lossy conversion from -32769 to short; at path $", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
gson.fromJson("65536", short.class);
|
||||||
|
fail();
|
||||||
|
} catch (JsonSyntaxException e) {
|
||||||
|
assertEquals("Lossy conversion from 65536 to short; at path $", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
gson.fromJson("2147483648", short.class);
|
||||||
|
fail();
|
||||||
|
} catch (JsonSyntaxException e) {
|
||||||
|
assertEquals("java.lang.NumberFormatException: Expected an int but was 2147483648 at line 1 column 11 path $", e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testPrimitiveIntegerAutoboxedInASingleElementArraySerialization() {
|
public void testPrimitiveIntegerAutoboxedInASingleElementArraySerialization() {
|
||||||
|
@ -46,110 +46,154 @@ public class JsonReaderPathTest {
|
|||||||
|
|
||||||
@Test public void path() throws IOException {
|
@Test public void path() throws IOException {
|
||||||
JsonReader reader = factory.create("{\"a\":[2,true,false,null,\"b\",{\"c\":\"d\"},[3]]}");
|
JsonReader reader = factory.create("{\"a\":[2,true,false,null,\"b\",{\"c\":\"d\"},[3]]}");
|
||||||
|
assertEquals("$", reader.getPreviousPath());
|
||||||
assertEquals("$", reader.getPath());
|
assertEquals("$", reader.getPath());
|
||||||
reader.beginObject();
|
reader.beginObject();
|
||||||
|
assertEquals("$.", reader.getPreviousPath());
|
||||||
assertEquals("$.", reader.getPath());
|
assertEquals("$.", reader.getPath());
|
||||||
reader.nextName();
|
reader.nextName();
|
||||||
|
assertEquals("$.a", reader.getPreviousPath());
|
||||||
assertEquals("$.a", reader.getPath());
|
assertEquals("$.a", reader.getPath());
|
||||||
reader.beginArray();
|
reader.beginArray();
|
||||||
|
assertEquals("$.a[0]", reader.getPreviousPath());
|
||||||
assertEquals("$.a[0]", reader.getPath());
|
assertEquals("$.a[0]", reader.getPath());
|
||||||
reader.nextInt();
|
reader.nextInt();
|
||||||
|
assertEquals("$.a[0]", reader.getPreviousPath());
|
||||||
assertEquals("$.a[1]", reader.getPath());
|
assertEquals("$.a[1]", reader.getPath());
|
||||||
reader.nextBoolean();
|
reader.nextBoolean();
|
||||||
|
assertEquals("$.a[1]", reader.getPreviousPath());
|
||||||
assertEquals("$.a[2]", reader.getPath());
|
assertEquals("$.a[2]", reader.getPath());
|
||||||
reader.nextBoolean();
|
reader.nextBoolean();
|
||||||
|
assertEquals("$.a[2]", reader.getPreviousPath());
|
||||||
assertEquals("$.a[3]", reader.getPath());
|
assertEquals("$.a[3]", reader.getPath());
|
||||||
reader.nextNull();
|
reader.nextNull();
|
||||||
|
assertEquals("$.a[3]", reader.getPreviousPath());
|
||||||
assertEquals("$.a[4]", reader.getPath());
|
assertEquals("$.a[4]", reader.getPath());
|
||||||
reader.nextString();
|
reader.nextString();
|
||||||
|
assertEquals("$.a[4]", reader.getPreviousPath());
|
||||||
assertEquals("$.a[5]", reader.getPath());
|
assertEquals("$.a[5]", reader.getPath());
|
||||||
reader.beginObject();
|
reader.beginObject();
|
||||||
|
assertEquals("$.a[5].", reader.getPreviousPath());
|
||||||
assertEquals("$.a[5].", reader.getPath());
|
assertEquals("$.a[5].", reader.getPath());
|
||||||
reader.nextName();
|
reader.nextName();
|
||||||
|
assertEquals("$.a[5].c", reader.getPreviousPath());
|
||||||
assertEquals("$.a[5].c", reader.getPath());
|
assertEquals("$.a[5].c", reader.getPath());
|
||||||
reader.nextString();
|
reader.nextString();
|
||||||
|
assertEquals("$.a[5].c", reader.getPreviousPath());
|
||||||
assertEquals("$.a[5].c", reader.getPath());
|
assertEquals("$.a[5].c", reader.getPath());
|
||||||
reader.endObject();
|
reader.endObject();
|
||||||
|
assertEquals("$.a[5]", reader.getPreviousPath());
|
||||||
assertEquals("$.a[6]", reader.getPath());
|
assertEquals("$.a[6]", reader.getPath());
|
||||||
reader.beginArray();
|
reader.beginArray();
|
||||||
|
assertEquals("$.a[6][0]", reader.getPreviousPath());
|
||||||
assertEquals("$.a[6][0]", reader.getPath());
|
assertEquals("$.a[6][0]", reader.getPath());
|
||||||
reader.nextInt();
|
reader.nextInt();
|
||||||
|
assertEquals("$.a[6][0]", reader.getPreviousPath());
|
||||||
assertEquals("$.a[6][1]", reader.getPath());
|
assertEquals("$.a[6][1]", reader.getPath());
|
||||||
reader.endArray();
|
reader.endArray();
|
||||||
|
assertEquals("$.a[6]", reader.getPreviousPath());
|
||||||
assertEquals("$.a[7]", reader.getPath());
|
assertEquals("$.a[7]", reader.getPath());
|
||||||
reader.endArray();
|
reader.endArray();
|
||||||
|
assertEquals("$.a", reader.getPreviousPath());
|
||||||
assertEquals("$.a", reader.getPath());
|
assertEquals("$.a", reader.getPath());
|
||||||
reader.endObject();
|
reader.endObject();
|
||||||
|
assertEquals("$", reader.getPreviousPath());
|
||||||
assertEquals("$", reader.getPath());
|
assertEquals("$", reader.getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test public void objectPath() throws IOException {
|
@Test public void objectPath() throws IOException {
|
||||||
JsonReader reader = factory.create("{\"a\":1,\"b\":2}");
|
JsonReader reader = factory.create("{\"a\":1,\"b\":2}");
|
||||||
|
assertEquals("$", reader.getPreviousPath());
|
||||||
assertEquals("$", reader.getPath());
|
assertEquals("$", reader.getPath());
|
||||||
|
|
||||||
reader.peek();
|
reader.peek();
|
||||||
|
assertEquals("$", reader.getPreviousPath());
|
||||||
assertEquals("$", reader.getPath());
|
assertEquals("$", reader.getPath());
|
||||||
reader.beginObject();
|
reader.beginObject();
|
||||||
|
assertEquals("$.", reader.getPreviousPath());
|
||||||
assertEquals("$.", reader.getPath());
|
assertEquals("$.", reader.getPath());
|
||||||
|
|
||||||
reader.peek();
|
reader.peek();
|
||||||
|
assertEquals("$.", reader.getPreviousPath());
|
||||||
assertEquals("$.", reader.getPath());
|
assertEquals("$.", reader.getPath());
|
||||||
reader.nextName();
|
reader.nextName();
|
||||||
|
assertEquals("$.a", reader.getPreviousPath());
|
||||||
assertEquals("$.a", reader.getPath());
|
assertEquals("$.a", reader.getPath());
|
||||||
|
|
||||||
reader.peek();
|
reader.peek();
|
||||||
|
assertEquals("$.a", reader.getPreviousPath());
|
||||||
assertEquals("$.a", reader.getPath());
|
assertEquals("$.a", reader.getPath());
|
||||||
reader.nextInt();
|
reader.nextInt();
|
||||||
|
assertEquals("$.a", reader.getPreviousPath());
|
||||||
assertEquals("$.a", reader.getPath());
|
assertEquals("$.a", reader.getPath());
|
||||||
|
|
||||||
reader.peek();
|
reader.peek();
|
||||||
|
assertEquals("$.a", reader.getPreviousPath());
|
||||||
assertEquals("$.a", reader.getPath());
|
assertEquals("$.a", reader.getPath());
|
||||||
reader.nextName();
|
reader.nextName();
|
||||||
|
assertEquals("$.b", reader.getPreviousPath());
|
||||||
assertEquals("$.b", reader.getPath());
|
assertEquals("$.b", reader.getPath());
|
||||||
|
|
||||||
reader.peek();
|
reader.peek();
|
||||||
|
assertEquals("$.b", reader.getPreviousPath());
|
||||||
assertEquals("$.b", reader.getPath());
|
assertEquals("$.b", reader.getPath());
|
||||||
reader.nextInt();
|
reader.nextInt();
|
||||||
|
assertEquals("$.b", reader.getPreviousPath());
|
||||||
assertEquals("$.b", reader.getPath());
|
assertEquals("$.b", reader.getPath());
|
||||||
|
|
||||||
reader.peek();
|
reader.peek();
|
||||||
|
assertEquals("$.b", reader.getPreviousPath());
|
||||||
assertEquals("$.b", reader.getPath());
|
assertEquals("$.b", reader.getPath());
|
||||||
reader.endObject();
|
reader.endObject();
|
||||||
|
assertEquals("$", reader.getPreviousPath());
|
||||||
assertEquals("$", reader.getPath());
|
assertEquals("$", reader.getPath());
|
||||||
|
|
||||||
reader.peek();
|
reader.peek();
|
||||||
|
assertEquals("$", reader.getPreviousPath());
|
||||||
assertEquals("$", reader.getPath());
|
assertEquals("$", reader.getPath());
|
||||||
reader.close();
|
reader.close();
|
||||||
|
assertEquals("$", reader.getPreviousPath());
|
||||||
assertEquals("$", reader.getPath());
|
assertEquals("$", reader.getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test public void arrayPath() throws IOException {
|
@Test public void arrayPath() throws IOException {
|
||||||
JsonReader reader = factory.create("[1,2]");
|
JsonReader reader = factory.create("[1,2]");
|
||||||
|
assertEquals("$", reader.getPreviousPath());
|
||||||
assertEquals("$", reader.getPath());
|
assertEquals("$", reader.getPath());
|
||||||
|
|
||||||
reader.peek();
|
reader.peek();
|
||||||
|
assertEquals("$", reader.getPreviousPath());
|
||||||
assertEquals("$", reader.getPath());
|
assertEquals("$", reader.getPath());
|
||||||
reader.beginArray();
|
reader.beginArray();
|
||||||
|
assertEquals("$[0]", reader.getPreviousPath());
|
||||||
assertEquals("$[0]", reader.getPath());
|
assertEquals("$[0]", reader.getPath());
|
||||||
|
|
||||||
reader.peek();
|
reader.peek();
|
||||||
|
assertEquals("$[0]", reader.getPreviousPath());
|
||||||
assertEquals("$[0]", reader.getPath());
|
assertEquals("$[0]", reader.getPath());
|
||||||
reader.nextInt();
|
reader.nextInt();
|
||||||
|
assertEquals("$[0]", reader.getPreviousPath());
|
||||||
assertEquals("$[1]", reader.getPath());
|
assertEquals("$[1]", reader.getPath());
|
||||||
|
|
||||||
reader.peek();
|
reader.peek();
|
||||||
|
assertEquals("$[0]", reader.getPreviousPath());
|
||||||
assertEquals("$[1]", reader.getPath());
|
assertEquals("$[1]", reader.getPath());
|
||||||
reader.nextInt();
|
reader.nextInt();
|
||||||
|
assertEquals("$[1]", reader.getPreviousPath());
|
||||||
assertEquals("$[2]", reader.getPath());
|
assertEquals("$[2]", reader.getPath());
|
||||||
|
|
||||||
reader.peek();
|
reader.peek();
|
||||||
|
assertEquals("$[1]", reader.getPreviousPath());
|
||||||
assertEquals("$[2]", reader.getPath());
|
assertEquals("$[2]", reader.getPath());
|
||||||
reader.endArray();
|
reader.endArray();
|
||||||
|
assertEquals("$", reader.getPreviousPath());
|
||||||
assertEquals("$", reader.getPath());
|
assertEquals("$", reader.getPath());
|
||||||
|
|
||||||
reader.peek();
|
reader.peek();
|
||||||
|
assertEquals("$", reader.getPreviousPath());
|
||||||
assertEquals("$", reader.getPath());
|
assertEquals("$", reader.getPath());
|
||||||
reader.close();
|
reader.close();
|
||||||
|
assertEquals("$", reader.getPreviousPath());
|
||||||
assertEquals("$", reader.getPath());
|
assertEquals("$", reader.getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,9 +204,11 @@ public class JsonReaderPathTest {
|
|||||||
reader.setLenient(true);
|
reader.setLenient(true);
|
||||||
reader.beginArray();
|
reader.beginArray();
|
||||||
reader.endArray();
|
reader.endArray();
|
||||||
|
assertEquals("$", reader.getPreviousPath());
|
||||||
assertEquals("$", reader.getPath());
|
assertEquals("$", reader.getPath());
|
||||||
reader.beginArray();
|
reader.beginArray();
|
||||||
reader.endArray();
|
reader.endArray();
|
||||||
|
assertEquals("$", reader.getPreviousPath());
|
||||||
assertEquals("$", reader.getPath());
|
assertEquals("$", reader.getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,6 +217,7 @@ public class JsonReaderPathTest {
|
|||||||
reader.beginArray();
|
reader.beginArray();
|
||||||
reader.skipValue();
|
reader.skipValue();
|
||||||
reader.skipValue();
|
reader.skipValue();
|
||||||
|
assertEquals("$[1]", reader.getPreviousPath());
|
||||||
assertEquals("$[2]", reader.getPath());
|
assertEquals("$[2]", reader.getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,17 +225,21 @@ public class JsonReaderPathTest {
|
|||||||
JsonReader reader = factory.create("{\"a\":1}");
|
JsonReader reader = factory.create("{\"a\":1}");
|
||||||
reader.beginObject();
|
reader.beginObject();
|
||||||
reader.skipValue();
|
reader.skipValue();
|
||||||
|
assertEquals("$.null", reader.getPreviousPath());
|
||||||
assertEquals("$.null", reader.getPath());
|
assertEquals("$.null", reader.getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test public void skipObjectValues() throws IOException {
|
@Test public void skipObjectValues() throws IOException {
|
||||||
JsonReader reader = factory.create("{\"a\":1,\"b\":2}");
|
JsonReader reader = factory.create("{\"a\":1,\"b\":2}");
|
||||||
reader.beginObject();
|
reader.beginObject();
|
||||||
|
assertEquals("$.", reader.getPreviousPath());
|
||||||
assertEquals("$.", reader.getPath());
|
assertEquals("$.", reader.getPath());
|
||||||
reader.nextName();
|
reader.nextName();
|
||||||
reader.skipValue();
|
reader.skipValue();
|
||||||
|
assertEquals("$.null", reader.getPreviousPath());
|
||||||
assertEquals("$.null", reader.getPath());
|
assertEquals("$.null", reader.getPath());
|
||||||
reader.nextName();
|
reader.nextName();
|
||||||
|
assertEquals("$.b", reader.getPreviousPath());
|
||||||
assertEquals("$.b", reader.getPath());
|
assertEquals("$.b", reader.getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,46 +247,63 @@ public class JsonReaderPathTest {
|
|||||||
JsonReader reader = factory.create("[[1,2,3],4]");
|
JsonReader reader = factory.create("[[1,2,3],4]");
|
||||||
reader.beginArray();
|
reader.beginArray();
|
||||||
reader.skipValue();
|
reader.skipValue();
|
||||||
|
assertEquals("$[0]", reader.getPreviousPath());
|
||||||
assertEquals("$[1]", reader.getPath());
|
assertEquals("$[1]", reader.getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test public void arrayOfObjects() throws IOException {
|
@Test public void arrayOfObjects() throws IOException {
|
||||||
JsonReader reader = factory.create("[{},{},{}]");
|
JsonReader reader = factory.create("[{},{},{}]");
|
||||||
reader.beginArray();
|
reader.beginArray();
|
||||||
|
assertEquals("$[0]", reader.getPreviousPath());
|
||||||
assertEquals("$[0]", reader.getPath());
|
assertEquals("$[0]", reader.getPath());
|
||||||
reader.beginObject();
|
reader.beginObject();
|
||||||
|
assertEquals("$[0].", reader.getPreviousPath());
|
||||||
assertEquals("$[0].", reader.getPath());
|
assertEquals("$[0].", reader.getPath());
|
||||||
reader.endObject();
|
reader.endObject();
|
||||||
|
assertEquals("$[0]", reader.getPreviousPath());
|
||||||
assertEquals("$[1]", reader.getPath());
|
assertEquals("$[1]", reader.getPath());
|
||||||
reader.beginObject();
|
reader.beginObject();
|
||||||
|
assertEquals("$[1].", reader.getPreviousPath());
|
||||||
assertEquals("$[1].", reader.getPath());
|
assertEquals("$[1].", reader.getPath());
|
||||||
reader.endObject();
|
reader.endObject();
|
||||||
|
assertEquals("$[1]", reader.getPreviousPath());
|
||||||
assertEquals("$[2]", reader.getPath());
|
assertEquals("$[2]", reader.getPath());
|
||||||
reader.beginObject();
|
reader.beginObject();
|
||||||
|
assertEquals("$[2].", reader.getPreviousPath());
|
||||||
assertEquals("$[2].", reader.getPath());
|
assertEquals("$[2].", reader.getPath());
|
||||||
reader.endObject();
|
reader.endObject();
|
||||||
|
assertEquals("$[2]", reader.getPreviousPath());
|
||||||
assertEquals("$[3]", reader.getPath());
|
assertEquals("$[3]", reader.getPath());
|
||||||
reader.endArray();
|
reader.endArray();
|
||||||
|
assertEquals("$", reader.getPreviousPath());
|
||||||
assertEquals("$", reader.getPath());
|
assertEquals("$", reader.getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test public void arrayOfArrays() throws IOException {
|
@Test public void arrayOfArrays() throws IOException {
|
||||||
JsonReader reader = factory.create("[[],[],[]]");
|
JsonReader reader = factory.create("[[],[],[]]");
|
||||||
reader.beginArray();
|
reader.beginArray();
|
||||||
|
assertEquals("$[0]", reader.getPreviousPath());
|
||||||
assertEquals("$[0]", reader.getPath());
|
assertEquals("$[0]", reader.getPath());
|
||||||
reader.beginArray();
|
reader.beginArray();
|
||||||
|
assertEquals("$[0][0]", reader.getPreviousPath());
|
||||||
assertEquals("$[0][0]", reader.getPath());
|
assertEquals("$[0][0]", reader.getPath());
|
||||||
reader.endArray();
|
reader.endArray();
|
||||||
|
assertEquals("$[0]", reader.getPreviousPath());
|
||||||
assertEquals("$[1]", reader.getPath());
|
assertEquals("$[1]", reader.getPath());
|
||||||
reader.beginArray();
|
reader.beginArray();
|
||||||
|
assertEquals("$[1][0]", reader.getPreviousPath());
|
||||||
assertEquals("$[1][0]", reader.getPath());
|
assertEquals("$[1][0]", reader.getPath());
|
||||||
reader.endArray();
|
reader.endArray();
|
||||||
|
assertEquals("$[1]", reader.getPreviousPath());
|
||||||
assertEquals("$[2]", reader.getPath());
|
assertEquals("$[2]", reader.getPath());
|
||||||
reader.beginArray();
|
reader.beginArray();
|
||||||
|
assertEquals("$[2][0]", reader.getPreviousPath());
|
||||||
assertEquals("$[2][0]", reader.getPath());
|
assertEquals("$[2][0]", reader.getPath());
|
||||||
reader.endArray();
|
reader.endArray();
|
||||||
|
assertEquals("$[2]", reader.getPreviousPath());
|
||||||
assertEquals("$[3]", reader.getPath());
|
assertEquals("$[3]", reader.getPath());
|
||||||
reader.endArray();
|
reader.endArray();
|
||||||
|
assertEquals("$", reader.getPreviousPath());
|
||||||
assertEquals("$", reader.getPath());
|
assertEquals("$", reader.getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user