Updated Grammar for matching JsonArray to be left-associative rather than right-associative. Gson can now parse arrays of size over 11MB instead of 80KB which was the prior limit. Thanks for the tip, kenotron.

This commit is contained in:
Inderjeet Singh 2009-08-22 01:03:27 +00:00
parent c13fc568c7
commit cbcf7defa3
12 changed files with 1037 additions and 905 deletions

View File

@ -19,9 +19,9 @@ package com.google.gson;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
/**
@ -39,7 +39,7 @@ public final class JsonArray extends JsonElement implements Iterable<JsonElement
* Creates an empty JsonArray.
*/
public JsonArray() {
elements = new LinkedList<JsonElement>();
elements = new ArrayList<JsonElement>();
}
/**

View File

@ -138,6 +138,10 @@ final class JsonParserJavacc implements JsonParserJavaccConstants {
JsonArray array = new JsonArray();
jj_consume_token(31);
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
case 32:
array = JsonArrayEmpty(array);
{if (true) return array;}
break;
case DIGITS:
case NULL:
case NAN:
@ -148,31 +152,51 @@ final class JsonParserJavacc implements JsonParserJavaccConstants {
case 27:
case 31:
case 33:
Elements(array);
JsonArrayElement(array);
label_1:
while (true) {
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
case 29:
;
break;
default:
jj_la1[6] = jj_gen;
;
break label_1;
}
JsonArrayNextElement(array);
}
jj_consume_token(32);
array.reverse();
{if (true) return array;}
break;
default:
jj_la1[7] = jj_gen;
jj_consume_token(-1);
throw new ParseException();
}
throw new Error("Missing return statement in function");
}
final private JsonArray JsonArrayEmpty(JsonArray array) throws ParseException {
jj_consume_token(32);
{if (true) return array;}
throw new Error("Missing return statement in function");
}
final private void Elements(JsonArray array) throws ParseException {
JsonElement element;
final private JsonArray JsonArrayElement(JsonArray array) throws ParseException {
JsonElement element = null;
element = JsonValue();
switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
case 29:
jj_consume_token(29);
Elements(array);
break;
default:
jj_la1[7] = jj_gen;
;
}
array.add(element);
{if (true) return array;}
throw new Error("Missing return statement in function");
}
final private JsonArray JsonArrayNextElement(JsonArray array) throws ParseException {
JsonElement element = null;
jj_consume_token(29);
element = JsonValue();
array.add(element);
{if (true) return array;}
throw new Error("Missing return statement in function");
}
final private JsonElement JsonValue() throws ParseException {
@ -406,36 +430,36 @@ final class JsonParserJavacc implements JsonParserJavaccConstants {
finally { jj_save(0, xla); }
}
private boolean jj_3R_4() {
private boolean jj_3R_3() {
if (jj_scan_token(NAN)) return true;
return false;
}
private boolean jj_3R_2() {
Token xsp;
xsp = jj_scanpos;
if (jj_3R_3()) {
jj_scanpos = xsp;
if (jj_3R_4()) return true;
}
return false;
}
private boolean jj_3R_5() {
if (jj_scan_token(33)) return true;
return false;
}
private boolean jj_3R_3() {
private boolean jj_3R_4() {
Token xsp;
xsp = jj_scanpos;
if (jj_3R_4()) jj_scanpos = xsp;
if (jj_3R_5()) jj_scanpos = xsp;
if (jj_scan_token(INFINITY)) return true;
return false;
}
private boolean jj_3_1() {
if (jj_3R_1()) return true;
return false;
}
private boolean jj_3R_2() {
if (jj_scan_token(NAN)) return true;
return false;
}
private boolean jj_3R_1() {
Token xsp;
xsp = jj_scanpos;
if (jj_3R_2()) {
jj_scanpos = xsp;
if (jj_3R_3()) return true;
}
if (jj_3R_2()) return true;
return false;
}
@ -458,10 +482,10 @@ final class JsonParserJavacc implements JsonParserJavaccConstants {
jj_la1_init_1();
}
private static void jj_la1_init_0() {
jj_la1_0 = new int[] {0x4000000,0x880307c0,0x8c0307c1,0x31800,0x20000000,0x31800,0x880307c0,0x20000000,0x880307c0,0x30740,0x0,0x20,0x40,0x0,0x300,0x0,0x1800,0x30000,};
jj_la1_0 = new int[] {0x4000000,0x880307c0,0x8c0307c1,0x31800,0x20000000,0x31800,0x20000000,0x880307c0,0x880307c0,0x30740,0x0,0x20,0x40,0x0,0x300,0x0,0x1800,0x30000,};
}
private static void jj_la1_init_1() {
jj_la1_1 = new int[] {0x0,0x2,0x2,0x0,0x0,0x0,0x2,0x0,0x2,0x2,0x4,0x0,0x2,0x2,0x2,0x2,0x0,0x0,};
jj_la1_1 = new int[] {0x0,0x2,0x2,0x0,0x0,0x0,0x0,0x3,0x2,0x2,0x4,0x0,0x2,0x2,0x2,0x2,0x0,0x0,};
}
final private JJCalls[] jj_2_rtns = new JJCalls[1];
private boolean jj_rescan = false;

View File

@ -6,7 +6,6 @@ package com.google.gson;
* Token literal values and constants.
* Generated by org.javacc.parser.OtherFilesGen#start()
*/
@SuppressWarnings("all")
interface JsonParserJavaccConstants {
/** End of File. */

View File

@ -1077,9 +1077,7 @@ protected Token jjFillToken()
beginColumn = input_stream.getBeginColumn();
endLine = input_stream.getEndLine();
endColumn = input_stream.getEndColumn();
t = Token.newToken(jjmatchedKind);
t.kind = jjmatchedKind;
t.image = curTokenImage;
t = Token.newToken(jjmatchedKind, curTokenImage);
t.beginLine = beginLine;
t.endLine = endLine;

View File

@ -1,4 +1,5 @@
/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 3.0 */
/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 4.1 */
/* JavaCCOptions:KEEP_LINE_COL=null */
package com.google.gson;
/**
@ -13,25 +14,25 @@ package com.google.gson;
@SuppressWarnings("all")
final class ParseException extends Exception {
/**
* The version identifier for this Serializable class.
* Increment only if the <i>serialized</i> form of the
* class changes.
*/
private static final long serialVersionUID = 1L;
/**
* This constructor is used by the method "generateParseException"
* in the generated parser. Calling this constructor generates
* a new object of this type with the fields "currentToken",
* "expectedTokenSequences", and "tokenImage" set. The boolean
* flag "specialConstructor" is also set to true to indicate that
* this constructor was used to create this object.
* This constructor calls its super class with the empty string
* to force the "toString" method of parent class "Throwable" to
* print the error message in the form:
* ParseException: <result of getMessage>
* "expectedTokenSequences", and "tokenImage" set.
*/
public ParseException(Token currentTokenVal,
int[][] expectedTokenSequencesVal,
String[] tokenImageVal
)
{
super("");
specialConstructor = true;
super(initialise(currentTokenVal, expectedTokenSequencesVal, tokenImageVal));
currentToken = currentTokenVal;
expectedTokenSequences = expectedTokenSequencesVal;
tokenImage = tokenImageVal;
@ -49,20 +50,13 @@ final class ParseException extends Exception {
public ParseException() {
super();
specialConstructor = false;
}
/** Constructor with message. */
public ParseException(String message) {
super(message);
specialConstructor = false;
}
/**
* This variable determines which constructor was used to create
* this object and thereby affects the semantics of the
* "getMessage" method (see below).
*/
protected boolean specialConstructor;
/**
* This is the last token that has been consumed successfully. If
@ -86,19 +80,16 @@ final class ParseException extends Exception {
public String[] tokenImage;
/**
* This method has the standard behavior when this object has been
* created using the standard constructors. Otherwise, it uses
* "currentToken" and "expectedTokenSequences" to generate a parse
* It uses "currentToken" and "expectedTokenSequences" to generate a parse
* error message and returns it. If this object has been created
* due to a parse error, and you do not catch it (it gets thrown
* from the parser), then this method is called during the printing
* of the final stack trace, and hence the correct error message
* from the parser) the correct error message
* gets displayed.
*/
public String getMessage() {
if (!specialConstructor) {
return super.getMessage();
}
private static String initialise(Token currentToken,
int[][] expectedTokenSequences,
String[] tokenImage) {
String eol = System.getProperty("line.separator", "\n");
StringBuffer expected = new StringBuffer();
int maxSize = 0;
for (int i = 0; i < expectedTokenSequences.length; i++) {
@ -106,7 +97,7 @@ final class ParseException extends Exception {
maxSize = expectedTokenSequences[i].length;
}
for (int j = 0; j < expectedTokenSequences[i].length; j++) {
expected.append(tokenImage[expectedTokenSequences[i][j]]).append(" ");
expected.append(tokenImage[expectedTokenSequences[i][j]]).append(' ');
}
if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) {
expected.append("...");
@ -121,7 +112,10 @@ final class ParseException extends Exception {
retval += tokenImage[0];
break;
}
retval += " " + tokenImage[tok.kind];
retval += " \"";
retval += add_escapes(tok.image);
retval += " \"";
tok = tok.next;
}
retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn;
@ -145,7 +139,7 @@ final class ParseException extends Exception {
* when these raw version cannot be used as part of an ASCII
* string literal.
*/
protected String add_escapes(String str) {
static String add_escapes(String str) {
StringBuffer retval = new StringBuffer();
char ch;
for (int i = 0; i < str.length(); i++) {
@ -191,3 +185,4 @@ final class ParseException extends Exception {
}
}
/* JavaCC - OriginalChecksum=bf6325585417e7bd5d488795e151433b (do not edit this line) */

View File

@ -1,18 +1,20 @@
/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 4.0 */
/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 4.1 */
/* JavaCCOptions:STATIC=false,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
package com.google.gson;
/**
* An implementation of interface CharStream, where the stream is assumed to
* contain only ASCII characters (without unicode processing).
*/
@SuppressWarnings("all")
final class SimpleCharStream
{
/** Whether parser is static. */
public static final boolean staticFlag = false;
int bufsize;
int available;
int tokenBegin;
/** Position in buffer. */
public int bufpos = -1;
protected int bufline[];
protected int bufcolumn[];
@ -45,8 +47,7 @@ final class SimpleCharStream
if (wrapAround)
{
System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
System.arraycopy(buffer, 0, newbuffer,
bufsize - tokenBegin, bufpos);
System.arraycopy(buffer, 0, newbuffer, bufsize - tokenBegin, bufpos);
buffer = newbuffer;
System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
@ -110,8 +111,7 @@ final class SimpleCharStream
int i;
try {
if ((i = inputStream.read(buffer, maxNextCharInd,
available - maxNextCharInd)) == -1)
if ((i = inputStream.read(buffer, maxNextCharInd, available - maxNextCharInd)) == -1)
{
inputStream.close();
throw new java.io.IOException();
@ -129,6 +129,7 @@ final class SimpleCharStream
}
}
/** Start. */
public char BeginToken() throws java.io.IOException
{
tokenBegin = -1;
@ -178,6 +179,7 @@ final class SimpleCharStream
bufcolumn[bufpos] = column;
}
/** Read a character. */
public char readChar() throws java.io.IOException
{
if (inBuf > 0)
@ -196,7 +198,7 @@ final class SimpleCharStream
char c = buffer[bufpos];
UpdateLineColumn(c);
return (c);
return c;
}
/**
@ -217,22 +219,27 @@ final class SimpleCharStream
return bufline[bufpos];
}
/** Get token end column number. */
public int getEndColumn() {
return bufcolumn[bufpos];
}
/** Get token end line number. */
public int getEndLine() {
return bufline[bufpos];
}
/** Get token beginning column number. */
public int getBeginColumn() {
return bufcolumn[tokenBegin];
}
/** Get token beginning line number. */
public int getBeginLine() {
return bufline[tokenBegin];
}
/** Backup a number of characters. */
public void backup(int amount) {
inBuf += amount;
@ -240,6 +247,7 @@ final class SimpleCharStream
bufpos += bufsize;
}
/** Constructor. */
public SimpleCharStream(java.io.Reader dstream, int startline,
int startcolumn, int buffersize)
{
@ -253,16 +261,20 @@ final class SimpleCharStream
bufcolumn = new int[buffersize];
}
/** Constructor. */
public SimpleCharStream(java.io.Reader dstream, int startline,
int startcolumn)
{
this(dstream, startline, startcolumn, 4096);
}
/** Constructor. */
public SimpleCharStream(java.io.Reader dstream)
{
this(dstream, 1, 1, 4096);
}
/** Reinitialise. */
public void ReInit(java.io.Reader dstream, int startline,
int startcolumn, int buffersize)
{
@ -282,81 +294,96 @@ final class SimpleCharStream
bufpos = -1;
}
/** Reinitialise. */
public void ReInit(java.io.Reader dstream, int startline,
int startcolumn)
{
ReInit(dstream, startline, startcolumn, 4096);
}
/** Reinitialise. */
public void ReInit(java.io.Reader dstream)
{
ReInit(dstream, 1, 1, 4096);
}
/** Constructor. */
public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
{
this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
}
/** Constructor. */
public SimpleCharStream(java.io.InputStream dstream, int startline,
int startcolumn, int buffersize)
{
this(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
}
/** Constructor. */
public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
int startcolumn) throws java.io.UnsupportedEncodingException
{
this(dstream, encoding, startline, startcolumn, 4096);
}
/** Constructor. */
public SimpleCharStream(java.io.InputStream dstream, int startline,
int startcolumn)
{
this(dstream, startline, startcolumn, 4096);
}
/** Constructor. */
public SimpleCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
{
this(dstream, encoding, 1, 1, 4096);
}
/** Constructor. */
public SimpleCharStream(java.io.InputStream dstream)
{
this(dstream, 1, 1, 4096);
}
/** Reinitialise. */
public void ReInit(java.io.InputStream dstream, String encoding, int startline,
int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
{
ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
}
/** Reinitialise. */
public void ReInit(java.io.InputStream dstream, int startline,
int startcolumn, int buffersize)
{
ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
}
/** Reinitialise. */
public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
{
ReInit(dstream, encoding, 1, 1, 4096);
}
/** Reinitialise. */
public void ReInit(java.io.InputStream dstream)
{
ReInit(dstream, 1, 1, 4096);
}
/** Reinitialise. */
public void ReInit(java.io.InputStream dstream, String encoding, int startline,
int startcolumn) throws java.io.UnsupportedEncodingException
{
ReInit(dstream, encoding, startline, startcolumn, 4096);
}
/** Reinitialise. */
public void ReInit(java.io.InputStream dstream, int startline,
int startcolumn)
{
ReInit(dstream, startline, startcolumn, 4096);
}
/** Get token literal value. */
public String GetImage()
{
if (bufpos >= tokenBegin)
@ -366,6 +393,7 @@ final class SimpleCharStream
new String(buffer, 0, bufpos + 1);
}
/** Get the suffix. */
public char[] GetSuffix(int len)
{
char[] ret = new char[len];
@ -382,6 +410,7 @@ final class SimpleCharStream
return ret;
}
/** Reset buffer when finished. */
public void Done()
{
buffer = null;
@ -409,8 +438,7 @@ final class SimpleCharStream
int i = 0, j = 0, k = 0;
int nextColDiff = 0, columnDiff = 0;
while (i < len &&
bufline[j = start % bufsize] == bufline[k = ++start % bufsize])
while (i < len && bufline[j = start % bufsize] == bufline[k = ++start % bufsize])
{
bufline[j] = newLine;
nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
@ -438,3 +466,4 @@ final class SimpleCharStream
}
}
/* JavaCC - OriginalChecksum=351e3d8e62614bff24f1b9ba2fd77764 (do not edit this line) */

View File

@ -1,12 +1,19 @@
/* Generated By:JavaCC: Do not edit this line. Token.java Version 3.0 */
/* Generated By:JavaCC: Do not edit this line. Token.java Version 4.1 */
/* JavaCCOptions:TOKEN_EXTENDS=,KEEP_LINE_COL=null,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
package com.google.gson;
/**
* Describes the input token stream.
*/
@SuppressWarnings("all")
final class Token {
final class Token implements java.io.Serializable {
/**
* The version identifier for this Serializable class.
* Increment only if the <i>serialized</i> form of the
* class changes.
*/
private static final long serialVersionUID = 1L;
/**
* An integer that describes the kind of this token. This numbering
@ -15,12 +22,14 @@ final class Token {
*/
public int kind;
/**
* beginLine and beginColumn describe the position of the first character
* of this token; endLine and endColumn describe the position of the
* last character of this token.
*/
public int beginLine, beginColumn, endLine, endColumn;
/** The line number of the first character of this Token. */
public int beginLine;
/** The column number of the first character of this Token. */
public int beginColumn;
/** The line number of the last character of this Token. */
public int endLine;
/** The column number of the last character of this Token. */
public int endColumn;
/**
* The string image of the token.
@ -51,6 +60,40 @@ final class Token {
*/
public Token specialToken;
/**
* An optional attribute value of the Token.
* Tokens which are not used as syntactic sugar will often contain
* meaningful values that will be used later on by the compiler or
* interpreter. This attribute value is often different from the image.
* Any subclass of Token that actually wants to return a non-null value can
* override this method as appropriate.
*/
public Object getValue() {
return null;
}
/**
* No-argument constructor
*/
public Token() {}
/**
* Constructs a new token for the specified Image.
*/
public Token(int kind)
{
this(kind, null);
}
/**
* Constructs a new token for the specified Image and Kind.
*/
public Token(int kind, String image)
{
this.kind = kind;
this.image = image;
}
/**
* Returns the image.
*/
@ -64,19 +107,25 @@ final class Token {
* can create and return subclass objects based on the value of ofKind.
* Simply add the cases to the switch for all those special cases.
* For example, if you have a subclass of Token called IDToken that
* you want to create if ofKind is ID, simlpy add something like :
* you want to create if ofKind is ID, simply add something like :
*
* case MyParserConstants.ID : return new IDToken();
* case MyParserConstants.ID : return new IDToken(ofKind, image);
*
* to the following switch statement. Then you can cast matchedToken
* variable to the appropriate type and use it in your lexical actions.
* variable to the appropriate type and use sit in your lexical actions.
*/
public static final Token newToken(int ofKind)
public static Token newToken(int ofKind, String image)
{
switch(ofKind)
{
default : return new Token();
default : return new Token(ofKind, image);
}
}
public static Token newToken(int ofKind)
{
return newToken(ofKind, null);
}
}
/* JavaCC - OriginalChecksum=f683548fa415467062989dfb10c566e6 (do not edit this line) */

View File

@ -1,20 +1,30 @@
/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 3.0 */
/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 4.1 */
/* JavaCCOptions: */
package com.google.gson;
/** Token Manager Error. */
@SuppressWarnings("all")
final class TokenMgrError extends Error
{
/**
* The version identifier for this Serializable class.
* Increment only if the <i>serialized</i> form of the
* class changes.
*/
private static final long serialVersionUID = 1L;
/*
* Ordinals for various reasons why an Error of this type can be thrown.
*/
/**
* Lexical error occured.
* Lexical error occurred.
*/
static final int LEXICAL_ERROR = 0;
/**
* An attempt wass made to create a second instance of a static token manager.
* An attempt was made to create a second instance of a static token manager.
*/
static final int STATIC_LEXER_ERROR = 1;
@ -35,7 +45,7 @@ final class TokenMgrError extends Error
int errorCode;
/**
* Replaces unprintable characters by their espaced (or unicode escaped)
* Replaces unprintable characters by their escaped (or unicode escaped)
* equivalents in the given string
*/
protected static final String addEscapes(String str) {
@ -87,11 +97,11 @@ final class TokenMgrError extends Error
* Returns a detailed message for the Error when it is thrown by the
* token manager to indicate a lexical error.
* Parameters :
* EOFSeen : indicates if EOF caused the lexicl error
* curLexState : lexical state in which this error occured
* errorLine : line number when the error occured
* errorColumn : column number when the error occured
* errorAfter : prefix that was seen before this error occured
* EOFSeen : indicates if EOF caused the lexical error
* curLexState : lexical state in which this error occurred
* errorLine : line number when the error occurred
* errorColumn : column number when the error occurred
* errorAfter : prefix that was seen before this error occurred
* curchar : the offending character
* Note: You can customize the lexical error message by modifying this method.
*/
@ -120,15 +130,19 @@ final class TokenMgrError extends Error
* Constructors of various flavors follow.
*/
/** No arg constructor. */
public TokenMgrError() {
}
/** Constructor with message and reason. */
public TokenMgrError(String message, int reason) {
super(message);
errorCode = reason;
}
/** Full Constructor. */
public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) {
this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason);
}
}
/* JavaCC - OriginalChecksum=f9c23e3fca926dbaf51c810110262be0 (do not edit this line) */

View File

@ -116,20 +116,29 @@ private JsonPrimitive JsonMemberName() :
private JsonArray JsonArray() :
{ JsonArray array = new JsonArray(); }
{
"[" [ Elements(array) ] "]"
{
array.reverse();
return array;
}
"[" (
array=JsonArrayEmpty(array) {return array;} |
JsonArrayElement(array) (JsonArrayNextElement(array))* "]" {return array; } )
}
private void Elements(JsonArray array) :
private JsonArray JsonArrayEmpty(JsonArray array) :
{ }
{
JsonElement element;
"]" { return array; }
}
private JsonArray JsonArrayElement(JsonArray array) :
{ JsonElement element = null; }
{
element=JsonValue() [ "," Elements(array) ]
{ array.add(element); }
element=JsonValue() {array.add(element);}
{ return array; }
}
private JsonArray JsonArrayNextElement(JsonArray array) :
{ JsonElement element = null; }
{
"," element=JsonValue() {array.add(element);}
{ return array; }
}
private JsonElement JsonValue() :

View File

@ -18,6 +18,7 @@ package com.google.gson.functional;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonParseException;
import com.google.gson.common.MoreAsserts;
import com.google.gson.common.TestTypes.BagOfPrimitives;
import com.google.gson.common.TestTypes.CrazyLongTypeAdapter;
@ -55,6 +56,15 @@ public class ArrayTest extends TestCase {
MoreAsserts.assertEquals(expected, actual);
}
public void testInvalidArrayDeserialization() {
String json = "[1, 2 3, 4, 5]";
try {
gson.fromJson(json, int[].class);
fail("Gson should not deserialize array elements with missing ,");
} catch (JsonParseException expected) {
}
}
public void testEmptyArraySerialization() {
int[] target = {};
assertEquals("[]", gson.toJson(target));
@ -66,7 +76,10 @@ public class ArrayTest extends TestCase {
Integer[] actualObject2 = gson.fromJson("[]", Integer[].class);
assertTrue(actualObject2.length == 0);
}
actualObject = gson.fromJson("[ ]", int[].class);
assertTrue(actualObject.length == 0);
}
public void testNullsInArraySerialization() {
String[] array = {"foo", null, "bar"};

View File

@ -117,16 +117,18 @@ public class ObjectTest extends TestCase {
}
public void testClassWithTransientFieldsSerialization() throws Exception {
ClassWithTransientFields target = new ClassWithTransientFields(1L);
ClassWithTransientFields<Long> target = new ClassWithTransientFields<Long>(1L);
assertEquals(target.getExpectedJson(), gson.toJson(target));
}
@SuppressWarnings("unchecked")
public void testClassWithTransientFieldsDeserialization() throws Exception {
String json = "{\"longValue\":[1]}";
ClassWithTransientFields target = gson.fromJson(json, ClassWithTransientFields.class);
assertEquals(json, target.getExpectedJson());
}
@SuppressWarnings("unchecked")
public void testClassWithTransientFieldsDeserializationTransientFieldsPassedInJsonAreIgnored()
throws Exception {
String json = "{\"transientLongValue\":1,\"longValue\":[1]}";

View File

@ -148,9 +148,9 @@ public class PerformanceTest extends TestCase {
/**
* Created in response to http://code.google.com/p/google-gson/issues/detail?id=96
*/
// Last I tested, Gson was able to deserialize a byte array of 80KB
// Last I tested, Gson was able to deserialize a byte array of 11MB
public void disable_testByteArrayDeserialization() {
for (int numElements = 32768; true; numElements += 4096) {
for (int numElements = 10639296; true; numElements += 16384) {
StringBuilder sb = new StringBuilder(numElements*2);
sb.append("[");
boolean first = true;