Skip to content

Commit

Permalink
bugfix string quoting
Browse files Browse the repository at this point in the history
  • Loading branch information
kasperjj committed Apr 20, 2017
1 parent d2084c8 commit dd556ad
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 33 deletions.
14 changes: 12 additions & 2 deletions src/main/java/me/doubledutch/lazyjson/LazyArray.java
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,12 @@ private void insertChild(int index,LazyNode token) throws LazyException{
}

public LazyArray put(String value) throws LazyException{
LazyNode child=appendAndSetDirtyString(LazyNode.VALUE_STRING,value);
LazyNode child=null;
if(shouldQuoteString(value)){
child=appendAndSetDirtyString(LazyNode.VALUE_ESTRING,quoteString(value));
}else{
child=appendAndSetDirtyString(LazyNode.VALUE_STRING,value);
}
appendChild(child);
return this;
}
Expand Down Expand Up @@ -279,7 +284,12 @@ public LazyArray put(LazyObject value) throws LazyException{
}

public LazyArray put(int index,String value) throws LazyException{
LazyNode child=appendAndSetDirtyString(LazyNode.VALUE_STRING,value);
LazyNode child=null;
if(shouldQuoteString(value)){
child=appendAndSetDirtyString(LazyNode.VALUE_ESTRING,quoteString(value));
}else{
child=appendAndSetDirtyString(LazyNode.VALUE_STRING,value);
}
insertChild(index,child);
return this;
}
Expand Down
59 changes: 59 additions & 0 deletions src/main/java/me/doubledutch/lazyjson/LazyElement.java
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,65 @@ public static LazyElement parse(String str) throws LazyException{
throw new LazyException("The given string is not a JSON object or array");
}

protected static boolean shouldQuoteString(String str){
boolean found=false;
int length=str.length();
char[] cbuf=new char[length];
str.getChars(0,length,cbuf,0);
for(int i=0;i<length;i++){
char c=cbuf[i];
if(c=='\\' || c=='"' || c=='\b' || c=='\t' || c=='\n' || c=='\f' || c=='\r'){// || c<' ' || (c>= '\u0080' && c<'\u00a0') || (c>='\u2000' && c<'\u2100')){
found=true;
}
}
return found;
}

protected static String quoteString(String str){
StringBuffer buf=new StringBuffer();
int length=str.length();
char[] cbuf=new char[length];
str.getChars(0,length,cbuf,0);

for(int i=0; i<length; i++){
char c=cbuf[i];
switch(c){
case '\\':
buf.append("\\\\");
break;
case '"':
buf.append('\\');
buf.append(c);
break;
case '\b':
buf.append("\\b");
break;
case '\t':
buf.append("\\t");
break;
case '\n':
buf.append("\\n");
break;
case '\f':
buf.append("\\f");
break;
case '\r':
buf.append("\\r");
break;
default:
/*
We shouldn't need to encode special characters other than the above, all others should be handled by utf-8 encoding
if(c<' ' || (c>= '\u0080' && c<'\u00a0') || (c>='\u2000' && c<'\u2100')){
String tmp="000"+Integer.toHexString(c);
buf.append("\\u"+tmp.substring(tmp.length()-4));
}else{*/
buf.append(c);
//}
}
}
return buf.toString();
}

public static LazyElement readFromTemplate(Template t,ByteBuffer buf,DictionaryCache dict) throws LazyException{
String str=t.read(buf,dict);
// System.out.println(str);
Expand Down
87 changes: 62 additions & 25 deletions src/main/java/me/doubledutch/lazyjson/LazyNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -346,38 +346,71 @@ protected String getStringValue(char[] source,StringBuilder dirtyBuf){
return new String(source,startIndex,endIndex-startIndex);
}else{
StringBuilder buf=new StringBuilder(endIndex-startIndex);
for(int i=startIndex;i<endIndex;i++){
char c=source[i];
if(c=='\\'){
i++;
c=source[i];
if(c=='"' || c=='\\' || c=='/'){
if(dirty){
for(int i=startIndex;i<endIndex;i++){
char c=dirtyBuf.charAt(i);
if(c=='\\'){
i++;
c=dirtyBuf.charAt(i);
if(c=='"' || c=='\\' || c=='/'){
buf.append(c);
}else if(c=='b'){
buf.append('\b');
}else if(c=='f'){
buf.append('\f');
}else if(c=='n'){
buf.append('\n');
}else if(c=='r'){
buf.append('\r');
}else if(c=='t'){
buf.append('\t');
}else if(c=='u'){
String code=dirtyBuf.substring(i+1,i+5);
buf.append((char)Integer.parseInt(code, 16));
i+=4;
}
}else{
buf.append(c);
}
}
}else{
for(int i=startIndex;i<endIndex;i++){
char c=source[i];
if(c=='\\'){
i++;
c=source[i];
if(c=='"' || c=='\\' || c=='/'){
buf.append(c);
}else if(c=='b'){
buf.append('\b');
}else if(c=='f'){
buf.append('\f');
}else if(c=='n'){
buf.append('\n');
}else if(c=='r'){
buf.append('\r');
}else if(c=='t'){
buf.append('\t');
}else if(c=='u'){
String code=new String(source,i+1,4);
buf.append((char)Integer.parseInt(code, 16));
i+=4;
}
}else{
buf.append(c);
}else if(c=='b'){
buf.append('\b');
}else if(c=='f'){
buf.append('\f');
}else if(c=='n'){
buf.append('\n');
}else if(c=='r'){
buf.append('\r');
}else if(c=='t'){
buf.append('\t');
}else if(c=='u'){
String code=new String(source,i+1,4);
buf.append((char)Integer.parseInt(code, 16));
i+=4;
}
}else{
buf.append(c);
}
}
return buf.toString();
}
}

private String getRawStringValue(char[] source){
return new String(source,startIndex,endIndex-startIndex);
protected String getRawStringValue(char[] source,StringBuilder dirtyBuf){
if(dirty){
return dirtyBuf.substring(startIndex,endIndex);
}else{
return new String(source,startIndex,endIndex-startIndex);
}
}

/**
Expand Down Expand Up @@ -464,7 +497,11 @@ private void addCommaSeparatedChildren(char[] cbuf,Template template){
}

private String getFieldString(char[] cbuf){
return "\""+getRawStringValue(cbuf)+"\":";
return "\""+getRawStringValue(cbuf,null)+"\":";
}

private String getFieldString(char[] cbuf,StringBuilder dirtyBuf){
return "\""+getRawStringValue(cbuf,dirtyBuf)+"\":";
}

private void putString(char[] cbuf,ByteBuffer buf,DictionaryCache dict){
Expand Down
10 changes: 7 additions & 3 deletions src/main/java/me/doubledutch/lazyjson/LazyObject.java
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ protected String serializeElementToString(){
buf.append(new LazyArray(pointer.child,cbuf,dirtyBuf).toString());
}else if(pointer.child.type==LazyNode.VALUE_STRING || pointer.child.type==LazyNode.VALUE_ESTRING){
buf.append("\"");
buf.append(pointer.child.getStringValue(cbuf,dirtyBuf));
buf.append(pointer.child.getRawStringValue(cbuf,dirtyBuf));
buf.append("\"");
}else if(pointer.child.type==LazyNode.VALUE_TRUE){
buf.append("true");
Expand Down Expand Up @@ -196,8 +196,12 @@ private void attachField(String key,LazyNode child) throws LazyException{
}

public LazyObject put(String key,String value) throws LazyException{
// TODO: correctly detect and encode string values
LazyNode child=appendAndSetDirtyString(LazyNode.VALUE_STRING,value);
LazyNode child=null;
if(shouldQuoteString(value)){
child=appendAndSetDirtyString(LazyNode.VALUE_ESTRING,quoteString(value));
}else{
child=appendAndSetDirtyString(LazyNode.VALUE_STRING,value);
}
attachField(key,child);
return this;
}
Expand Down
6 changes: 3 additions & 3 deletions src/main/resources/lazyjson_version.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#Thu Apr 20 15:00:53 PDT 2017
#Thu Apr 20 16:23:24 PDT 2017
BUILD_VERSION=2.0.0
BUILD_DATE=2017-04-20T22\:00\:53Z
BUILD_NUMBER=900
BUILD_DATE=2017-04-20T23\:23\:24Z
BUILD_NUMBER=937
10 changes: 10 additions & 0 deletions src/test/java/me/doubledutch/lazyjson/ModifyTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@ public void addStringTest() throws LazyException{
assertEquals(obj.toString(),"{\"foo\":\"bar\",\"baz\":42,\"test\":\"Hello World\"}");
}

@Test
public void addComplexStringTest() throws LazyException{
String str="{\"foo\":\"bar\",\"baz\":42}";
LazyObject obj=new LazyObject(str);
obj.put("test","Hello \n\t\r\b\"\\\f World");
assertEquals(obj.getString("test"),"Hello \n\t\r\b\"\\\f World");
assertEquals(obj.getString("foo"),"bar");
assertEquals(obj.toString(),"{\"foo\":\"bar\",\"baz\":42,\"test\":\"Hello \\n\\t\\r\\b\\\"\\\\\\f World\"}");
}

@Test
public void buildObjectTest() throws LazyException{
LazyObject obj=new LazyObject();
Expand Down

0 comments on commit dd556ad

Please sign in to comment.