您的位置:首页 > 移动开发 > Objective-C

自己编写的一个Json工具类,实现了反射将整个Object转换为Json对象的功能,支持Hibernate的延迟加载对象[修订081217]

2008-01-07 17:21 1176 查看
最后更新:09-02-08
bug fix:支持了Hibernate one-to-many映射到List的处理

由于Json自己的String转换有问题,无法正确的转换中文为uxxxx的字符,因此改用DWR包内的JavascriptUtil处理String类型。可以直接引用,还可以拆离出来,因为仅是一个转换工具类,跟DWR的没有依赖关系。这样就可以采用ISO-8859-1编码来传递所有UNICODE了。

代码:

package com.aherp.framework.util;

import org.json.JSONString;

public class JSONStringObject implements JSONString {

private String jsonString = null;

public JSONStringObject(String jsonString){

this.jsonString = jsonString;

}

@Override

public String toString() {

return jsonString;

}

public String toJSONString() {

return jsonString;

}

}

package com.aherp.framework.util;

import java.lang.reflect.Array;

import java.lang.reflect.Method;

import java.util.Calendar;

import java.util.Date;

import java.util.Map;

import java.util.Map.Entry;

import org.json.JSONArray;

import org.json.JSONException;

import org.json.JSONObject;

import org.json.JSONString;

/**

* JSON工具类,反射的方式转换整个对象

* @author Jim Wu

*

*/

public class JSONUtil {

private static JSONUtil instance = null;

public JSONUtil(){}

/**

* 代理类是否输出的检查,返回true则允许继续转换

* @param bean

* @return 是否允许继续转换

*/

protected boolean canProxyOutput(Object bean) {

return true;

}

/**

* 代理类时做的检查.返回应该检查的对象.

* @param bean

* @return 实际获取的对象

*/

protected Object proxyConvert(Object bean){

return bean;

}

static public String toJSONString(Object obj) throws JSONException{

return toJSONString(obj, false);

}

static public String toJSONString(Object obj, boolean useClassConvert) throws JSONException{

if(instance == null)

instance = new JSONUtil();

return instance.getJSONObject(obj, useClassConvert).toString();

}

@SuppressWarnings("unchecked")

private String getJSONArray(Object arrayObj, boolean useClassConvert) throws JSONException{

if(arrayObj == null)

return "null";

arrayObj = proxyConvert(arrayObj);

JSONArray jSONArray = new JSONArray();

if(arrayObj instanceof Iterable){

for(Object rowObj: ((Iterable)arrayObj)){

if(canProxyOutput(rowObj)){

if(rowObj == null)

jSONArray.put(new JSONStringObject(null));

else if(rowObj.getClass().isArray() || rowObj instanceof Iterable)

jSONArray.put(getJSONArray(rowObj, useClassConvert));

else

jSONArray.put(getJSONObject(rowObj, useClassConvert));

}

}

}

if(arrayObj.getClass().isArray()){

int arrayLength = Array.getLength(arrayObj);

for(int i = 0; i < arrayLength; i ++){

Object rowObj = Array.get(arrayObj, i);

if(canProxyOutput(rowObj)){

if(rowObj == null)

jSONArray.put(new JSONStringObject(null));

else if(rowObj.getClass().isArray() || rowObj instanceof Iterable)

jSONArray.put(getJSONArray(rowObj, useClassConvert));

else

jSONArray.put(getJSONObject(rowObj, useClassConvert));

}

}

}

return jSONArray.toString();

}

@SuppressWarnings("unchecked")

JSONStringObject getJSONObject(Object value, boolean useClassConvert) throws JSONException{

//处理原始类型

if (value == null) {

return new JSONStringObject("null");

}

value = proxyConvert(value);

if (value instanceof JSONString) {

Object o;

try {

o = ((JSONString)value).toJSONString();

} catch (Exception e) {

throw new JSONException(e);

}

throw new JSONException("Bad value from toJSONString: " + o);

}

if (value instanceof Number) {

return new JSONStringObject(JSONObject.numberToString((Number) value));

}

if (value instanceof Boolean || value instanceof JSONObject ||

value instanceof JSONArray) {

return new JSONStringObject(value.toString());

}

if (value instanceof String)

return new JSONStringObject('"' + JavascriptUtil.escapeJavaScript(value.toString()) + '"');

if (value instanceof Map) {

JSONObject jSONObject = new JSONObject();

for(Object rowObj: ((Map)value).entrySet()){

Entry entry = (Entry)rowObj;

Object valueObj = entry.getValue();

if(canProxyOutput(valueObj))

jSONObject.put(entry.getKey().toString(), getJSONObject(valueObj, useClassConvert));

}

return new JSONStringObject(jSONObject.toString());

}

if(value instanceof Date){

Calendar calendar = Calendar.getInstance();

calendar.setTime(calendar.getTime());

StringBuilder sb = new StringBuilder("new Date(");

sb.append(calendar.get(Calendar.YEAR));

sb.append(",");

sb.append(calendar.get(Calendar.MONTH));

sb.append(",");

sb.append(calendar.get(Calendar.DAY_OF_MONTH));

sb.append(",");

sb.append(calendar.get(Calendar.HOUR_OF_DAY));

sb.append(",");

sb.append(calendar.get(Calendar.MINUTE));

sb.append(",");

sb.append(calendar.get(Calendar.SECOND));

sb.append(")");

return new JSONStringObject(sb.toString());

}

//class

if(value instanceof Class)

return new JSONStringObject(JavascriptUtil.escapeJavaScript(((Class)value).getSimpleName()));

//数组

if (value instanceof Iterable || value.getClass().isArray()) {

return new JSONStringObject(getJSONArray(proxyConvert(value), useClassConvert));

}

return reflectObject(value, useClassConvert);

}

@SuppressWarnings("unchecked")

private JSONStringObject reflectObject(Object bean, boolean useClassConvert){

JSONObject jSONObject = new JSONObject();

Class klass = bean.getClass();

for (Method method: klass.getMethods()) {

try {

String name = method.getName();

String key = "";

if (name.startsWith("get")) {

key = name.substring(3);

} else if (name.startsWith("is")) {

key = name.substring(2);

}

if (key.length() > 0 &

Character.isUpperCase(key.charAt(0)) &

method.getParameterTypes().length == 0) {

if (key.length() == 1) {

key = key.toLowerCase();

} else if (!Character.isUpperCase(key.charAt(1))) {

key = key.substring(0, 1).toLowerCase() +

key.substring(1);

}

Object elementObj = method.invoke(bean);

if(!useClassConvert && elementObj instanceof Class)

continue;

if(canProxyOutput(elementObj))

jSONObject.put(key, getJSONObject(elementObj, useClassConvert));

}

} catch (Exception e) {

/* forget about it */

}

}

return new JSONStringObject(jSONObject.toString());

}

}

调用测试程序


import java.util.ArrayList;


import java.util.HashMap;


import java.util.List;








public class AObj ...{


private int ii = 7;


private boolean bb = true;


private String ss = "你好";


private List aList = new ArrayList();






public AObj()...{


aList.add("hello");


aList.add(false);


aList.add(new BObj());


aList.add(new HashMap());


}






public boolean isBb() ...{


return bb;


}




public void setBb(boolean bb) ...{


this.bb = bb;


}




public int getIi() ...{


return ii;


}




public void setIi(int ii) ...{


this.ii = ii;


}




public String getSs() ...{


return ss;


}




public void setSs(String ss) ...{


this.ss = ss;


}




public List getAList() ...{


return aList;


}




public void setAList(List list) ...{


aList = list;


}


}




import java.math.BigDecimal;


import java.util.HashMap;








public class BObj ...{




private HashMap innerhm = new HashMap();






public BObj()...{


double dd = 7.4354;


innerhm.put("gigi", "高兴");


innerhm.put("sina", new BigDecimal(dd));


}






public HashMap getInnerhm() ...{


return innerhm;


}






public void setInnerhm(HashMap innerhm) ...{


this.innerhm = innerhm;


}


}








public class CObj extends AObj...{






private Object[] oarray = new Object[]...{352, false, "kick"};






public Object[] getOarray() ...{


return oarray;


}






public void setOarray(Object[] oarray) ...{


this.oarray = oarray;


}


}




import org.json.JSONException;




import com.aherp.framework.util.JSONUtil;






public class Test ...{




public static void main(String[] args) throws JSONException ...{


CObj cObj = new CObj();


System.out.println(JSONUtil.toJSONString(cObj));


}


}





输出:
{"AList":["hello",false,{"innerhm":{"gigi":"/u9AD8/u5174","sina":7.4353999999999995651478457148186862468719482421875}},{}],"ii":7,"oarray":[352,false,"kick"],"ss":"/u4F60/u597D","bb":true}

如果需要支持Hibernate,那么必须弄清其机制。Hibernate采用CGLIB对VO对象进行字节码增加,实际机制就是使用一个原类型的proxy子类,其子类实现了HibernateProxy接口。其接口有一个isUninitialized的判断方法,用来判断该代理类是否已经初始化(还记得在事务外使用延迟加载的对象会抛no Session的错误吗,正是由于实际使用的对象已经变成原来类的子类proxy了)。而对于one-to-many映射时,很难判断对象只加载一次,因此为了避免递归调用死循环,忽略了Hibernate的one-to-many集合的递归反射。其原理和many-to-one一样,也是一个子类化的proxy,具有PersistentSet的接口。

因此,支持Hibernate的JSONUtil如下:

package com.aherp.framework.util;

import org.hibernate.collection.PersistentSet;

import org.hibernate.proxy.HibernateProxy;

import org.hibernate.proxy.LazyInitializer;

import org.json.JSONException;

/**

* 支持Hibernate的JSONUtil.

* 自动检测是否已经代理加载,如果未加载,则将对象仅加载为OID

* @author Jim Wu

*

*/

public class HiJSONUtil extends JSONUtil {

private static HiJSONUtil instance = null;

static public String toJSONString(Object obj) throws JSONException{

return toJSONString(obj, false);

}

static public String toJSONString(Object obj, boolean useClassConvert) throws JSONException{

if(instance == null)

instance = new HiJSONUtil();

return instance.getJSONObject(obj, useClassConvert).toString();

}

@Override

protected Object proxyConvert(Object bean) {

if(bean instanceof HibernateProxy){

LazyInitializer lazyInitializer = ((HibernateProxy)bean).getHibernateLazyInitializer();

if(lazyInitializer.isUninitialized()){

return lazyInitializer.getIdentifier();

}else

return lazyInitializer.getImplementation();

}

if(bean instanceof PersistentSet || bean instanceof PersistentList){

return new String[]{}; //忽略hibernate one-to-many

}

return bean;

}

@Override

protected boolean canProxyOutput(Object bean) {

return !(bean != null && (bean instanceof PersistentSet || bean instanceof PersistentList));

}

}

;

但是这样还是有个问题,当one-to-one具备双向映射关系时,会陷入调用递归死循环。因此避免这样的情况。

将本人修改过的JavaScriptUtil也附上

/*

* Copyright 2005 Joe Walker

*

* 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.

*/

package com.aherp.framework.util;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.StringReader;

import java.util.Arrays;

import java.util.Locale;

import java.util.SortedSet;

import java.util.TreeSet;

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

/**

* Various Javascript code utilities.

* The escape classes were taken from jakarta-commons-lang which in turn borrowed

* from Turbine and other projects. The list of authors below is almost certainly

* far too long, but I'm not sure who really wrote these methods.

* @author Joe Walker [joe at getahead dot ltd dot uk]

* @author Apache Jakarta Turbine

* @author GenerationJavaCore library

* @author Purple Technology

* @author <a href="mailto:bayard@generationjava.com">Henri Yandell</a>

* @author <a href="mailto:alex@purpletech.com">Alexander Day Chaffee</a>

* @author <a href="mailto:cybertiger@cyberiantiger.org">Antony Riley</a>

* @author Helge Tesgaard

* @author <a href="sean@boohai.com">Sean Brown</a>

* @author <a href="mailto:ggregory@seagullsw.com">Gary Gregory</a>

* @author Phil Steitz

* @author Pete Gieser

*/

@SuppressWarnings("unchecked")

public class JavascriptUtil

