fix(接口测试): 修复jsonpath提取显示科学计数法的缺陷
--bug=1024973 --user=王孝刚 【接口测试】jsonpath提取小数格式-提取结果格式被转换了 https://www.tapd.cn/55049933/s/1357860
This commit is contained in:
parent
ddfbc355e8
commit
c8cdd4dcd2
|
@ -238,14 +238,10 @@ export default {
|
|||
.replaceAll('(', '\\(')
|
||||
.replaceAll(')', '\\)')
|
||||
.replaceAll('+', '\\+')
|
||||
.replaceAll('[', '\\[')
|
||||
.replaceAll(']', '\\]')
|
||||
.replaceAll('?', '\\?')
|
||||
.replaceAll('/', '\\/')
|
||||
.replaceAll('*', '\\*')
|
||||
.replaceAll('^', '\\^')
|
||||
.replaceAll('{', '\\{')
|
||||
.replaceAll('}', '\\}')
|
||||
.replaceAll('$', '\\$');
|
||||
}
|
||||
jsonItem.expect = expect;
|
||||
|
|
|
@ -200,14 +200,10 @@ export default {
|
|||
.replaceAll(')', '\\)')
|
||||
.replaceAll('+', '\\+')
|
||||
.replaceAll('.', '\\.')
|
||||
.replaceAll('[', '\\[')
|
||||
.replaceAll(']', '\\]')
|
||||
.replaceAll('?', '\\?')
|
||||
.replaceAll('/', '\\/')
|
||||
.replaceAll('*', '\\*')
|
||||
.replaceAll('^', '\\^')
|
||||
.replaceAll('{', '\\{')
|
||||
.replaceAll('}', '\\}')
|
||||
.replaceAll('$', '\\$');
|
||||
}
|
||||
jsonItem.expect = expect;
|
||||
|
|
|
@ -250,14 +250,10 @@ export default {
|
|||
.replaceAll('(', '\\(')
|
||||
.replaceAll(')', '\\)')
|
||||
.replaceAll('+', '\\+')
|
||||
.replaceAll('[', '\\[')
|
||||
.replaceAll(']', '\\]')
|
||||
.replaceAll('?', '\\?')
|
||||
.replaceAll('/', '\\/')
|
||||
.replaceAll('*', '\\*')
|
||||
.replaceAll('^', '\\^')
|
||||
.replaceAll('{', '\\{')
|
||||
.replaceAll('}', '\\}')
|
||||
.replaceAll('$', '\\$');
|
||||
}
|
||||
jsonItem.expect = expect;
|
||||
|
|
|
@ -224,10 +224,15 @@ export default {
|
|||
jsonItem.setJSONPathDescription();
|
||||
let expect = jsonItem.expect;
|
||||
if (expect) {
|
||||
expect = expect.replaceAll('\\', "\\\\").replaceAll('(', "\\(").replaceAll(')', "\\)")
|
||||
.replaceAll('+', "\\+").replaceAll('[', "\\[").replaceAll(']', "\\]")
|
||||
.replaceAll('?', "\\?").replaceAll('/', "\\/").replaceAll('*', "\\*")
|
||||
.replaceAll('^', "\\^").replaceAll('{', "\\{").replaceAll('}', "\\}").replaceAll('$', "\\$");
|
||||
expect = expect.replaceAll('\\', "\\\\")
|
||||
.replaceAll('(', "\\(")
|
||||
.replaceAll(')', "\\)")
|
||||
.replaceAll('+', "\\+")
|
||||
.replaceAll('?', "\\?")
|
||||
.replaceAll('/', "\\/")
|
||||
.replaceAll('*', "\\*")
|
||||
.replaceAll('^', "\\^")
|
||||
.replaceAll('$', "\\$");
|
||||
}
|
||||
jsonItem.expect = expect;
|
||||
jsonItem.enable = true;
|
||||
|
|
|
@ -197,10 +197,16 @@ export default {
|
|||
jsonItem.setJSONPathDescription();
|
||||
let expect = jsonItem.expect;
|
||||
if (expect) {
|
||||
expect = expect.replaceAll('\\', "\\\\").replaceAll('(', "\\(").replaceAll(')', "\\)")
|
||||
.replaceAll('+', "\\+").replaceAll('.', "\\.").replaceAll('[', "\\[").replaceAll(']', "\\]")
|
||||
.replaceAll('?', "\\?").replaceAll('/', "\\/").replaceAll('*', "\\*")
|
||||
.replaceAll('^', "\\^").replaceAll('{', "\\{").replaceAll('}', "\\}").replaceAll('$', "\\$");
|
||||
expect = expect.replaceAll('\\', '\\\\')
|
||||
.replaceAll('(', '\\(')
|
||||
.replaceAll(')', '\\)')
|
||||
.replaceAll('+', '\\+')
|
||||
.replaceAll('.', '\\.')
|
||||
.replaceAll('?', '\\?')
|
||||
.replaceAll('/', '\\/')
|
||||
.replaceAll('*', '\\*')
|
||||
.replaceAll('^', '\\^')
|
||||
.replaceAll('$', '\\$');
|
||||
}
|
||||
jsonItem.expect = expect;
|
||||
this.assertions.jsonPath.push(jsonItem);
|
||||
|
|
|
@ -0,0 +1,826 @@
|
|||
package net.minidev.json.parser;
|
||||
|
||||
/*
|
||||
* Copyright 2011-2023 JSON-SMART authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import net.minidev.json.writer.JsonReader;
|
||||
import net.minidev.json.writer.JsonReaderI;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
|
||||
import static net.minidev.json.parser.ParseException.ERROR_UNEXPECTED_CHAR;
|
||||
import static net.minidev.json.parser.ParseException.ERROR_UNEXPECTED_EOF;
|
||||
import static net.minidev.json.parser.ParseException.ERROR_UNEXPECTED_LEADING_0;
|
||||
import static net.minidev.json.parser.ParseException.ERROR_UNEXPECTED_TOKEN;
|
||||
import static net.minidev.json.parser.ParseException.ERROR_UNEXPECTED_UNICODE;
|
||||
import static net.minidev.json.parser.ParseException.ERROR_UNEXPECTED_JSON_DEPTH;
|
||||
|
||||
/**
|
||||
* JSONParserBase is the common code between {@link JSONParserString} and
|
||||
* {@link JSONParserReader}
|
||||
*
|
||||
* @author Uriel Chemouni <uchemouni@gmail.com>
|
||||
* @see JSONParserMemory
|
||||
* @see JSONParserStream
|
||||
*/
|
||||
abstract class JSONParserBase {
|
||||
protected char c;
|
||||
/**
|
||||
* hard coded maximal depth for JSON parsing
|
||||
*/
|
||||
public final static int MAX_DEPTH = 400;
|
||||
protected int depth = 0;
|
||||
|
||||
JsonReader base;
|
||||
public final static byte EOI = 0x1A;
|
||||
protected static final char MAX_STOP = 126; // '}' -> 125
|
||||
private String lastKey;
|
||||
|
||||
protected static boolean[] stopAll = new boolean[MAX_STOP];
|
||||
protected static boolean[] stopArray = new boolean[MAX_STOP];
|
||||
protected static boolean[] stopKey = new boolean[MAX_STOP];
|
||||
protected static boolean[] stopValue = new boolean[MAX_STOP];
|
||||
protected static boolean[] stopX = new boolean[MAX_STOP];
|
||||
|
||||
static {
|
||||
stopKey[':'] = stopKey[EOI] = true;
|
||||
stopValue[','] = stopValue['}'] = stopValue[EOI] = true;
|
||||
stopArray[','] = stopArray[']'] = stopArray[EOI] = true;
|
||||
stopX[EOI] = true;
|
||||
stopAll[','] = stopAll[':'] = true;
|
||||
stopAll[']'] = stopAll['}'] = stopAll[EOI] = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* End of static declaration
|
||||
*/
|
||||
//
|
||||
//
|
||||
protected final MSB sb = new MSB(15);
|
||||
protected Object xo;
|
||||
protected String xs;
|
||||
protected int pos;
|
||||
|
||||
/*
|
||||
* Parsing flags
|
||||
*/
|
||||
protected final boolean acceptLeadinZero;
|
||||
protected final boolean acceptNaN;
|
||||
protected final boolean acceptNonQuote;
|
||||
protected final boolean acceptSimpleQuote;
|
||||
protected final boolean acceptUselessComma;
|
||||
protected final boolean checkTaillingData;
|
||||
protected final boolean checkTaillingSpace;
|
||||
protected final boolean ignoreControlChar;
|
||||
protected final boolean useHiPrecisionFloat;
|
||||
protected final boolean useIntegerStorage;
|
||||
protected final boolean reject127;
|
||||
protected final boolean unrestictBigDigit;
|
||||
|
||||
public JSONParserBase(int permissiveMode) {
|
||||
this.acceptNaN = (permissiveMode & JSONParser.ACCEPT_NAN) > 0;
|
||||
this.acceptNonQuote = (permissiveMode & JSONParser.ACCEPT_NON_QUOTE) > 0;
|
||||
this.acceptSimpleQuote = (permissiveMode & JSONParser.ACCEPT_SIMPLE_QUOTE) > 0;
|
||||
this.ignoreControlChar = (permissiveMode & JSONParser.IGNORE_CONTROL_CHAR) > 0;
|
||||
this.useIntegerStorage = (permissiveMode & JSONParser.USE_INTEGER_STORAGE) > 0;
|
||||
this.acceptLeadinZero = (permissiveMode & JSONParser.ACCEPT_LEADING_ZERO) > 0;
|
||||
this.acceptUselessComma = (permissiveMode & JSONParser.ACCEPT_USELESS_COMMA) > 0;
|
||||
this.useHiPrecisionFloat = (permissiveMode & JSONParser.USE_HI_PRECISION_FLOAT) > 0;
|
||||
this.checkTaillingData = (permissiveMode & (JSONParser.ACCEPT_TAILLING_DATA
|
||||
| JSONParser.ACCEPT_TAILLING_SPACE)) != (JSONParser.ACCEPT_TAILLING_DATA
|
||||
| JSONParser.ACCEPT_TAILLING_SPACE);
|
||||
this.checkTaillingSpace = (permissiveMode & JSONParser.ACCEPT_TAILLING_SPACE) == 0;
|
||||
this.reject127 = (permissiveMode & JSONParser.REJECT_127_CHAR) > 0;
|
||||
this.unrestictBigDigit = (permissiveMode & JSONParser.BIG_DIGIT_UNRESTRICTED) > 0;
|
||||
}
|
||||
|
||||
public void checkControleChar() throws ParseException {
|
||||
if (ignoreControlChar)
|
||||
return;
|
||||
int l = xs.length();
|
||||
for (int i = 0; i < l; i++) {
|
||||
char c = xs.charAt(i);
|
||||
if (c < 0)
|
||||
continue;
|
||||
if (c <= 31)
|
||||
throw new ParseException(pos + i, ERROR_UNEXPECTED_CHAR, c);
|
||||
if (c == 127) {
|
||||
if (reject127)
|
||||
throw new ParseException(pos + i, ParseException.ERROR_UNEXPECTED_CHAR, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void checkLeadinZero() throws ParseException {
|
||||
int len = xs.length();
|
||||
if (len == 1)
|
||||
return;
|
||||
if (len == 2) {
|
||||
if (xs.equals("00"))
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_LEADING_0, xs);
|
||||
return;
|
||||
}
|
||||
char c1 = xs.charAt(0);
|
||||
char c2 = xs.charAt(1);
|
||||
if (c1 == '-') {
|
||||
char c3 = xs.charAt(2);
|
||||
if (c2 == '0' && c3 >= '0' && c3 <= '9')
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_LEADING_0, xs);
|
||||
return;
|
||||
}
|
||||
if (c1 == '0' && c2 >= '0' && c2 <= '9')
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_LEADING_0, xs);
|
||||
}
|
||||
|
||||
protected Number extractFloat() throws ParseException {
|
||||
if (!acceptLeadinZero)
|
||||
checkLeadinZero();
|
||||
|
||||
try {
|
||||
if (!useHiPrecisionFloat)
|
||||
return Float.parseFloat(xs);
|
||||
|
||||
// follow JSonIJ parsing method
|
||||
// use extra CPU to check if the result can be return as double without
|
||||
// precision lost
|
||||
if (!unrestictBigDigit) {
|
||||
double asDouble = Double.parseDouble(xs);
|
||||
final String doubleStr = String.valueOf(asDouble);
|
||||
// we need a compare `e` `E` `e+` `E+`
|
||||
if (compareDoublePrecision(doubleStr, xs)) {
|
||||
return asDouble;
|
||||
}
|
||||
}
|
||||
return new BigDecimal(xs);
|
||||
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean compareDoublePrecision(String convert, String origin) {
|
||||
final char[] charArray = convert.toCharArray();
|
||||
final char[] originArray = origin.toCharArray();
|
||||
if (charArray.length > originArray.length) {
|
||||
return false;
|
||||
}
|
||||
int j = 0;
|
||||
for (int i = 0; i < charArray.length; i++) {
|
||||
if (charArray[i] < '0' || charArray[i] > '9') {
|
||||
if (originArray[j] >= '0' && originArray[j] <= '9') {
|
||||
return false;
|
||||
} else {
|
||||
j++;
|
||||
if (originArray[j] == '+') {
|
||||
j++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (charArray[i] != originArray[j]) {
|
||||
return false;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
return j == originArray.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* use to return Primitive Type, or String, Or JsonObject or JsonArray generated
|
||||
* by a ContainerFactory
|
||||
*/
|
||||
protected <T> T parse(JsonReaderI<T> mapper) throws ParseException {
|
||||
this.pos = -1;
|
||||
T result;
|
||||
try {
|
||||
read();
|
||||
result = readFirst(mapper);
|
||||
if (checkTaillingData) {
|
||||
if (!checkTaillingSpace)
|
||||
skipSpace();
|
||||
if (c != EOI)
|
||||
throw new ParseException(pos - 1, ERROR_UNEXPECTED_TOKEN, c);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new ParseException(pos, e);
|
||||
}
|
||||
xs = null;
|
||||
xo = null;
|
||||
return result;
|
||||
}
|
||||
|
||||
protected Number parseNumber(String s) throws ParseException {
|
||||
// position
|
||||
int p = 0;
|
||||
// length
|
||||
int l = s.length();
|
||||
// max position long base 10 length
|
||||
int max = 19;
|
||||
boolean neg;
|
||||
|
||||
if (s.charAt(0) == '-') {
|
||||
p++;
|
||||
max++;
|
||||
neg = true;
|
||||
if (!acceptLeadinZero && l >= 3 && s.charAt(1) == '0')
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_LEADING_0, s);
|
||||
} else {
|
||||
neg = false;
|
||||
if (!acceptLeadinZero && l >= 2 && s.charAt(0) == '0')
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_LEADING_0, s);
|
||||
}
|
||||
|
||||
boolean mustCheck;
|
||||
if (l < max) {
|
||||
max = l;
|
||||
mustCheck = false;
|
||||
} else if (l > max) {
|
||||
return new BigInteger(s, 10);
|
||||
} else {
|
||||
max = l - 1;
|
||||
mustCheck = true;
|
||||
}
|
||||
|
||||
long r = 0;
|
||||
while (p < max) {
|
||||
r = (r * 10L) + ('0' - s.charAt(p++));
|
||||
}
|
||||
if (mustCheck) {
|
||||
boolean isBig;
|
||||
if (r > -922337203685477580L) {
|
||||
isBig = false;
|
||||
} else if (r < -922337203685477580L) {
|
||||
isBig = true;
|
||||
} else {
|
||||
if (neg)
|
||||
isBig = (s.charAt(p) > '8');
|
||||
else
|
||||
isBig = (s.charAt(p) > '7');
|
||||
}
|
||||
if (isBig)
|
||||
return new BigInteger(s, 10);
|
||||
r = r * 10L + ('0' - s.charAt(p));
|
||||
}
|
||||
if (neg) {
|
||||
if (this.useIntegerStorage && r >= Integer.MIN_VALUE)
|
||||
return (int) r;
|
||||
return r;
|
||||
}
|
||||
r = -r;
|
||||
if (this.useIntegerStorage && r <= Integer.MAX_VALUE)
|
||||
return (int) r;
|
||||
return r;
|
||||
}
|
||||
|
||||
abstract protected void read() throws IOException;
|
||||
|
||||
protected <T> T readArray(JsonReaderI<T> mapper) throws ParseException, IOException {
|
||||
if (c != '[')
|
||||
throw new RuntimeException("Internal Error");
|
||||
if (++this.depth > MAX_DEPTH) {
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_JSON_DEPTH, c);
|
||||
}
|
||||
Object current = mapper.createArray();
|
||||
read();
|
||||
boolean needData = false;
|
||||
// special case needData is false and can close is true
|
||||
if (c == ',' && !acceptUselessComma)
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, (char) c);
|
||||
for (; ; ) {
|
||||
switch (c) {
|
||||
case ' ':
|
||||
case '\r':
|
||||
case '\n':
|
||||
case '\t':
|
||||
read();
|
||||
continue;
|
||||
case ']':
|
||||
if (needData && !acceptUselessComma)
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, (char) c);
|
||||
this.depth--;
|
||||
read(); /* unstack */
|
||||
//
|
||||
return mapper.convert(current);
|
||||
case ':':
|
||||
case '}':
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, (char) c);
|
||||
case ',':
|
||||
if (needData && !acceptUselessComma)
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, (char) c);
|
||||
read();
|
||||
needData = true;
|
||||
continue;
|
||||
case EOI:
|
||||
throw new ParseException(pos - 1, ERROR_UNEXPECTED_EOF, "EOF");
|
||||
default:
|
||||
mapper.addValue(current, readMain(mapper, stopArray));
|
||||
needData = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* use to return Primitive Type, or String, Or JsonObject or JsonArray generated
|
||||
* by a ContainerFactory
|
||||
*/
|
||||
protected <T> T readFirst(JsonReaderI<T> mapper) throws ParseException, IOException {
|
||||
for (; ; ) {
|
||||
switch (c) {
|
||||
// skip spaces
|
||||
case ' ':
|
||||
case '\r':
|
||||
case '\n':
|
||||
case '\t':
|
||||
read();
|
||||
continue;
|
||||
// invalid state
|
||||
case ':':
|
||||
case '}':
|
||||
case ']':
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, c);
|
||||
// start object
|
||||
case '{':
|
||||
return readObject(mapper);
|
||||
// start Array
|
||||
case '[':
|
||||
return readArray(mapper);
|
||||
// start string
|
||||
case '"':
|
||||
case '\'':
|
||||
readString();
|
||||
//
|
||||
return mapper.convert(xs);
|
||||
// string or null
|
||||
case 'n':
|
||||
readNQString(stopX);
|
||||
if ("null".equals(xs)) {
|
||||
//
|
||||
return null;
|
||||
}
|
||||
if (!acceptNonQuote)
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs);
|
||||
//
|
||||
return mapper.convert(xs);
|
||||
// string or false
|
||||
case 'f':
|
||||
readNQString(stopX);
|
||||
if ("false".equals(xs)) {
|
||||
//
|
||||
return mapper.convert(Boolean.FALSE);
|
||||
}
|
||||
if (!acceptNonQuote)
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs);
|
||||
//
|
||||
return mapper.convert(xs);
|
||||
// string or true
|
||||
case 't':
|
||||
readNQString(stopX);
|
||||
if ("true".equals(xs)) {
|
||||
//
|
||||
return mapper.convert(Boolean.TRUE);
|
||||
}
|
||||
if (!acceptNonQuote)
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs);
|
||||
//
|
||||
return mapper.convert(xs);
|
||||
// string or NaN
|
||||
case 'N':
|
||||
readNQString(stopX);
|
||||
if (!acceptNaN)
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs);
|
||||
if ("NaN".equals(xs)) {
|
||||
//
|
||||
return mapper.convert(Float.valueOf(Float.NaN));
|
||||
}
|
||||
if (!acceptNonQuote)
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs);
|
||||
//
|
||||
return mapper.convert(xs);
|
||||
// digits
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case '-':
|
||||
xo = readNumber(stopX);
|
||||
//
|
||||
return mapper.convert(xo);
|
||||
default:
|
||||
readNQString(stopX);
|
||||
if (!acceptNonQuote)
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs);
|
||||
//
|
||||
return mapper.convert(xs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* use to return Primitive Type, or String, Or JsonObject or JsonArray generated
|
||||
* by a ContainerFactory
|
||||
*/
|
||||
protected Object readMain(JsonReaderI<?> mapper, boolean stop[]) throws ParseException, IOException {
|
||||
for (; ; ) {
|
||||
switch (c) {
|
||||
// skip spaces
|
||||
case ' ':
|
||||
case '\r':
|
||||
case '\n':
|
||||
case '\t':
|
||||
read();
|
||||
continue;
|
||||
// invalid state
|
||||
case ':':
|
||||
case '}':
|
||||
case ']':
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, c);
|
||||
// start object
|
||||
case '{':
|
||||
return readObject(mapper.startObject(lastKey));
|
||||
// start Array
|
||||
case '[':
|
||||
return readArray(mapper.startArray(lastKey));
|
||||
// start string
|
||||
case '"':
|
||||
case '\'':
|
||||
readString();
|
||||
//
|
||||
return xs;
|
||||
// string or null
|
||||
case 'n':
|
||||
readNQString(stop);
|
||||
if ("null".equals(xs)) {
|
||||
//
|
||||
return null;
|
||||
}
|
||||
if (!acceptNonQuote)
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs);
|
||||
//
|
||||
return xs;
|
||||
// string or false
|
||||
case 'f':
|
||||
readNQString(stop);
|
||||
if ("false".equals(xs)) {
|
||||
//
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
if (!acceptNonQuote)
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs);
|
||||
//
|
||||
return xs;
|
||||
// string or true
|
||||
case 't':
|
||||
readNQString(stop);
|
||||
if ("true".equals(xs)) {
|
||||
//
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
if (!acceptNonQuote)
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs);
|
||||
//
|
||||
return xs;
|
||||
// string or NaN
|
||||
case 'N':
|
||||
readNQString(stop);
|
||||
if (!acceptNaN)
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs);
|
||||
if ("NaN".equals(xs)) {
|
||||
//
|
||||
return Float.valueOf(Float.NaN);
|
||||
}
|
||||
if (!acceptNonQuote)
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs);
|
||||
//
|
||||
return xs;
|
||||
// digits
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case '-':
|
||||
//
|
||||
//
|
||||
return readNumber(stop);
|
||||
default:
|
||||
readNQString(stop);
|
||||
if (!acceptNonQuote)
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs);
|
||||
//
|
||||
return xs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract protected void readNoEnd() throws ParseException, IOException;
|
||||
|
||||
abstract protected void readNQString(boolean[] stop) throws IOException;
|
||||
|
||||
abstract protected Object readNumber(boolean[] stop) throws ParseException, IOException;
|
||||
|
||||
protected <T> T readObject(JsonReaderI<T> mapper) throws ParseException, IOException {
|
||||
//
|
||||
if (c != '{')
|
||||
throw new RuntimeException("Internal Error");
|
||||
if (++this.depth > MAX_DEPTH) {
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_JSON_DEPTH, c);
|
||||
}
|
||||
Object current = mapper.createObject();
|
||||
boolean needData = false;
|
||||
boolean acceptData = true;
|
||||
for (; ; ) {
|
||||
read();
|
||||
switch (c) {
|
||||
case ' ':
|
||||
case '\r':
|
||||
case '\t':
|
||||
case '\n':
|
||||
continue;
|
||||
case ':':
|
||||
case ']':
|
||||
case '[':
|
||||
case '{':
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, c);
|
||||
case '}':
|
||||
if (needData && !acceptUselessComma)
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, (char) c);
|
||||
this.depth--;
|
||||
read(); /* unstack */
|
||||
//
|
||||
return mapper.convert(current);
|
||||
case ',':
|
||||
if (needData && !acceptUselessComma)
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, (char) c);
|
||||
acceptData = needData = true;
|
||||
continue;
|
||||
case '"':
|
||||
case '\'':
|
||||
default:
|
||||
// int keyStart = pos;
|
||||
if (c == '\"' || c == '\'') {
|
||||
readString();
|
||||
} else {
|
||||
readNQString(stopKey);
|
||||
if (!acceptNonQuote)
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, xs);
|
||||
}
|
||||
String key = xs;
|
||||
if (!acceptData)
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_TOKEN, key);
|
||||
|
||||
// Skip spaces
|
||||
skipSpace();
|
||||
|
||||
if (c != ':') {
|
||||
if (c == EOI)
|
||||
throw new ParseException(pos - 1, ERROR_UNEXPECTED_EOF, null);
|
||||
throw new ParseException(pos - 1, ERROR_UNEXPECTED_CHAR, c);
|
||||
}
|
||||
readNoEnd(); /* skip : */
|
||||
lastKey = key;
|
||||
Object value = readMain(mapper, stopValue);
|
||||
mapper.setValue(current, key, value);
|
||||
lastKey = null;
|
||||
|
||||
// Object duplicate = obj.put(key, readMain(stopValue));
|
||||
// if (duplicate != null)
|
||||
// throw new ParseException(keyStart, ERROR_UNEXPECTED_DUPLICATE_KEY, key);
|
||||
// handler.endObjectEntry();
|
||||
// should loop skipping read step
|
||||
skipSpace();
|
||||
if (c == '}') {
|
||||
this.depth--;
|
||||
read(); /* unstack */
|
||||
//
|
||||
return mapper.convert(current);
|
||||
}
|
||||
if (c == EOI) // Fixed on 18/10/2011 reported by vladimir
|
||||
throw new ParseException(pos - 1, ERROR_UNEXPECTED_EOF, null);
|
||||
// if c==, continue
|
||||
if (c == ',')
|
||||
acceptData = needData = true;
|
||||
else
|
||||
throw new ParseException(pos - 1, ERROR_UNEXPECTED_TOKEN, c);
|
||||
// acceptData = needData = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* store and read
|
||||
*/
|
||||
abstract void readS() throws IOException;
|
||||
|
||||
abstract protected void readString() throws ParseException, IOException;
|
||||
|
||||
protected void readString2() throws ParseException, IOException {
|
||||
/* assert (c == '\"' || c == '\'') */
|
||||
char sep = c;
|
||||
for (; ; ) {
|
||||
read();
|
||||
switch (c) {
|
||||
case EOI:
|
||||
throw new ParseException(pos - 1, ERROR_UNEXPECTED_EOF, null);
|
||||
case '"':
|
||||
case '\'':
|
||||
if (sep == c) {
|
||||
read();
|
||||
xs = sb.toString();
|
||||
return;
|
||||
}
|
||||
sb.append(c);
|
||||
break;
|
||||
case '\\':
|
||||
read();
|
||||
switch (c) {
|
||||
case 't':
|
||||
sb.append('\t');
|
||||
break;
|
||||
case 'n':
|
||||
sb.append('\n');
|
||||
break;
|
||||
case 'r':
|
||||
sb.append('\r');
|
||||
break;
|
||||
case 'f':
|
||||
sb.append('\f');
|
||||
break;
|
||||
case 'b':
|
||||
sb.append('\b');
|
||||
break;
|
||||
case '\\':
|
||||
sb.append('\\');
|
||||
break;
|
||||
case '/':
|
||||
sb.append('/');
|
||||
break;
|
||||
case '\'':
|
||||
sb.append('\'');
|
||||
break;
|
||||
case '"':
|
||||
sb.append('"');
|
||||
break;
|
||||
case 'u':
|
||||
sb.append(readUnicode(4));
|
||||
break;
|
||||
case 'x':
|
||||
sb.append(readUnicode(2));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case '\0': // end of string
|
||||
case (char) 1: // Start of heading
|
||||
case (char) 2: // Start of text
|
||||
case (char) 3: // End of text
|
||||
case (char) 4: // End of transmission
|
||||
case (char) 5: // Enquiry
|
||||
case (char) 6: // Acknowledge
|
||||
case (char) 7: // Bell
|
||||
case '\b': // 8: backSpase
|
||||
case '\t': // 9: horizontal tab
|
||||
case '\n': // 10: new line
|
||||
case (char) 11: // Vertical tab
|
||||
case '\f': // 12: form feed
|
||||
case '\r': // 13: return carriage
|
||||
case (char) 14: // Shift Out, alternate character set
|
||||
case (char) 15: // Shift In, resume defaultn character set
|
||||
case (char) 16: // Data link escape
|
||||
case (char) 17: // XON, with XOFF to pause listings;
|
||||
case (char) 18: // Device control 2, block-mode flow control
|
||||
case (char) 19: // XOFF, with XON is TERM=18 flow control
|
||||
case (char) 20: // Device control 4
|
||||
case (char) 21: // Negative acknowledge
|
||||
case (char) 22: // Synchronous idle
|
||||
case (char) 23: // End transmission block, not the same as EOT
|
||||
case (char) 24: // Cancel line, MPE echoes !!!
|
||||
case (char) 25: // End of medium, Control-Y interrupt
|
||||
// case (char) 26: // Substitute == EOI
|
||||
case (char) 27: // escape
|
||||
case (char) 28: // File Separator
|
||||
case (char) 29: // Group Separator
|
||||
case (char) 30: // Record Separator
|
||||
case (char) 31: // Unit Separator
|
||||
if (ignoreControlChar)
|
||||
continue;
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, c);
|
||||
case (char) 127: // del
|
||||
if (ignoreControlChar)
|
||||
continue;
|
||||
if (reject127)
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, c);
|
||||
default:
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected char readUnicode(int totalChars) throws ParseException, IOException {
|
||||
int value = 0;
|
||||
for (int i = 0; i < totalChars; i++) {
|
||||
value = value * 16;
|
||||
read();
|
||||
if (c <= '9' && c >= '0')
|
||||
value += c - '0';
|
||||
else if (c <= 'F' && c >= 'A')
|
||||
value += (c - 'A') + 10;
|
||||
else if (c >= 'a' && c <= 'f')
|
||||
value += (c - 'a') + 10;
|
||||
else if (c == EOI)
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_EOF, "EOF");
|
||||
else
|
||||
throw new ParseException(pos, ERROR_UNEXPECTED_UNICODE, c);
|
||||
}
|
||||
return (char) value;
|
||||
}
|
||||
|
||||
protected void skipDigits() throws IOException {
|
||||
for (; ; ) {
|
||||
if (c < '0' || c > '9')
|
||||
return;
|
||||
readS();
|
||||
}
|
||||
}
|
||||
|
||||
protected void skipNQString(boolean[] stop) throws IOException {
|
||||
for (; ; ) {
|
||||
if ((c == EOI) || (c >= 0 && c < MAX_STOP && stop[c]))
|
||||
return;
|
||||
readS();
|
||||
}
|
||||
}
|
||||
|
||||
protected void skipSpace() throws IOException {
|
||||
for (; ; ) {
|
||||
if (c > ' ' || c == EOI)
|
||||
return;
|
||||
readS();
|
||||
}
|
||||
}
|
||||
|
||||
public static class MSB {
|
||||
char b[];
|
||||
int p;
|
||||
|
||||
public MSB(int size) {
|
||||
b = new char[size];
|
||||
p = -1;
|
||||
}
|
||||
|
||||
public void append(char c) {
|
||||
p++;
|
||||
if (b.length <= p) {
|
||||
char[] t = new char[b.length * 2 + 1];
|
||||
System.arraycopy(b, 0, t, 0, b.length);
|
||||
b = t;
|
||||
}
|
||||
b[p] = c;
|
||||
}
|
||||
|
||||
public void append(int c) {
|
||||
p++;
|
||||
if (b.length <= p) {
|
||||
char[] t = new char[b.length * 2 + 1];
|
||||
System.arraycopy(b, 0, t, 0, b.length);
|
||||
b = t;
|
||||
}
|
||||
b[p] = (char) c;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new String(b, 0, p + 1);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
p = -1;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue