org.json源码分析及增强(一)——JSONObject对象与Java对象相互转换

本文详细分析了org.json库的JSONObject源码,探讨了如何从字符串和Java对象创建JSONObject,以及如何实现JSONObject与Java对象之间的转换。通过对JSONObject的源码解析,展示了如何增强JSONObject的功能,使其支持反序列化。
摘要由CSDN通过智能技术生成

本系列文章将对org.json(https://github.com/stleary/JSON-java)的部分源代码进行分析,并介绍如何将其缺少的一些功能进行增强和完善。

为什么是org.json

Java世界中存在着各种针对JSON数据格式类型处理的各种利器,优秀者比如google-gson、Jackson、Genson、Flexjson等(可以从http://www.json.org/站点获取几乎所有编程语言的各种JSON支持项目)。
org.json在其中简直可以说是默默无闻,但它非常轻量,几乎与json-simple一样轻,而且功能比较齐全,选择org.json进行分析和增强有利于我们对于相关知识的学习。以下是GitHub上org.json项目对于其源代码的说明:

JSONObject.java: The JSONObject can parse text from a String or a JSONTokener to produce a map-like object. The object provides methods for manipulating its contents, and for producing a JSON compliant object serialization.

JSONArray.java: The JSONObject can parse text from a String or a JSONTokener to produce a vector-like object. The object provides methods for manipulating its contents, and for producing a JSON compliant array serialization.

JSONTokener.java: The JSONTokener breaks a text into a sequence of individual tokens. It can be constructed from a String, Reader, or InputStream.

JSONException.java: The JSONException is the standard exception type thrown by this package.

JSONPointer.java: Implementation of JSON Pointer (RFC 6901). Supports
JSON Pointers both in the form of string representation and URI fragment
representation.

JSONString.java: The JSONString interface requires a toJSONString method,allowing an object to provide its own serialization.

JSONStringer.java: The JSONStringer provides a convenient facility for building JSON strings.

JSONWriter.java: The JSONWriter provides a convenient facility for building JSON text through a writer.

CDL.java: CDL provides support for converting between JSON and comma delimited lists.

Cookie.java: Cookie provides support for converting between JSON and cookies.

CookieList.java: CookieList provides support for converting between JSON and cookie lists.

HTTP.java: HTTP provides support for converting between JSON and HTTP headers.

HTTPTokener.java: HTTPTokener extends JSONTokener for parsing HTTP headers.

XML.java: XML provides support for converting between JSON and XML.

JSONML.java: JSONML provides support for converting between JSONML and XML.

XMLTokener.java: XMLTokener extends JSONTokener for parsing XML text.

JSONObject.java源码分析

JSONObject是一个核心类,它内部利用HashMap进行存储,实现了从一个字符串、Map对象、Java对象,JSONObject对象自身来构建一个key-value形式的JSON数据格式类型对象(这种数据格式与JavaScript的对象格式非常相似)。从而达到Map一样的操作,并可以输出为标准的JSON字符串。
在源码分析中我们主要讨论从字符串转换为JSONObject对象和从Java对象转换为JSONObject对象:

(1)字符串转换为JSONObject对象

public JSONObject(String source) throws JSONException {
        this(new JSONTokener(source));
    }

转换利用JSONTokener类,首先将字符串转换为可以将其按JSON数据格式拆解为一个一个循序的char对象的JSONTokener对象,之后遵循JSON数据格式的标准规则:
1. 以”{“开头;
2. 以”}”结尾;
3. key后面紧跟着”:”;
4. 属性对(key-value)之间使用”,”分割。
利用以下代码,按JSONTokener对象所拆解的每个char对象一种顺序循环直至出现JSON语法错误或到达尾部终止,最终完成对HashMap的填充:

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 ':'.

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

// Pairs are separated by ','.

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

这里需要注意的是,在进行key和value取值时,使用了JSONTokener类的nextValue()方法,此方法将通过字符对类型进行判断,目前支持Boolean, Double, Integer,JSONArray, JSONObject, Long, String, JSONObject.NULL类型,主要的逻辑代码参考如下:

switch (c) {
            case '"':
            case '\'':
                return this.nextString(c);
            case '{':
                this.back();
                return new JSONObject(this);
            case '[':
                this.back();
                return new JSONArray(this);
        }

除去”外,\’对应一个String类型,{对应一个JSONObject类型,[对应一个JSONArray类型,对于”会继续判断,最终通过JSONObject.stringToValue()方法返回对应类型的Object对象。

(2)Java对象转换为JSONObject对象

public JSONObject(Object bean) {
        this();
        this.populateMap(bean);
    }

转换的实际是一个JavaBean对象,实际方法为populateMap,可以理解为是一个对于JavaBean对象实现序列化的通用方法。我们可以关注populateMap的几个细节。
1. 通过getClassLoader()来判断处理的是否是一个纯系统(JRE)类或是一个基本类型,从JRS中我们可以看到这样一个描述:

Returns the class loader for the class. Some implementations may use null to represent the bootstrap class loader. This method will return null in such implementations if this class was loaded by the bootstrap class loader.
If this object represents a primitive type or void, null is returned.

当启动一个JVM时,Bootstrap Classloader会加载java的核心类,也就是我们说的System Class,当你试图获取其类加载器时会返回一个null,因为Bootstrap Classloader并不是一个Java类,而是一个JVM的内部实现;另外,当获取基本类型的Classloader时也同样返回null。
2. 通过Modifier.isPublic(method.getModifiers())判断是否为public方法,通过反射get方法获取对应的key值和value值,并利用wrap方法对value值判断类型后进行分别处理,wrap方法代码如下:

 public 
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值