{

/**

* Flag for use in javascript compression: Remove single line comments.

* For ease of use you may wish to use one of the LEVEL_* compression levels.

* @noinspection PointlessBitwiseExpression

*/

public static final int COMPRESS_STRIP_SL_COMMENTS = 1 << 0;

/**

* Flag for use in javascript compression: Remove multi line comments.

* For ease of use you may wish to use one of the LEVEL_* compression levels.

*/

public static final int COMPRESS_STRIP_ML_COMMENTS = 1 << 1;

/**

* Flag for use in javascript compression: Remove whitespace at the start and end of a line.

* For ease of use you may wish to use one of the LEVEL_* compression levels.

*/

public static final int COMPRESS_TRIM_LINES = 1 << 2;

/**

* Flag for use in javascript compression: Remove blank lines.

* This option will make the javascript harder to debug because line number references

* are likely be altered.

* For ease of use you may wish to use one of the LEVEL_* compression levels.

*/

public static final int COMPRESS_STRIP_BLANKLINES = 1 << 3;

/**

* Flag for use in javascript compression: Shrink variable names.

* This option is currently un-implemented.

* For ease of use you may wish to use one of the LEVEL_* compression levels.

*/

public static final int COMPRESS_SHRINK_VARS = 1 << 4;

/**

* Flag for use in javascript compression: Remove all lines endings.

* Warning: Javascript can add semi-colons in for you. If you make use of this feature

* then removing newlines may well break.

* For ease of use you may wish to use one of the LEVEL_* compression levels.

*/

public static final int COMPRESS_REMOVE_NEWLINES = 1 << 5;

/**

* Compression level that leaves the source un-touched.

*/

public static final int LEVEL_NONE = 0;

/**

* Basic compression that leaves the source fully debuggable.

* This includes removing all comments and extraneous whitespace.

*/

public static final int LEVEL_DEBUGGABLE = COMPRESS_STRIP_SL_COMMENTS | COMPRESS_STRIP_ML_COMMENTS | COMPRESS_TRIM_LINES;

/**

* Normal compression makes all changes that will work for generic javascript.

* This adds variable name compression and blank line removal in addition to the

* compressions done by LEVEL_DEBUGGABLE.

*/

public static final int LEVEL_NORMAL = LEVEL_DEBUGGABLE | COMPRESS_STRIP_BLANKLINES | COMPRESS_SHRINK_VARS;

/**

* LEVEL_ULTRA performs additional compression that makes some assumptions about the

* style of javascript.

* Specifically it assumes that you are not using javascripts ability to infer where the ;

* should go.

*/

public static final int LEVEL_ULTRA = LEVEL_NORMAL | COMPRESS_REMOVE_NEWLINES;

/**

* Compress the source code by removing java style comments and removing

* leading and trailing spaces.

* @param text The javascript (or java) program to compress

* @param level The compression level - see LEVEL_* and COMPRESS_* constants.

* @return The compressed version

*/

public static String compress(String text, int level)

{

String reply = text;

// First we strip multi line comments. I think this is important:

if ((level & COMPRESS_STRIP_ML_COMMENTS) != 0)

{

reply = stripMultiLineComments(text);

}

if ((level & COMPRESS_STRIP_SL_COMMENTS) != 0)

{

reply = stripSingleLineComments(reply);

}

if ((level & COMPRESS_TRIM_LINES) != 0)

{

reply = trimLines(reply);

}

if ((level & COMPRESS_STRIP_BLANKLINES) != 0)

{

reply = stripBlankLines(reply);

}

if ((level & COMPRESS_SHRINK_VARS) != 0)

{

reply = shrinkVariableNames(reply);

}

if ((level & COMPRESS_REMOVE_NEWLINES) != 0)

{

reply = stripNewlines(reply);

}

return reply;

}

/**

* Remove any leading or trailing spaces from a line of code.

* This function could be improved by making it strip unnecessary double

* spaces, but since we would need to leave double spaces inside strings

* this is not simple and since the benefit is small, we'll leave it for now

* @param text The javascript program to strip spaces from.

* @return The stripped program

*/

public static String trimLines(String text)

{

if (text == null)

{

return null;

}

try

{

StringBuffer output = new StringBuffer();

// First we strip multi line comments. I think this is important:

BufferedReader in = new BufferedReader(new StringReader(text));

while (true)

{

String line = in.readLine();

if (line == null)

{

break;

}

output.append(line.trim());

output.append('/n');

}

return output.toString();

}

catch (IOException ex)

{

log.error("IOExecption unexpected.", ex);

throw new IllegalArgumentException("IOExecption unexpected.");

}

}

/**

* Remove all the single-line comments from a block of text

* @param text The text to remove single-line comments from

* @return The single-line comment free text

*/

public static String stripSingleLineComments(String text)

{

if (text == null)

{

return null;

}

try

{

StringBuffer output = new StringBuffer();

BufferedReader in = new BufferedReader(new StringReader(text));

while (true)

{

String line = in.readLine();

if (line == null)

{

break;

}

// Skip @DWR comments

if (line.indexOf(COMMENT_RETAIN) == -1)

{

int cstart = line.indexOf(COMMENT_SL_START);

if (cstart >= 0)

{

line = line.substring(0, cstart);

}

}

output.append(line);

output.append('/n');

}

return output.toString();

}

catch (IOException ex)

{

log.error("IOExecption unexpected.", ex);

throw new IllegalArgumentException("IOExecption unexpected.");

}

}

/**

* Remove all the multi-line comments from a block of text

* @param text The text to remove multi-line comments from

* @return The multi-line comment free text

*/

public static String stripMultiLineComments(String text)

{

if (text == null)

{

return null;

}

try

{

StringBuffer output = new StringBuffer();

// Comment rules:

/*/ This is still a comment

/* /* */ // Comments do not nest

// /* */ This is in a comment

/* // */ // The second // is needed to make this a comment.

// First we strip multi line comments. I think this is important:

boolean inMultiLine = false;

BufferedReader in = new BufferedReader(new StringReader(text));

while (true)

{

String line = in.readLine();

if (line == null)

{

break;

}

if (!inMultiLine)

{

// We are not in a multi-line comment, check for a start

int cstart = line.indexOf(COMMENT_ML_START);

if (cstart >= 0)

{

// This could be a MLC on one line ...

int cend = line.indexOf(COMMENT_ML_END, cstart + COMMENT_ML_START.length());

if (cend >= 0)

{

// A comment that starts and ends on one line

// BUG: you can have more than 1 multi-line comment on a line

line = line.substring(0, cstart) + SPACE + line.substring(cend + COMMENT_ML_END.length());

}

else

{

// A real multi-line comment

inMultiLine = true;

line = line.substring(0, cstart) + SPACE;

}

}

else

{

// We are not in a multi line comment and we havn't

// started one so we are going to ignore closing

// comments even if they exist.

}

}

else

{

// We are in a multi-line comment, check for the end

int cend = line.indexOf(COMMENT_ML_END);

if (cend >= 0)

{

// End of comment

line = line.substring(cend + COMMENT_ML_END.length());

inMultiLine = false;

}

else

{

// The comment continues

line = SPACE;

}

}

output.append(line);

output.append('/n');

}

return output.toString();

}

catch (IOException ex)

{

log.error("IOExecption unexpected.", ex);

throw new IllegalArgumentException("IOExecption unexpected.");

}

}

/**

* Remove all blank lines from a string.

* A blank line is defined to be a line where the only characters are whitespace.

* We always ensure that the line contains a newline at the end.

* @param text The string to strip blank lines from

* @return The blank line stripped reply

*/

public static String stripBlankLines(String text)

{

if (text == null)

{

return null;

}

try

{

StringBuffer output = new StringBuffer();

BufferedReader in = new BufferedReader(new StringReader(text));

boolean doneOneLine = false;

while (true)

{

String line = in.readLine();

if (line == null)

{

break;

}

if (line.trim().length() > 0)

{

output.append(line);

output.append('/n');

doneOneLine = true;

}

}

if (!doneOneLine)

{

output.append('/n');

}

return output.toString();

}

catch (IOException ex)

{

log.error("IOExecption unexpected.", ex);

throw new IllegalArgumentException("IOExecption unexpected.");

}

}

/**

* Remove all newline characters from a string.

* @param text The string to strip newline characters from

* @return The stripped reply

*/

public static String stripNewlines(String text)

{

if (text == null)

{

return null;

}

try

{

StringBuffer output = new StringBuffer();

BufferedReader in = new BufferedReader(new StringReader(text));

while (true)

{

String line = in.readLine();

if (line == null)

{

break;

}

output.append(line);

output.append(SPACE);

}

output.append('/n');

return output.toString();

}

catch (IOException ex)

{

log.error("IOExecption unexpected.", ex);

throw new IllegalArgumentException("IOExecption unexpected.");

}

}

/**

* Shrink variable names to a minimum.

* @param text The javascript program to shrink the variable names in.

* @return The shrunk version of the javascript program.

*/

public static String shrinkVariableNames(String text)

{

if (text == null)

{

return null;

}

throw new UnsupportedOperationException("Variable name shrinking is not supported");

}

/**

* <p>Escapes the characters in a <code>String</code> using JavaScript String rules.</p>

* <p>Escapes any values it finds into their JavaScript String form.

* Deals correctly with quotes and control-chars (tab, backslash, cr, ff, etc.) </p>

*

* <p>So a tab becomes the characters <code>'//'</code> and

* <code>'t'</code>.</p>

*

* <p>The only difference between Java strings and JavaScript strings

* is that in JavaScript, a single quote must be escaped.</p>

*

* <p>Example:

* <pre>

* input string: He didn't say, "Stop!"

* output string: He didn/'t say, /"Stop!/"

* </pre>

* </p>

*

* @param str String to escape values in, may be null

* @return String with escaped values, <code>null</code> if null string input

*/

public static String escapeJavaScript(String str)

{

if (str == null)

{

return null;

}

StringBuffer writer = new StringBuffer(str.length() * 2);

int sz = str.length();

for (int i = 0; i < sz; i++)

{

char ch = str.charAt(i);

// handle unicode

if (ch > 0xfff)

{

writer.append("//u");

writer.append(hex(ch));

}

else if (ch > 0xff)

{

writer.append("//u0");

writer.append(hex(ch));

}

else if (ch > 0x7f)

{

writer.append("//u00");

writer.append(hex(ch));

}

else if (ch < 32)

{

switch (ch)

{

case '/b':

writer.append('//');

writer.append('b');

break;

case '/n':

writer.append('//');

writer.append('n');

break;

case '/t':

writer.append('//');

writer.append('t');

break;

case '/f':

writer.append('//');

writer.append('f');

break;

case '/r':

writer.append('//');

writer.append('r');

break;

default:

if (ch > 0xf)

{

writer.append("//u00");

writer.append(hex(ch));

}

else

{

writer.append("//u000");

writer.append(hex(ch));

}

break;

}

}

else

{

switch (ch)

{

case '/'':

// If we wanted to escape for Java strings then we would

// not need this next line.

writer.append('//');

writer.append('/'');

break;

case '"':

writer.append('//');

writer.append('"');

break;

case '//':

writer.append('//');

writer.append('//');

break;

case '<':

writer.append("//u003c");

break;

case '>':

writer.append("//u003e");

break;

default:

writer.append(ch);

break;

}

}

}

return writer.toString();

}

/**

* <p>Returns an upper case hexadecimal <code>String</code> for the given

* character.</p>

* @param ch The character to convert.

* @return An upper case hexadecimal <code>String</code>

*/

private static String hex(char ch)

{

return Integer.toHexString(ch).toUpperCase(Locale.ENGLISH);

}

/**

* <p>Unescapes any JavaScript literals found in the <code>String</code>.</p>

* <p>For example, it will turn a sequence of <code>'/'</code> and <code>'n'</code>

* into a newline character, unless the <code>'/'</code> is preceded by another

* <code>'/'</code>.</p>

* @param str the <code>String</code> to unescape, may be null

* @return A new unescaped <code>String</code>, <code>null</code> if null string input

*/

public static String unescapeJavaScript(String str)

{

if (str == null)

{

return null;

}

StringBuffer writer = new StringBuffer(str.length());

int sz = str.length();

StringBuffer unicode = new StringBuffer(4);

boolean hadSlash = false;

boolean inUnicode = false;

for (int i = 0; i < sz; i++)

{

char ch = str.charAt(i);

if (inUnicode)

{

// if in unicode, then we're reading unicode

// values in somehow

unicode.append(ch);

if (unicode.length() == 4)

{

// unicode now contains the four hex digits

// which represents our unicode chacater

try

{

int value = Integer.parseInt(unicode.toString(), 16);

writer.append((char) value);

unicode.setLength(0);

inUnicode = false;

hadSlash = false;

}

catch (NumberFormatException nfe)

{

throw new IllegalArgumentException("Unable to parse unicode value: " + unicode + " cause: " + nfe);

}

}

continue;

}

if (hadSlash)

{

// handle an escaped value

hadSlash = false;

switch (ch)

{

case '//':

writer.append('//');

break;

case '/'':

writer.append('/'');

break;

case '/"':

writer.append('"');

break;

case 'r':

writer.append('/r');

break;

case 'f':

writer.append('/f');

break;

case 't':

writer.append('/t');

break;

case 'n':

writer.append('/n');

break;

case 'b':

writer.append('/b');

break;

case 'u':

// uh-oh, we're in unicode country....

inUnicode = true;

break;

default:

writer.append(ch);

break;

}

continue;

}

else if (ch == '//')

{

hadSlash = true;

continue;

}

writer.append(ch);

}

if (hadSlash)

{

// then we're in the weird case of a / at the end of the

// string, let's output it anyway.

writer.append('//');

}

return writer.toString();

}

/**

* Check to see if the given word is reserved or a bad idea in any known

* version of JavaScript.

* @param name The word to check

* @return false if the word is not reserved

*/

public static boolean isReservedWord(String name)

{

return reserved.contains(name);

}

/**

* The array of javascript reserved words

*/

private static final String[] RESERVED_ARRAY = new String[]

{

// Reserved and used at ECMAScript 4

"as",

"break",

"case",

"catch",

"class",

"const",

"continue",

"default",

"delete",

"do",

"else",

"export",

"extends",

"false",

"finally",

"for",

"function",

"if",

"import",

"in",

"instanceof",

"is",

"namespace",

"new",

"null",

"package",

"private",

"public",

"return",

"super",

"switch",

"this",

"throw",

"true",

"try",

"typeof",

"use",

"var",

"void",

"while",

"with",

// Reserved for future use at ECMAScript 4

"abstract",

"debugger",

"enum",

"goto",

"implements",

"interface",

"native",

"protected",

"synchronized",

"throws",

"transient",

"volatile",

// Reserved in ECMAScript 3, unreserved at 4 best to avoid anyway

"boolean",

"byte",

"char",

"double",

"final",

"float",

"int",

"long",

"short",

"static",

// I have seen the folowing list as 'best avoided for function names'

// but it seems way to all encompassing, so I'm not going to include it

/*

"alert", "anchor", "area", "arguments", "array", "assign", "blur",

"boolean", "button", "callee", "caller", "captureevents", "checkbox",

"clearinterval", "cleartimeout", "close", "closed", "confirm",

"constructor", "date", "defaultstatus", "document", "element", "escape",

"eval", "fileupload", "find", "focus", "form", "frame", "frames",

"getclass", "hidden", "history", "home", "image", "infinity",

"innerheight", "isfinite", "innerwidth", "isnan", "java", "javaarray",

"javaclass", "javaobject", "javapackage", "length", "link", "location",

"locationbar", "math", "menubar", "mimetype", "moveby", "moveto",

"name", "nan", "navigate", "navigator", "netscape", "number", "object",

"onblur", "onerror", "onfocus", "onload", "onunload", "open", "opener",

"option", "outerheight", "outerwidth", "packages", "pagexoffset",

"pageyoffset", "parent", "parsefloat", "parseint", "password",

"personalbar", "plugin", "print", "prompt", "prototype", "radio", "ref",

"regexp", "releaseevents", "reset", "resizeby", "resizeto",

"routeevent", "scroll", "scrollbars", "scrollby", "scrollto", "select",

"self", "setinterval", "settimeout", "status", "statusbar", "stop",

"string", "submit", "sun", "taint", "text", "textarea", "toolbar",

"top", "tostring", "unescape", "untaint", "unwatch", "valueof", "watch",

"window",

*/

};

private static SortedSet reserved = new TreeSet();

/**

* For easy access ...

*/

static

{

// The Javascript reserved words array so we don't generate illegal javascript

reserved.addAll(Arrays.asList(RESERVED_ARRAY));

}

private static final String SPACE = " ";

/**

* How does a multi line comment start?

*/

private static final String COMMENT_ML_START = "/*";

/**

* How does a multi line comment end?

*/

private static final String COMMENT_ML_END = "*/";

/**

* How does a single line comment start?

*/

private static final String COMMENT_SL_START = "//";

/**

* Sometimes we need to retain the comment because it has special meaning

*/

private static final String COMMENT_RETAIN = "#DWR";

/**

* The log stream

*/

private static final Log log = LogFactory.getLog(JavascriptUtil.class);

}

需要的JSON类我已经放到共享,你可以从
http://download.csdn.net/source/879579

下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