1. 程式人生 > >json格式資料的封裝與使用

json格式資料的封裝與使用

json格式資料的使用

解析Json資料用到的Jar包 json.jar 與 json-lib-2.4-jdk15.jar

Json資料格式的封裝

		//一個Json物件
		// String resultJson="{\"name\":\"張三\",\"age\":22}";
		JSONObject resultJson=new JSONObject();
		resultJson.put("name", "張三");
		resultJson.put("age", 22);
		//Json陣列
		JSONObject resultJson=new JSONObject();
		JSONArray jsonArray=new JSONArray();
		JSONObject jsonObject1=new JSONObject();
		jsonObject1.put("name", "張三");
		jsonObject1.put("age", 22);
		JSONObject jsonObject2=new JSONObject();
		jsonObject2.put("name", "李四");
		jsonObject2.put("age", 23);
		JSONObject jsonObject3=new JSONObject();
		jsonObject3.put("name", "王五");
		jsonObject3.put("age", 24);
		jsonArray.add(jsonObject1);
		jsonArray.add(jsonObject2);
		jsonArray.add(jsonObject3);
		
		//Json巢狀
		JSONObject resultJson=new JSONObject();
		JSONArray jsonArray=new JSONArray();
		JSONObject jsonObject1=new JSONObject();
		jsonObject1.put("name", "張三");
		jsonObject1.put("age", 22);
		
		JSONObject scoreObject1=new JSONObject();
		scoreObject1.put("chinese", 90);
		scoreObject1.put("math", 100);
		scoreObject1.put("english", 80);
		jsonObject1.put("score", scoreObject1);
		
		JSONObject jsonObject2=new JSONObject();
		jsonObject2.put("name", "李四");
		jsonObject2.put("age", 23);
		
		JSONObject scoreObject2=new JSONObject();
		scoreObject2.put("chinese", 70);
		scoreObject2.put("math", 90);
		scoreObject2.put("english", 90);
		jsonObject2.put("score", scoreObject2);
		
		JSONObject jsonObject3=new JSONObject();
		jsonObject3.put("name", "王五");
		jsonObject3.put("age", 24);
		
		JSONObject scoreObject3=new JSONObject();
		scoreObject3.put("chinese", 80);
		scoreObject3.put("math", 60);
		scoreObject3.put("english", 90);
		jsonObject3.put("score", scoreObject3);
		
		jsonArray.add(jsonObject1);
		jsonArray.add(jsonObject2);
		jsonArray.add(jsonObject3);
		
		resultJson.put("students", jsonArray);

import com.platform.util.json.JSONException;
import com.platform.util.json.JSONObject;
var strwhere = "recordType:\""+recordType+"\",recordId:\""+ids+"\",isRecord:\""+isRecord;
		strwhere+="\"";

private JSONObject objWhere = null;
try {
objWhere = new JSONObject("{" + strWhere + "}");
} catch (JSONException e) {}

try {
String recordType= objWhere.getString("recordType");
String isRecord= objWhere.getString("isRecord");
}
} catch (JSONException e) {
e.printStackTrace();
}

$.toJSON(data) 與jQuery.parseJSON(data);

//數組裡的欄位的命名和型別要和一般處理程式裡定義的類裡的變數要一樣
//否則會出問題
var postdata = new Array();
postdata[1] = { id: 1, number: "yes" };
postdata[2] = { id: 2, number: "no" };
var postData = $.toJSON(postdata);  //把陣列轉換成json字串
//將json字串反序列化,這個只是測試一下陣列是否轉換成json字串
var content = $.parseJSON(postData);
$.each(content, function () {
   alert(this.number);
 });

$.parseJSON() 函式用於將符合標準格式的的JSON字串轉為與之對應的JavaScript物件。可以將json字串轉換成json物件 

var cookieuser;
 try {
  cookieuser = $.parseJSON(cookieData);
  } catch (e) {
  //window.location.href = TIMEOUT_PATH;
    return {};
  }

將資料封裝為JSON字串

delBef: function(curDom, event){
		var _self = this;
		var data = _self.getSelectIds();
		if(data.length == 0){
			layer.msg("請至少選擇一條需要刪除的資料");
			return;
		}
		var url = $(curDom).attr("url") + "?act=" + WebConst.DELETE;
		layer.confirm('確定刪除嗎', function(index){			
			var dataArr = new Array();
			var Row = _self.getSelectRows();
			for(var i=0;i<Row.length;i++)
			{
				var adviceData = new Object(); 
				adviceData.adviceFlowId = Row[i].adviceFlowId;
				adviceData.companyId = Row[i].companyId;
				dataArr.push(adviceData);
			}
			var checkUrl = CONTEXT_PATH +"/advice/beforeDel"
			var param ={
					"JsonArray":$.toJSON(dataArr)//把陣列轉換成json字串
			}
			var retData  = $.getData(checkUrl,param);
			if(retData.status==-1000 ){
				return layer.msg("無法進行刪除");
				return;
			}else{
				$.ajaxReq(url,$.toJSON(data),function(){
					layui.table.reload(_self.tableId)
				});
				return layer.msg("刪除成功");
			}
			layer.close(index);
			
		});
	}

後臺接收前臺的JSON字串並解析


	@RequestMapping("/advice/beforeDel")
	@ResponseBody
	public AssembleJSON beforedeleteAdvice(String JsonArray)
	{	 
		
		List<Advice> adviceList = JSON.parseArray(JsonArray, Advice.class);
		for(Advice advice:adviceList) {
			String adviceFlowId =advice.getAdviceFlowId();
			String companyId = advice.getCompanyId();
			AdviceFLowNodeVO upFLowNodeVO = new AdviceFLowNodeVO();
			upFLowNodeVO.setAdviceFlowId(adviceFlowId);
			upFLowNodeVO.setCompanyId(companyId);
			AdviceFLowNodeVO adviceFLowNodeVO = new AdviceFLowNodeVO();
			if(null!=adviceFlowId) {
				 adviceFLowNodeVO = adviceFlowNodeService.getUpAdvice(upFLowNodeVO);	
			}else {
				adviceFLowNodeVO = null;
			}
			if(null!=adviceFLowNodeVO) {
				String status = adviceFLowNodeVO.getAdviceStatus();
				if("1".equals(status)||"2".equals(status)) {
					return AssembleJSON.FAILURE("已經提交公開不能刪除");
				}
			}
		}
		
		return AssembleJSON.SUCCESS;

	}

js物件轉json字串

params = {}
params.attachmentIds = uploadAttachmentIds.join(",");
JSON.stringify(params)

