本文完成于2021.1.14,首发于独立博客空间
一、概述
Json是fastjson软件包使用的入口、代码的主类,能获得一个可操作的JsonObject对象;其分别实现了JSONSteamAware接口和JSONAware接口
二、提供对外API
1.toJSONString(object)
该方法要求对象必须为泛型(Generic type),与之相对的writeJSONString(Writer, Object, SerializerFeature[])方法,就可以使用非泛型的对象,两者的目标都是将制定对象转换为特定格式的JSON形式的字符串
其实现了13个重载方法:
public static String toJSONString(Object object)
public static String toJSONString(Object object, SerializerFeature... features)
public static String toJSONString(Object object, int defaultFeatures, SerializerFeature... features)
public static String toJSONStringWithDateFormat(Object object, String dateFormat,SerializerFeature... features)
public static String toJSONString(Object object, SerializeFilter filter, SerializerFeature... features)
public static String toJSONString(Object object, SerializeFilter[] filters, SerializerFeature... features)
public static String toJSONString(Object object, SerializeConfig config, SerializerFeature... features)
public static String toJSONString(Object object, SerializeConfig config,SerializeFilter filter,SerializerFeature... features)
public static String toJSONString(Object object, SerializeConfig config, SerializeFilter[] filters, SerializerFeature... features)
public static String toJSONString(Object object,SerializeConfig config,SerializeFilter[] filters, String dateFormat,int defaultFeatures, SerializerFeature... features)
public static String toJSONStringZ(Object object, SerializeConfig mapping, SerializerFeature... features)
public static String toJSONString(Object object, boolean prettyFormat)
public String toJSONString()
在简单使用中,我们只传入一个任意类型的对象时,代码如下:
Coder.java
public class Coder {
private String name;
private int hairs;
private String health;
....
}
测试方法
public void testToJsonStringObject(){
Coder coder = new Coder();
coder.setName("张三");
coder.setHairs(100);
coder.setHealth("快死了");
String jsonString = JSON.toJSONString(coder);
System.out.println(jsonString);
}
首先进入JSON的toJSONString(coder)方法:
public static String toJSONString(Object object) {
return toJSONString(object, emptyFilters);
}
这个返回调用toJSONString(object, emptyFilters):
运行后发现指向
public static String toJSONString(Object object, SerializeFilter[] filters, SerializerFeature... features) {
return toJSONString(object, SerializeConfig.globalInstance, filters, null, DEFAULT_GENERATE_FEATURE, features);
}
再次跟进,进入:
public static String toJSONString(Object object, //
SerializeConfig config, //
SerializeFilter[] filters, //
String dateFormat, //
int defaultFeatures, //
SerializerFeature... features)
此时变量情况如下:
仔细观察当前进入方法逻辑:
首先是创建了一个SerializeWriter对象
SerializeWriter out = new SerializeWriter(null, defaultFeatures, features);
SerializeWriter类的作用是对输入对象进行序列化操作,在此处是用来提前构建一个缓冲区,用于之后的解析操作。
因为在该类中有一个静态代码块,首次执行时,会设定一个缓存区域的大小
static {
try {
String prop = IOUtils.getStringProperty("fastjson.serializer_buffer_threshold");
if (prop != null && prop.length() > 0) {
int serializer_buffer_threshold = Integer.parseInt(prop);
if (serializer_buffer_threshold >= 64 && serializer_buffer_threshold <= 1024 * 64) {
BUFFER_THRESHOLD = serializer_buffer_threshold * 1024;
}
}
} catch (Throwable error) {
// skip
}
}
存储当前设定值的缓冲区域的值为BUFFER_THRESHO
此时就多了一个SeriallzeWriter类型的out对象了
再次往下运行代码,进入异常处理区域
try {
JSONSerializer serializer = new JSONSerializer(out, config);
if (dateFormat != null && dateFormat.length() != 0) {
serializer.setDateFormat(dateFormat);
serializer.config(SerializerFeature.WriteDateUseDateFormat, true);
}
if (filters != null) {
for (SerializeFilter filter : filters) {
serializer.addFilter(filter);
}
}
serializer.write(object);
return out.toString();
} finally {
out.close();
}
这里首先是新建了一个JSONSerializer对象,将刚才新建的SeriallzeWriter类型的out对象,以及SerializeConfig类型的config对象,作为参数传入
JSONSerializer serializer = new JSONSerializer(out, config);
通过JSONSerializer类的构造方法,赋值给当前对象的指定对象中
public JSONSerializer(SerializeWriter out, SerializeConfig config){
this.out = out;
this.config = config;
}
这个类是对JSON解析的序列化,除了要根据规则
还要对时区和语言进行一个初始化设置
// 时区 本质上使用的是java.util.TimeZone,TimeZone使用的也是sun.util.calendar.ZoneInfo
protected TimeZone timeZone = JSON.defaultTimeZone;
// 语言
protected Locale locale = JSON.defaultLocale;
执行完这一步,将结果返回到变量中
因为此处dataformat为空,所以直接跳过下面代码
if (dateFormat != null && dateFormat.length() != 0) {
serializer.setDateFormat(dateFormat);
serializer.config(SerializerFeature.WriteDateUseDateFormat, true);
}
执行
if (filters != null) {
for (SerializeFilter filter : filters) {
serializer.addFilter(filter);
}
}
所有前置准备都执行完毕后,现在将我们输入的对象写进JSONSerializer类型的变量serializer中
serializer.write(object);
下面为JSONSerializer.write方法
public final void write(Object object) {
if (object == null) {
out.writeNull();
return;
}
Class<?> clazz = object.getClass();
ObjectSerializer writer = getObjectWriter(clazz);
try {
writer.write(this, object, null, null, 0);
} catch (IOException e) {
throw new JSONException(e.getMessage(), e);
}
}
此处,在对传入对象进行一个判空操作以后,使用getClass()方法获得object运行时额类
Class<?> clazz = object.getClass();
此处是利用到了Java的反射,所谓反射,可以理解为在运行Java代码时获取对象类型信息的操作,即动态获取对象运行类型信息。
然后将获取到的类型,获取到制定的序列化方法,一个ObjectSerializer类型的对象,此处为writer
public ObjectSerializer getObjectWriter(Class<?> clazz) {
return config.getObjectWriter(clazz);
}
然后就是写入
writer.write(this, object, null, null, 0);
} catch (IOException e) {
throw new JSONException(e.getMessage(), e);
还记得刚才利用SerializeWriter分配的缓存空间吗,刚才在JSONSerializer类中进行的写入操作的数据,其实都放在缓存空间中
所以,最后一步的操作就是讲缓存空间中的数据转换为字符类型,并返回
return out.toString();
至此,一个对象解析为JSON格式的字符串的整个流程我们就走完了。
2.parseObject(String,Class)
变成JSON的格式的字符串还是字符串,不是一个JSON对象,所以这里我们还需要使用parseObject方法来将上面个我们得到的字符串转换为JSON对象
在测试代码中加上:
JSONObject jsonObject = JSON.parseObject(jsonString);
以下是JSON.parseObject()方法的源码
public static JSONObject parseObject(String text) {
Object obj = parse(text);
if (obj instanceof JSONObject) {
return (JSONObject) obj;
}
try {
return (JSONObject) JSON.toJSON(obj);
} catch (RuntimeException e) {
throw new JSONException("can not cast to JSONObject.", e);
}
}
在正式进行转换之前,FastJson还需要按照内置规范对字符串进行解析
public static Object parse(String text) {
return parse(text, DEFAULT_PARSER_FEATURE);
}
public static Object parse(String text, int features) {
return parse(text, ParserConfig.getGlobalInstance(), features);
}
public static Object parse(String text, ParserConfig config, int features) {
if (text == null) {
return null;
}
DefaultJSONParser parser = new DefaultJSONParser(text, config, features);
Object value = parser.parse();
parser.handleResovleTask(value);
parser.close();
return value;
}
连着进了三个方法,终于来到了正题
此时的变量如下:
[
将传入的三个值作为参数,新建一个DefaultJSONParser类型的对象,构建一个默认的 解析器
DefaultJSONParser parser = new DefaultJSONParser(text, config, features);
这里主要是进行了一个字节码格式的添加,斗胆猜测是为了提高解析的速度,故先内置一些常用的数据类型
private final static Set<Class<?>> primitiveClasses = new HashSet<Class<?>>();
static {
Class<?>[] classes = new Class[] {
boolean.class,
byte.class,
short.class,
int.class,
long.class,
float.class,
double.class,
Boolean.class,
Byte.class,
Short.class,
Integer.class,
Long.class,
Float.class,
Double.class,
BigInteger.class,
BigDecimal.class,
String.class
};
primitiveClasses.addAll(Arrays.asList(classes));
}
于是我们就有了一个默认的解析器
[
使用其parse方法对 传入的对象进行解析
Object value = parser.parse();
这个解析方法源码如下:
public Object parse(Object fieldName) {
final JSONLexer lexer = this.lexer;
switch (lexer.token()) {
case SET:
lexer.nextToken();
HashSet<Object> set = new HashSet<Object>();
parseArray(set, fieldName);
return set;
case TREE_SET:
lexer.nextToken();
TreeSet<Object> treeSet = new TreeSet<Object>();
parseArray(treeSet, fieldName);
return treeSet;
case LBRACKET:
JSONArray array = new JSONArray();
parseArray(array, fieldName);
if (lexer.isEnabled(Feature.UseObjectArray)) {
return array.toArray();
}
return array;
case LBRACE:
JSONObject object = new JSONObject(lexer.isEnabled(Feature.OrderedField));
return parseObject(object, fieldName);
// case LBRACE: {
// Map<String, Object> map = lexer.isEnabled(Feature.OrderedField)
// ? new LinkedHashMap<String, Object>()
// : new HashMap<String, Object>();
// Object obj = parseObject(map, fieldName);
// if (obj != map) {
// return obj;
// }
// return new JSONObject(map);
// }
case LITERAL_INT:
Number intValue = lexer.integerValue();
lexer.nextToken();
return intValue;
case LITERAL_FLOAT:
Object value = lexer.decimalValue(lexer.isEnabled(Feature.UseBigDecimal));
lexer.nextToken();
return value;
case LITERAL_STRING:
String stringLiteral = lexer.stringVal();
lexer.nextToken(JSONToken.COMMA);
if (lexer.isEnabled(Feature.AllowISO8601DateFormat)) {
JSONScanner iso8601Lexer = new JSONScanner(stringLiteral);
try {
if (iso8601Lexer.scanISO8601DateIfMatch()) {
return iso8601Lexer.getCalendar().getTime();
}
} finally {
iso8601Lexer.close();
}
}
return stringLiteral;
case NULL:
lexer.nextToken();
return null;
case UNDEFINED:
lexer.nextToken();
return null;
case TRUE:
lexer.nextToken();
return Boolean.TRUE;
case FALSE:
lexer.nextToken();
return Boolean.FALSE;
case NEW:
lexer.nextToken(JSONToken.IDENTIFIER);
if (lexer.token() != JSONToken.IDENTIFIER) {
throw new JSONException("syntax error");
}
lexer.nextToken(JSONToken.LPAREN);
accept(JSONToken.LPAREN);
long time = lexer.integerValue().longValue();
accept(JSONToken.LITERAL_INT);
accept(JSONToken.RPAREN);
return new Date(time);
case EOF:
if (lexer.isBlankInput()) {
return null;
}
throw new JSONException("unterminated json string, " + lexer.info());
case HEX:
byte[] bytes = lexer.bytesValue();
lexer.nextToken();
return bytes;
case IDENTIFIER:
String identifier = lexer.stringVal();
if ("NaN".equals(identifier)) {
lexer.nextToken();
return null;
}
throw new JSONException("syntax error, " + lexer.info());
case ERROR:
default:
throw new JSONException("syntax error, " + lexer.info());
}
}
内容过于变态,吓得我跳了出去
经过解析后的数据如下:
然后就是jsonObject格式的转换了
parser.handleResovleTask(value);
底层代码依旧变态
public void handleResovleTask(Object value) {
if (resolveTaskList == null) {
return;
}
for (int i = 0, size = resolveTaskList.size(); i < size; ++i) {
ResolveTask task = resolveTaskList.get(i);
String ref = task.referenceValue;
Object object = null;
if (task.ownerContext != null) {
object = task.ownerContext.object;
}
Object refValue;
if (ref.startsWith("$")) {
refValue = getObject(ref);
if (refValue == null) {
try {
JSONPath jsonpath = JSONPath.compile(ref);
if (jsonpath.isRef()) {
refValue = jsonpath.eval(value);
}
} catch (JSONPathException ex) {
// skip
}
}
} else {
refValue = task.context.object;
}
FieldDeserializer fieldDeser = task.fieldDeserializer;
if (fieldDeser != null) {
if (refValue != null
&& refValue.getClass() == JSONObject.class
&& fieldDeser.fieldInfo != null
&& !Map.class.isAssignableFrom(fieldDeser.fieldInfo.fieldClass)) {
Object root = this.contextArray[0].object;
JSONPath jsonpath = JSONPath.compile(ref);
if (jsonpath.isRef()) {
refValue = jsonpath.eval(root);
}
}
// workaround for bug
if (fieldDeser.getOwnerClass() != null
&& (!fieldDeser.getOwnerClass().isInstance(object))
&& task.ownerContext.parent != null
) {
for (ParseContext ctx = task.ownerContext.parent;ctx != null;ctx = ctx.parent) {
if (fieldDeser.getOwnerClass().isInstance(ctx.object)) {
object = ctx.object;
break;
}
}
}
fieldDeser.setValue(object, refValue);
}
}
}
不过我们可以依稀看见是在利用数据组装JSON了(哈哈
最后,我们终于获取到了想要的JSON数据