json字串轉js物件

var imgs = JSON.parse(readCookie("Imges"));

JSON.parse() 方法用來解析JSON字串,構造由字串描述的JavaScript值或物件。可以將json字串轉換成json物件

var json = '{"result":true, "count":42}';
obj = JSON.parse(json);

console.log(obj.count);
// expected output: 42

console.log(obj.result);
// expected output: true

form序列化轉json

   serializeJson:function(){    
        var serializeObj = {};    
        var array = this.serializeArray();    
        var str = this.serialize();    
        $(array).each(function(){    
            if(serializeObj[this.name]){    
                if($.isArray(serializeObj[this.name])){    
                    serializeObj[this.name].push(this.value);    
                }else{    
                    serializeObj[this.name]=[serializeObj[this.name],this.value];    
                }    
            }else{    
                serializeObj[this.name]=this.value;     
            }    
        });    
        return serializeObj;    
    } 

java使用fastJson進行物件和json字串轉換

import com.alibaba.fastjson.JSON;

Object[] arguments = joinPoint.getArgs();
//[{logType=0, businessId=5952e48d1dec1c2ea, userId=6b005881d00e239d}]

//轉為json字串
String params = JSON.toJSONString(arguments[0]);
//{"logType":"0","businessId":"5952e48d1dec1c2ea","userId":"6b005881d00e239d"}

//獲取物件
AccessLogVO log = JSON.parseObject(params, AccessLogVO.class);
log.setReadTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
return log;

java的json字串轉string

	public static String transJsonToString(String json)
	{
		String s = json.replaceAll("\\{\"","{'") // {"  --> {'
	            .replaceAll("\":\"", "':'")     // ":" --> ':'
	            .replaceAll("\",\"", "','")     // "," --> ','
	            .replaceAll("\":", "':")        // ":  --> ':
	            .replaceAll(",\"", ",'")        // ,"  --> ,'
	            .replaceAll("\"\\}", "'}")      // "}  --> '}
	            .replaceAll("\"", "")           // "   --> 空,以去掉字串中間的引號
	            .replaceAll("'", "\"")          // '   --> ",所有的單引號替換回雙引號
	            .replaceAll("<br />", "")       // 去掉字串中的<br />
	            .replaceAll("\\\\", "?");       // 字串中含\也會導致解析失敗
		
		return s;
		
	}

json轉換工具類的使用

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.introspect.Annotated;
import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;
import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
import java.io.IOException;
import java.lang.reflect.AnnotatedElement;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Component;

@Component
public class JsonUtil
{
  private static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
  private static final ObjectMapper mapper;
  
  public ObjectMapper getMapper()
  {
    return mapper;
  }
  
  static
  {
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    
    mapper = new ObjectMapper();
    mapper.setDateFormat(dateFormat);
    mapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector()
    {
      public Object findSerializer(Annotated a)
      {
        if ((a instanceof AnnotatedMethod))
        {
          AnnotatedElement m = a.getAnnotated();
          DateTimeFormat an = (DateTimeFormat)m.getAnnotation(DateTimeFormat.class);
          if ((an != null) && 
            (!"yyyy-MM-dd HH:mm:ss".equals(an.pattern()))) {
            return new JsonUtil.JsonDateSerializer(an.pattern());
          }
        }
        return super.findSerializer(a);
      }
    });
  }
  
  public static String toJson(Object obj)
  {
    try
    {
      return mapper.writeValueAsString(obj);
    }
    catch (Exception e)
    {
      throw new RuntimeException("轉換json字元失敗!");
    }
  }
  
  public <T> T toObject(String json, Class<T> clazz)
  {
    try
    {
      return mapper.readValue(json, clazz);
    }
    catch (IOException e)
    {
      throw new RuntimeException("將json字元轉換為物件時失敗!");
    }
  }
  
  public static class JsonDateSerializer
    extends JsonSerializer<Date>
  {
    private SimpleDateFormat dateFormat;
    
    public JsonDateSerializer(String format)
    {
      this.dateFormat = new SimpleDateFormat(format);
    }
    
    public void serialize(Date date, JsonGenerator gen, SerializerProvider provider)
      throws IOException, JsonProcessingException
    {
      String value = this.dateFormat.format(date);
      gen.writeString(value);
    }
  }
}

將JsonObject轉為Bean

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.platform.core.base.Bean;
import com.platform.core.base.IBean;
import com.platform.core.exception.CoreException;
import com.platform.util.json.JSONArray;
import com.platform.util.json.JSONException;
import com.platform.util.json.JSONObject;
   /**
     * @param str JSON串
     * @return Bean實體
   */
    public static Bean transferToBean(String str) {
        Bean n = new Bean();
        if (str != null && str.length() > 0) {
            try {
                JSONObject jsObject = new JSONObject(str);
                /*Iterator is = jsObject.keys();
                for (Iterator iterator = collection.iterator(); iterator
						.hasNext();) {
					type type = (type) iterator.next();
					
				}*/
                for (Iterator<?> i = jsObject.keys(); i.hasNext();) {
                    Bean[] tmpBean = new Bean[] { };
                    String key = (String) i.next();
                    Object value = jsObject.get(key);
                    if (value instanceof JSONArray) {
                        JSONArray tmpArray = (JSONArray) value;
                        tmpBean = new Bean[tmpArray.length()];
                        for (int index = 0, len = tmpArray.length(); index < len; index++) {
                        	String subStr = tmpArray.getString(index).toString();
                        	//處理類似"ids":["125","124"]的列表資料轉換報錯
                        	if(subStr.startsWith("[") || subStr.startsWith("{"))
                        		tmpBean[index] = transferToBean(tmpArray.getString(index).toString());
                        	else {
                        		tmpBean = new Bean[] {};//{"ids":["125","124"],"gridArray":[{"__PK_CODE__":"125"},{"__PK_CODE__":"124"}]}
                        		break;
                        	}
                        }
                    }
                    if (tmpBean.length > 0) {
                        n.set(key, tmpBean);
                    } else {
                        n.set(key, value);
                    }
                }
            } catch (JSONException e) {
                throw new CoreException("JSONException: " + e.getMessage());
            }
        }
        return n;
    }

具體使用

		//獲取業務引數
		String busiStr = req.getParameter("busiData");
		if(!StringUtils.isEmpty(busiStr)){
			try {
				this.busiData = JsonUtils.transferToBean(busiStr);
			} catch (Exception e) {}
		}

將物件轉為JSON字串

    /**
     * @param obj 物件
     * @return JSON串 */
    public static String toJson(Object obj) {
        return new JSONObject(obj).toString();
    }

json字串陣列為List<IBean>,形如[{},{}]

 public static List<IBean> transferToListBean(String str) {
    	List<IBean> retListIBeans = new ArrayList<IBean>();
        if (str != null && str.length() > 0) {
        	try {
				JSONArray jsonArray = new JSONArray(str);
				if(null != jsonArray  && jsonArray.length() > 0){
					for (int i = 0; i < jsonArray.length(); i++) {
						String jsonString = jsonArray.getString(i);
						IBean bean = transferToBean(jsonString);
						retListIBeans.add(bean);
					}
				}
			} catch (JSONException e) {
				e.printStackTrace();
			}
        	
        }
		return retListIBeans;
    }

將list物件轉為JSON字串

    public static String toListJson(List<IBean> obj) {
        return new JSONArray(obj).toString();
    }

後臺傳來接送的資料並解析

	                String child = Emergency.getTABLE();
			if(child!=null){
				JSONArray json = new JSONArray(child);
				for(int i=0;i<json.length();i++){
				JSONObject job = json.getJSONObject(i);
				Object data1 = job.get("data1");
				Object data2 = job.get("data2");
			        Object data3 = job.get("data3");
			        Segment.setDISTANCE(data1.toString());
			        Segment.setELECTRIC(data2.toString());
			        Segment.setQUALIFIED(data3.toString());
			       
				}
			}
	public void delFile(String fileIds, String id){
		try{
            if(!StringUtils.isEmpty(fileIds)){
            	JSONArray jsonArray = new JSONArray(fileIds);
            	if(null != jsonArray && jsonArray.length() > 0){
            		String ids = "";
            		for(int i = 0; i < jsonArray.length(); i++){
            			JSONObject jsonObj = jsonArray.getJSONObject(i);
            			JSONObject obj = (JSONObject)jsonObj.get("data");
            			if(!id.equals(obj.getString("ATTACHMENTID"))){
            				ids += obj.get("ATTACHMENTID") + ",";
            			}
            		}
            		//更新資料庫
            		if(ids.indexOf(",") > -1)
            			ids = ids.substring(0, ids.length() - 1);
        			String sql = "update " + tableName + " set " + fieldName + " = '" + ids + "' where " + pkFieldName
            				+ " = " + entityId;
            	}
            }

附錄json原始碼

JSONException 

package com.platform.util.json;

/**
 * The JSONException is thrown by the JSON.org classes when things are amiss.
 * @author JSON.org
 * @version 2008-09-18
 */
public class JSONException extends Exception {
    /**
	 * 
	 */
	private static final long serialVersionUID = 0;
	private Throwable cause;

    /**
     * Constructs a JSONException with an explanatory message.
     * @param message Detail about the reason for the exception.
     */
    public JSONException(String message) {
        super(message);
    }

    public JSONException(Throwable t) {
        super(t.getMessage());
        this.cause = t;
    }

    public Throwable getCause() {
        return this.cause;
    }
}

JSONObject 

需要引入StringUtil

    /**
     * 匹配字首字元是否相同
     * @param str 源字串
     * @param prefix 目標字串
     * @return 字首字元相同與否
     */
    public static boolean startWithIgnoreCase(String str, String prefix) {
        if (prefix.length() > str.length()) {
            return false;
        }
        return str.substring(0, prefix.length()).equalsIgnoreCase(prefix);
    }
package com.platform.util.json;

/*
 * Copyright (c) 2002 JSON.org Permission is hereby granted, free of charge, to
 * any person obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to permit
 * persons to whom the Software is furnished to do so, subject to the following
 * conditions: The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software. The Software
 * shall be used for Good, not Evil. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT
 * WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
 * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

import java.io.IOException;
import java.io.Serializable;
import java.io.Writer;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;

import com.platform.util.StringUtils;

/**
 * A JSONObject is an unordered collection of name/value pairs. Its external
 * form is a string wrapped in curly braces with colons between the names and
 * values, and commas between the values and names. The internal form is an
 * object having <code>get</code> and <code>opt</code> methods for accessing the
 * values by name, and <code>put</code> methods for adding or replacing values
 * by name. The values can be any of these types: <code>Boolean</code>,
 * <code>JSONArray</code>, <code>JSONObject</code>, <code>Number</code>,
 * <code>String</code>, or the <code>JSONObject.NULL</code> object. A JSONObject
 * constructor can be used to convert an external form JSON text into an
 * internal form whose values can be retrieved with the <code>get</code> and
 * <code>opt</code> methods, or to convert values into a JSON text using the
 * <code>put</code> and <code>toString</code> methods. A <code>get</code> method
 * returns a value if one can be found, and throws an exception if one cannot be
 * found. An <code>opt</code> method returns a default value instead of throwing
 * an exception, and so is useful for obtaining optional values.
 * <p>
 * The generic <code>get()</code> and <code>opt()</code> methods return an
 * object, which you can cast or query for type. There are also typed
 * <code>get</code> and <code>opt</code> methods that do type checking and type
 * coercion for you.
 * <p>
 * The <code>put</code> methods adds values to an object. For example,
 *
 * <pre>
 * myString = new JSONObject().put(&quot;JSON&quot;, &quot;Hello, World!&quot;).toString();
 * </pre>
 *
 * produces the string <code>{"JSON": "Hello, World"}</code>.
 * <p>
 * The texts produced by the <code>toString</code> methods strictly conform to
 * the JSON syntax rules. The constructors are more forgiving in the texts they
 * will accept:
 * <ul>
 * <li>An extra <code>,</code>&nbsp;<small>(comma)</small> may appear just
 * before the closing brace.</li>
 * <li>Strings may be quoted with <code>'</code>&nbsp;<small>(single quote)</small>.</li>
 * <li>Strings do not need to be quoted at all if they do not begin with a quote
 * or single quote, and if they do not contain leading or trailing spaces, and
 * if they do not contain any of these characters:
 * <code>{ } [ ] / \ : , = ; #</code> and if they do not look like numbers and
 * if they are not the reserved words <code>true</code>, <code>false</code>, or
 * <code>null</code>.</li>
 * <li>Keys can be followed by <code>=</code> or <code>=></code> as well as by
 * <code>:</code>.</li>
 * <li>Values can be followed by <code>;</code> <small>(semicolon)</small> as
 * well as by <code>,</code> <small>(comma)</small>.</li>
 * <li>Numbers may have the <code>0x-</code> <small>(hex)</small> prefix.</li>
 * </ul>
 * @author JSON.org
 * @version 2010-05-17
 */
public class JSONObject {

    /**
     * JSONObject.NULL is equivalent to the value that JavaScript calls null,
     * whilst Java's null is equivalent to the value that JavaScript calls
     * undefined.
     */
    private static final class Null implements Serializable{

        /**
         * There is only intended to be a single instance of the NULL object, so
         * the clone method returns itself.
         * @return NULL.
         */
        protected final Object clone() {
            return this;
        }

        /**
         * A Null object is equal to the null value and to itself.
         * @param object An object to test for nullness.
         * @return true if the object parameter is the JSONObject.NULL object or
         *         null.
         */
        public boolean equals(Object object) {
            return object == null || object == this;
        }

        /**
         * Get the "null" string value.
         * @return The string "null".
         */
        public String toString() {
            return "null";
        }
    }

    /**
     * The map where the JSONObject's properties are kept.
     */
    private Map map;

    /**
     * It is sometimes more convenient and less ambiguous to have a
     * <code>NULL</code> object than to use Java's <code>null</code> value.
     * <code>JSONObject.NULL.equals(null)</code> returns <code>true</code>.
     * <code>JSONObject.NULL.toString()</code> returns <code>"null"</code>.
     */
    public static final Object NULL = new Null();

    /**
     * Construct an empty JSONObject.
     */
    public JSONObject() {
        this.map = new HashMap();
    }

    /**
     * Construct a JSONObject from a subset of another JSONObject. An array of
     * strings is used to identify the keys that should be copied. Missing keys
     * are ignored.
     * @param jo A JSONObject.
     * @param names An array of strings.
     * @throws JSONException
     * @exception JSONException If a value is a non-finite number or if a name
     *                is duplicated.
     */
    public JSONObject(JSONObject jo, String[] names) {
        this();
        for (int i = 0; i < names.length; i += 1) {
            try {
                putOnce(names[i], jo.opt(names[i]));
            } catch (Exception ignore) {
            }
        }
    }

    /**
     * Construct a JSONObject from a JSONTokener.
     * @param x A JSONTokener object containing the source string.
     * @throws JSONException If there is a syntax error in the source string or
     *             a duplicated key.
     */
    public JSONObject(JSONTokener x) throws JSONException {
        this();
        char c;
        String key;

        if (x.nextClean() != '{') {
            throw x.syntaxError("A JSONObject text must begin with '{'");
        }
        for (;;) {
            c = x.nextClean();
            switch (c) {
                case 0:
                    throw x.syntaxError("A JSONObject text must end with '}'");
                case '}':
                    return;
                default:
                    x.back();
                    key = x.nextValue().toString();
            }

            /*
             * The key is followed by ':'. We will also tolerate '=' or '=>'.
             */

            c = x.nextClean();
            if (c == '=') {
                if (x.next() != '>') {
                    x.back();
                }
            } else if (c != ':') {
                throw x.syntaxError("Expected a ':' after a key");
            }
            putOnce(key, x.nextValue());

            /*
             * Pairs are separated by ','. We will also tolerate ';'.
             */

            switch (x.nextClean()) {
                case ';':
                case ',':
                    if (x.nextClean() == '}') {
                        return;
                    }
                    x.back();
                    break;
                case '}':
                    return;
                default:
                    throw x.syntaxError("Expected a ',' or '}'");
            }
        }
    }

    /**
     * Construct a JSONObject from a Map.
     * @param map A map object that can be used to initialize the contents of
     *            the JSONObject.
     * @throws JSONException
     */
    public JSONObject(Map map) {
        this.map = new HashMap();
        if (map != null) {
            Iterator i = map.entrySet().iterator();
            while (i.hasNext()) {
                Map.Entry e = (Map.Entry) i.next();
                this.map.put(e.getKey(), wrap(e.getValue()));
            }
        }
    }

    /**
     * Construct a JSONObject from an Object using bean getters. It reflects on
     * all of the public methods of the object. For each of the methods with no
     * parameters and a name starting with <code>"get"</code> or
     * <code>"is"</code> followed by an uppercase letter, the method is invoked,
     * and a key and the value returned from the getter method are put into the
     * new JSONObject. The key is formed by removing the <code>"get"</code> or
     * <code>"is"</code> prefix. If the second remaining character is not upper
     * case, then the first character is converted to lower case. For example,
     * if an object has a method named <code>"getName"</code>, and if the result
     * of calling <code>object.getName()</code> is <code>"Larry Fine"</code>,
     * then the JSONObject will contain <code>"name": "Larry Fine"</code>.
     * @param bean An object that has getter methods that should be used to make
     *            a JSONObject.
     */
    public JSONObject(Object bean) {
        this();
        populateMap(bean);
    }

    /**
     * Construct a JSONObject from an Object, using reflection to find the
     * public members. The resulting JSONObject's keys will be the strings from
     * the names array, and the values will be the field values associated with
     * those keys in the object. If a key is not found or not visible, then it
     * will not be copied into the new JSONObject.
     * @param object An object that has fields that should be used to make a
     *            JSONObject.
     * @param names An array of strings, the names of the fields to be obtained
     *            from the object.
     */
    public JSONObject(Object object, String names[]) {
        this();
        Class c = object.getClass();
        for (int i = 0; i < names.length; i += 1) {
            String name = names[i];
            try {
                putOpt(name, c.getField(name).get(object));
            } catch (Exception ignore) {
            }
        }
    }

    /**
     * Construct a JSONObject from a source JSON text string. This is the most
     * commonly used JSONObject constructor.
     * @param source A string beginning with <code>{</code>&nbsp;<small>(left
     *            brace)</small> and ending with <code>}</code>
     *            &nbsp;<small>(right brace)</small>.
     * @exception JSONException If there is a syntax error in the source string
     *                or a duplicated key.
     */
    public JSONObject(String source) throws JSONException {
        this(new JSONTokener(source));
    }

    /**
     * Accumulate values under a key. It is similar to the put method except
     * that if there is already an object stored under the key then a JSONArray
     * is stored under the key to hold all of the accumulated values. If there
     * is already a JSONArray, then the new value is appended to it. In
     * contrast, the put method replaces the previous value.
     * @param key A key string.
     * @param value An object to be accumulated under the key.
     * @return this.
     * @throws JSONException If the value is an invalid number or if the key is
     *             null.
     */
    public JSONObject accumulate(String key, Object value)
        throws JSONException {
        testValidity(value);
        Object o = opt(key);
        if (o == null) {
            put(key, value instanceof JSONArray ?
                new JSONArray().put(value) :
                value);
        } else if (o instanceof JSONArray) {
            ((JSONArray) o).put(value);
        } else {
            put(key, new JSONArray().put(o).put(value));
        }
        return this;
    }

    /**
     * Append values to the array under a key. If the key does not exist in the
     * JSONObject, then the key is put in the JSONObject with its value being a
     * JSONArray containing the value parameter. If the key was already
     * associated with a JSONArray, then the value parameter is appended to it.
     * @param key A key string.
     * @param value An object to be accumulated under the key.
     * @return this.
     * @throws JSONException If the key is null or if the current value
     *             associated with the key is not a JSONArray.
     */
    public JSONObject append(String key, Object value) throws JSONException {
        testValidity(value);
        Object o = opt(key);
        if (o == null) {
            put(key, new JSONArray().put(value));
        } else if (o instanceof JSONArray) {
            put(key, ((JSONArray) o).put(value));
        } else {
            throw new JSONException("JSONObject[" + key +
                "] is not a JSONArray.");
        }
        return this;
    }

    /**
     * Produce a string from a double. The string "null" will be returned if the
     * number is not finite.
     * @param d A double.
     * @return A String.
     */
    static public String doubleToString(double d) {
        if (Double.isInfinite(d) || Double.isNaN(d)) {
            return "null";
        }

        // Shave off trailing zeros and decimal point, if possible.

        String s = Double.toString(d);
        if (s.indexOf('.') > 0 && s.indexOf('e') < 0 && s.indexOf('E') < 0) {
            while (s.endsWith("0")) {
                s = s.substring(0, s.length() - 1);
            }
            if (s.endsWith(".")) {
                s = s.substring(0, s.length() - 1);
            }
        }
        return s;
    }

    /**
     * Get the value object associated with a key.
     * @param key A key string.
     * @return The object associated with the key.
     * @throws JSONException if the key is not found.
     */
    public Object get(String key) throws JSONException {
        Object o = opt(key);
        if (o == null) {
            throw new JSONException("JSONObject[" + quote(key) +
                "] not found.");
        }
        return o;
    }

    /**
     * Get the boolean value associated with a key.
     * @param key A key string.
     * @return The truth.
     * @throws JSONException if the value is not a Boolean or the String "true"
     *             or "false".
     */
    public boolean getBoolean(String key) throws JSONException {
        Object o = get(key);
        if (o.equals(Boolean.FALSE) ||
            (o instanceof String &&
            ((String) o).equalsIgnoreCase("false"))) {
            return false;
        } else if (o.equals(Boolean.TRUE) ||
            (o instanceof String &&
            ((String) o).equalsIgnoreCase("true"))) {
            return true;
        }
        throw new JSONException("JSONObject[" + quote(key) +
            "] is not a Boolean.");
    }

    /**
     * Get the double value associated with a key.
     * @param key A key string.
     * @return The numeric value.
     * @throws JSONException if the key is not found or if the value is not a
     *             Number object and cannot be converted to a number.
     */
    public double getDouble(String key) throws JSONException {
        Object o = get(key);
        try {
            return o instanceof Number ?
                ((Number) o).doubleValue() :
                Double.valueOf((String) o).doubleValue();
        } catch (Exception e) {
            throw new JSONException("JSONObject[" + quote(key) +
                "] is not a number.");
        }
    }

    /**
     * Get the int value associated with a key.
     * @param key A key string.
     * @return The integer value.
     * @throws JSONException if the key is not found or if the value cannot be
     *             converted to an integer.
     */
    public int getInt(String key) throws JSONException {
        Object o = get(key);
        try {
            return o instanceof Number ?
                ((Number) o).intValue() :
                Integer.parseInt((String) o);
        } catch (Exception e) {
            throw new JSONException("JSONObject[" + quote(key) +
                "] is not an int.");
        }
    }

    /**
     * Get the JSONArray value associated with a key.
     * @param key A key string.
     * @return A JSONArray which is the value.
     * @throws JSONException if the key is not found or if the value is not a
     *             JSONArray.
     */
    public JSONArray getJSONArray(String key) throws JSONException {
        Object o = get(key);
        if (o instanceof JSONArray) {
            return (JSONArray) o;
        }
        throw new JSONException("JSONObject[" + quote(key) +
            "] is not a JSONArray.");
    }

    /**
     * Get the JSONObject value associated with a key.
     * @param key A key string.
     * @return A JSONObject which is the value.
     * @throws JSONException if the key is not found or if the value is not a
     *             JSONObject.
     */
    public JSONObject getJSONObject(String key) throws JSONException {
        Object o = get(key);
        if (o instanceof JSONObject) {
            return (JSONObject) o;
        }
        throw new JSONException("JSONObject[" + quote(key) +
            "] is not a JSONObject.");
    }

    /**
     * Get the long value associated with a key.
     * @param key A key string.
     * @return The long value.
     * @throws JSONException if the key is not found or if the value cannot be
     *             converted to a long.
     */
    public long getLong(String key) throws JSONException {
        Object o = get(key);
        try {
            return o instanceof Number ?
                ((Number) o).longValue() :
                Long.parseLong((String) o);
        } catch (Exception e) {
            throw new JSONException("JSONObject[" + quote(key) +
                "] is not a long.");
        }
    }

    /**
     * Get an array of field names from a JSONObject.
     * @return An array of field names, or null if there are no names.
     */
    public static String[] getNames(JSONObject jo) {
        int length = jo.length();
        if (length == 0) {
            return null;
        }
        Iterator i = jo.keys();
        String[] names = new String[length];
        int j = 0;
        while (i.hasNext()) {
            names[j] = (String) i.next();
            j += 1;
        }
        return names;
    }

    /**
     * Get an array of field names from an Object.
     * @return An array of field names, or null if there are no names.
     */
    public static String[] getNames(Object object) {
        if (object == null) {
            return null;
        }
        Class klass = object.getClass();
        Field[] fields = klass.getFields();
        int length = fields.length;
        if (length == 0) {
            return null;
        }
        String[] names = new String[length];
        for (int i = 0; i < length; i += 1) {
            names[i] = fields[i].getName();
        }
        return names;
    }

    /**
     * Get the string associated with a key.
     * @param key A key string.
     * @return A string which is the value.
     * @throws JSONException if the key is not found.
     */
    public String getString(String key) throws JSONException {
        return get(key).toString();
    }

    /**
     * Determine if the JSONObject contains a specific key.
     * @param key A key string.
     * @return true if the key exists in the JSONObject.
     */
    public boolean has(String key) {
        return this.map.containsKey(key);
    }

    /**
     * Increment a property of a JSONObject. If there is no such property,
     * create one with a value of 1. If there is such a property, and if it is
     * an Integer, Long, Double, or Float, then add one to it.
     * @param key A key string.
     * @return this.
     * @throws JSONException If there is already a property with this name that
     *             is not an Integer, Long, Double, or Float.
     */
    public JSONObject increment(String key) throws JSONException {
        Object value = opt(key);
        if (value == null) {
            put(key, 1);
        } else {
            if (value instanceof Integer) {
                put(key, ((Integer) value).intValue() + 1);
            } else if (value instanceof Long) {
                put(key, ((Long) value).longValue() + 1);
            } else if (value instanceof Double) {
                put(key, ((Double) value).doubleValue() + 1);
            } else if (value instanceof Float) {
                put(key, ((Float) value).floatValue() + 1);
            } else {
                throw new JSONException("Unable to increment [" + key + "].");
            }
        }
        return this;
    }

    /**
     * Determine if the value associated with the key is null or if there is no
     * value.
     * @param key A key string.
     * @return true if there is no value associated with the key or if the value
     *         is the JSONObject.NULL object.
     */
    public boolean isNull(String key) {
        return JSONObject.NULL.equals(opt(key));
    }

    /**
     * Get an enumeration of the keys of the JSONObject.
     * @return An iterator of the keys.
     */
    public Iterator keys() {
        return this.map.keySet().iterator();
    }

    /**
     * Get the number of keys stored in the JSONObject.
     * @return The number of keys in the JSONObject.
     */
    public int length() {
        return this.map.size();
    }

    /**
     * Produce a JSONArray containing the names of the elements of this
     * JSONObject.
     * @return A JSONArray containing the key strings, or null if the JSONObject
     *         is empty.
     */
    public JSONArray names() {
        JSONArray ja = new JSONArray();
        Iterator keys = keys();
        while (keys.hasNext()) {
            ja.put(keys.next());
        }
        return ja.length() == 0 ? null : ja;
    }

    /**
     * Produce a string from a Number.
     * @param n A Number
     * @return A String.
     * @throws JSONException If n is a non-finite number.
     */
    static public String numberToString(Number n)
        throws JSONException {
        if (n == null) {
            throw new JSONException("Null pointer");
        }
        testValidity(n);

        // Shave off trailing zeros and decimal point, if possible.

        String s = n.toString();
        if (s.indexOf('.') > 0 && s.indexOf('e') < 0 && s.indexOf('E') < 0) {
            while (s.endsWith("0")) {
                s = s.substring(0, s.length() - 1);
            }
            if (s.endsWith(".")) {
                s = s.substring(0, s.length() - 1);
            }
        }
        return s;
    }

    /**
     * Get an optional value associated with a key.
     * @param key A key string.
     * @return An object which is the value, or null if there is no value.
     */
    public Object opt(String key) {
        return key == null ? null : this.map.get(key);
    }

    /**
     * Get an optional boolean associated with a key. It returns false if there
     * is no such key, or if the value is not Boolean.TRUE or the String "true".
     * @param key A key string.
     * @return The truth.
     */
    public boolean optBoolean(String key) {
        return optBoolean(key, false);
    }

    /**
     * Get an optional boolean associated with a key. It returns the
     * defaultValue if there is no such key, or if it is not a Boolean or the
     * String "true" or "false" (case insensitive).
     * @param key A key string.
     * @param defaultValue The default.
     * @return The truth.
     */
    public boolean optBoolean(String key, boolean defaultValue) {
        try {
            return getBoolean(key);
        } catch (Exception e) {
            return defaultValue;
        }
    }

    /**
     * Get an optional double associated with a key, or NaN if there is no such
     * key or if its value is not a number. If the value is a string, an attempt
     * will be made to evaluate it as a number.
     * @param key A string which is the key.
     * @return An object which is the value.
     */
    public double optDouble(String key) {
        return optDouble(key, Double.NaN);
    }

    /**
     * Get an optional double associated with a key, or the defaultValue if
     * there is no such key or if its value is not a number. If the value is a
     * string, an attempt will be made to evaluate it as a number.
     * @param key A key string.
     * @param defaultValue The default.
     * @return An object which is the value.
     */
    public double optDouble(String key, double defaultValue) {
        try {
            Object o = opt(key);
            return o instanceof Number ? ((Number) o).doubleValue() :
                new Double((String) o).doubleValue();
        } catch (Exception e) {
            return defaultValue;
        }
    }

    /**
     * Get an optional int value associated with a key, or zero if there is no
     * such key or if the value is not a number. If the value is a string, an
     * attempt will be made to evaluate it as a number.
     * @param key A key string.
     * @return An object which is the value.
     */
    public int optInt(String key) {
        return optInt(key, 0);
    }

    /**
     * Get an optional int value associated with a key, or the default if there
     * is no such key or if the value is not a number. If the value is a string,
     * an attempt will be made to evaluate it as a number.
     * @param key A key string.
     * @param defaultValue The default.
     * @return An object which is the value.
     */
    public int optInt(String key, int defaultValue) {
        try {
            return getInt(key);
        } catch (Exception e) {
            return defaultValue;
        }
    }

    /**
     * Get an optional JSONArray associated with a key. It returns null if there
     * is no such key, or if its value is not a JSONArray.
     * @param key A key string.
     * @return A JSONArray which is the value.
     */
    public JSONArray optJSONArray(String key) {
        Object o = opt(key);
        return o instanceof JSONArray ? (JSONArray) o : null;
    }

    /**
     * Get an optional JSONObject associated with a key. It returns null if
     * there is no such key, or if its value is not a JSONObject.
     * @param key A key string.
     * @return A JSONObject which is the value.
     */
    public JSONObject optJSONObject(String key) {
        Object o = opt(key);
        return o instanceof JSONObject ? (JSONObject) o : null;
    }

    /**
     * Get an optional long value associated with a key, or zero if there is no
     * such key or if the value is not a number. If the value is a string, an
     * attempt will be made to evaluate it as a number.
     * @param key A key string.
     * @return An object which is the value.
     */
    public long optLong(String key) {
        return optLong(key, 0);
    }

    /**
     * Get an optional long value associated with a key, or the default if there
     * is no such key or if the value is not a number. If the value is a string,
     * an attempt will be made to evaluate it as a number.
     * @param key A key string.
     * @param defaultValue The default.
     * @return An object which is the value.
     */
    public long optLong(String key, long defaultValue) {
        try {
            return getLong(key);
        } catch (Exception e) {
            return defaultValue;
        }
    }

    /**
     * Get an optional string associated with a key. It returns an empty string
     * if there is no such key. If the value is not a string and is not null,
     * then it is coverted to a string.
     * @param key A key string.
     * @return A string which is the value.
     */
    public String optString(String key) {
        return optString(key, "");
    }

    /**
     * Get an optional string associated with a key. It returns the defaultValue
     * if there is no such key.
     * @param key A key string.
     * @param defaultValue The default.
     * @return A string which is the value.
     */
    public String optString(String key, String defaultValue) {
        Object o = opt(key);
        return o != null ? o.toString() : defaultValue;
    }

    private void populateMap(Object bean) {
        Class klass = bean.getClass();
        // If klass is a System class then set includeSuperClass to false.
        boolean includeSuperClass = klass.getClassLoader() != null;
        Method[] methods = (includeSuperClass) ?
            klass.getMethods() : klass.getDeclaredMethods();
        Method comMethod = null;
        for (int i = 0; i < methods.length; i++) {
            String name = methods[i].getName();
            if ("get".equals(name) && methods[i].getParameterTypes().length == 1) {
                comMethod = methods[i];
                break;
            }
        }
        for (int i = 0; i < methods.length; i++) {
            try {
                Method method = methods[i];
                if (Modifier.isPublic(method.getModifiers())) {
                    String name = method.getName();
                    if (name.equals("getClass") ||
                        name.equals("getDeclaringClass") || name.equals("isEmpty")) {
                        continue;
                    }
                    if (StringUtils.startWithIgnoreCase(name, "get") || StringUtils.startWithIgnoreCase(name, "is") ) {
                        String key = "";
                        if(StringUtils.startWithIgnoreCase(name, "get")){
                            key = name.substring(3);
                        }else if(StringUtils.startWithIgnoreCase(name, "is")){
                            key = name.substring(2);
                        }

                        Object result = method.invoke(bean, (Object[]) null);
                        if (key.trim().length() > 0) {
                            if (!Character.isUpperCase(key.charAt(1))) {
                                key = key.substring(0, 1).toLowerCase() +
                                    key.substring(1);
                            }
                            if ("keys".equals(key) && comMethod != null) { // ����̬��
                                for (Iterator iter = ((List) result).iterator(); iter.hasNext();) {
                                    String comKey = (String) iter.next();
                                    map.put(comKey, wrap(comMethod.invoke(bean, comKey)));
                                }
                            } else if("data".equals(key)){
                            	continue;
                            }else{// ����ʵ����
                                map.put(key, wrap(result));
                            }
                        }
                    }
                }
            } catch (Exception ignore) {
            }
        }
    }

    /**
     * Put a key/boolean pair in the JSONObject.
     * @param key A key string.
     * @param value A boolean which is the value.
     * @return this.
     * @throws JSONException If the key is null.
     */
    public JSONObject put(String key, boolean value) throws JSONException {
        put(key, value ? Boolean.TRUE : Boolean.FALSE);
        return this;
    }

    /**
     * Put a key/value pair in the JSONObject, where the value will be a
     * JSONArray which is produced from a Collection.
     * @param key A key string.
     * @param value A Collection value.
     * @return this.
     * @throws JSONException
     */
    public JSONObject put(String key, Collection value) throws JSONException {
        put(key, new JSONArray(value));
        return this;
    }

    /**
     * Put a key/double pair in the JSONObject.
     * @param key A key string.
     * @param value A double which is the value.
     * @return this.
     * @throws JSONException If the key is null or if the number is invalid.
     */
    public JSONObject put(String key, double value) throws JSONException {
        put(key, new Double(value));
        return this;
    }

    /**
     * Put a key/int pair in the JSONObject.
     * @param key A key string.
     * @param value An int which is the value.
     * @return this.
     * @throws JSONException If the key is null.
     */
    public JSONObject put(String key, int value) throws JSONException {
        put(key, new Integer(value));
        return this;
    }

    /**
     * Put a key/long pair in the JSONObject.
     * @param key A key string.
     * @param value A long which is the value.
     * @return this.
     * @throws JSONException If the key is null.
     */
    public JSONObject put(String key, long value) throws JSONException {
        put(key, new Long(value));
        return this;
    }

    /**
     * Put a key/value pair in the JSONObject, where the value will be a
     * JSONObject which is produced from a Map.
     * @param key A key string.
     * @param value A Map value.
     * @return this.
     * @throws JSONException
     */
    public JSONObject put(String key, Map value) throws JSONException {
        put(key, new JSONObject(value));
        return this;
    }

    /**
     * Put a key/value pair in the JSONObject. If the value is null, then the
     * key will be removed from the JSONObject if it is present.
     * @param key A key string.
     * @param value An object which is the value. It should be of one of these
     *            types: Boolean, Double, Integer, JSONArray, JSONObject, Long,
     *            String, or the JSONObject.NULL object.
     * @return this.
     * @throws JSONException If the value is non-finite number or if the key is
     *             null.
     */
    public JSONObject put(String key, Object value) throws JSONException {
        if (key == null) {
            throw new JSONException("Null key.");
        }
        if (value != null) {
            testValidity(value);
            this.map.put(key, value);
        } else {
            remove(key);
        }
        return this;
    }

    /**
     * Put a key/value pair in the JSONObject, but only if the key and the value
     * are both non-null, and only if there is not already a member with that
     * name.
     * @param key
     * @param value
     * @return his.
     * @throws JSONException if the key is a duplicate
     */
    public JSONObject putOnce(String key, Object value) throws JSONException {
        if (key != null && value != null) {
            if (opt(key) != null) {
                throw new JSONException("Duplicate key \"" + key + "\"");
            }
            put(key, value);
        }
        return this;
    }

    /**
     * Put a key/value pair in the JSONObject, but only if the key and the value
     * are both non-null.
     * @param key A key string.
     * @param value An object which is the value. It should be of one of these
     *            types: Boolean, Double, Integer, JSONArray, JSONObject, Long,
     *            String, or the JSONObject.NULL object.
     * @return this.
     * @throws JSONException If the value is a non-finite number.
     */
    public JSONObject putOpt(String key, Object value) throws JSONException {
        if (key != null && value != null) {
            put(key, value);
        }
        return this;
    }

    /**
     * Produce a string in double quotes with backslash sequences in all the
     * right places. A backslash will be inserted within </, allowing JSON text
     * to be delivered in HTML. In JSON text, a string cannot contain a control
     * character or an unescaped quote or backslash.
     * @param string A String
     * @return A String correctly formatted for insertion in a JSON text.
     */
    public static String quote(String string) {
        if (string == null || string.length() == 0) {
            return "\"\"";
        }

        char b;
        char c = 0;
        int i;
        int len = string.length();
        StringBuffer sb = new StringBuffer(len + 4);
        String t;

        sb.append('"');
        for (i = 0; i < len; i += 1) {
            b = c;
            c = string.charAt(i);
            switch (c) {
                case '\\':
                case '"':
                    sb.append('\\');
                    sb.append(c);
                    break;
                case '/':
                    if (b == '<') {
                        sb.append('\\');
                    }
                    sb.append(c);
                    break;
                case '\b':
                    sb.append("\\b");
                    break;
                case '\t':
                    sb.append("\\t");
                    break;
                case '\n':
                    sb.append("\\n");
                    break;
                case '\f':
                    sb.append("\\f");
                    break;
                case '\r':
                    sb.append("\\r");
                    break;
                default:
                    if (c < ' ' || (c >= '\u0080' && c < '\u00a0') ||
                        (c >= '\u2000' && c < '\u2100')) {
                        t = "000" + Integer.toHexString(c);
                        sb.append("\\u" + t.substring(t.length() - 4));
                    } else {
                        sb.append(c);
                    }
            }
        }
        sb.append('"');
        return sb.toString();
    }

    /**
     * Remove a name and its value, if present.
     * @param key The name to be removed.
     * @return The value that was associated with the name, or null if there was
     *         no value.
     */
    public Object remove(String key) {
        return this.map.remove(key);
    }

    /**
     * Get an enumeration of the keys of the JSONObject. The keys will be sorted
     * alphabetically.
     * @return An iterator of the keys.
     */
    public Iterator sortedKeys() {
        return new TreeSet(this.map.keySet()).iterator();
    }

    /**
     * Try to convert a string into a number, boolean, or null. If the string
     * can't be converted, return the string.
     * @param s A String.
     * @return A simple JSON value.
     */
    static public Object stringToValue(String s) {
        if (s.equals("")) {
            return s;
        }
        if (s.equalsIgnoreCase("true")) {
            return Boolean.TRUE;
        }
        if (s.equalsIgnoreCase("false")) {
            return Boolean.FALSE;
        }
        if (s.equalsIgnoreCase("null")) {
            return JSONObject.NULL;
        }

        /*
         * If it might be a number, try converting it. We support the
         * non-standard 0x- convention. If a number cannot be produced, then the
         * value will just be a string. Note that the 0x-, plus, and implied
         * string conventions are non-standard. A JSON parser may accept
         * non-JSON forms as long as it accepts all correct JSON forms.
         */

        char b = s.charAt(0);
        if ((b >= '0' && b <= '9') || b == '.' || b == '-' || b == '+') {
            if (b == '0' && s.length() > 2 &&
                (s.charAt(1) == 'x' || s.charAt(1) == 'X')) {
                try {
                    return new Integer(Integer.parseInt(s.substring(2), 16));
                } catch (Exception ignore) {
                }
            }
            try {
                if (s.indexOf('.') > -1 ||
                    s.indexOf('e') > -1 || s.indexOf('E') > -1) {
                    return Double.valueOf(s);
                } else {
                    Long myLong = new Long(s);
                    if (myLong.longValue() == myLong.intValue()) {
                        return new Integer(myLong.intValue());
                    } else {
                        return myLong;
                    }
                }
            } catch (Exception ignore) {
            }
        }
        return s;
    }

    /**
     * Throw an exception if the object is an NaN or infinite number.
     * @param o The object to test.
     * @throws JSONException If o is a non-finite number.
     */
    static void testValidity(Object o) throws JSONException {
        if (o != null) {
            if (o instanceof Double) {
                if (((Double) o).isInfinite() || ((Double) o).isNaN()) {
                    throw new JSONException(
                        "JSON does not allow non-finite numbers.");
                }
            } else if (o instanceof Float) {
                if (((Float) o).isInfinite() || ((Float) o).isNaN()) {
                    throw new JSONException(
                        "JSON does not allow non-finite numbers.");
                }
            }
        }
    }

    /**
     * Produce a JSONArray containing the values of the members of this
     * JSONObject.
     * @param names A JSONArray containing a list of key strings. This
     *            determines the sequence of the values in the result.
     * @return A JSONArray of values.
     * @throws JSONException If any of the values are non-finite numbers.
     */
    public JSONArray toJSONArray(JSONArray names) throws JSONException {
        if (names == null || names.length() == 0) {
            return null;
        }
        JSONArray ja = new JSONArray();
        for (int i = 0; i < names.length(); i += 1) {
            ja.put(this.opt(names.getString(i)));
        }
        return ja;
    }

    /**
     * Make a JSON text of this JSONObject. For compactness, no whitespace is
     * added. If this would not result in a syntactically correct JSON text,
     * then null will be returned instead.
     * <p>
     * Warning: This method assumes that the data structure is acyclical.
     * @return a printable, displayable, portable, transmittable representation
     *         of the object, beginning with <code>{</code>&nbsp;<small>(left
     *         brace)</small> and ending with <code>}</code>&nbsp;<small>(right
     *         brace)</small>.
     */
    public String toString() {
        try {
            Iterator keys = keys();
            StringBuffer sb = new StringBuffer("{");

            while (keys.hasNext()) {
                if (sb.length() > 1) {
                    sb.append(',');
                }
                Object o = keys.next();
                sb.append(quote(o.toString()));
                sb.append(':');
                sb.append(valueToString(this.map.get(o)));
            }
            sb.append('}');
            return sb.toString();
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * Make a prettyprinted JSON text of this JSONObject.
     * <p>
     * Warning: This method assumes that the data structure is acyclical.
     * @param indentFactor The number of spaces to add to each level of
     *            indentation.
     * @return a printable, displayable, portable, transmittable representation
     *         of the object, beginning with <code>{</code>&nbsp;<small>(left
     *         brace)</small> and ending with <code>}</code>&nbsp;<small>(right
     *         brace)</small>.
     * @throws JSONException If the object contains an invalid number.
     */
    public String toString(int indentFactor) throws JSONException {
        return toString(indentFactor, 0);
    }

    /**
     * Make a prettyprinted JSON text of this JSONObject.
     * <p>
     * Warning: This method assumes that the data structure is acyclical.
     * @param indentFactor The number of spaces to add to each level of
     *            indentation.
     * @param indent The indentation of the top level.
     * @return a printable, displayable, transmittable representation of the
     *         object, beginning with <code>{</code>&nbsp;<small>(left
     *         brace)</small> and ending with <code>}</code>&nbsp;<s