fastjson是阿里巴巴的开源JSON解析库,它可以解析JSON格式的字符串,支持将Java Bean序列化为JSON字符串,也可以从JSON字符串反序列化到JavaBean。
fastjson相对其他JSON库的特点是快,从2011年fastjson发布1.1.x版本之后,其性能从未被其他Java实现的JSON库超越。
fastjson在阿里巴巴大规模使用,在数万台服务器上部署,fastjson在业界被广泛接受。在2012年被开源中国评选为最受欢迎的国产开源软件之一。
fastjson有非常多的testcase,在1.2.11版本中,testcase超过3321个。每次发布都会进行回归测试,保证质量稳定。
fastjson的API十分简洁。
String text = JSON.toJSONString(obj); //序列化
VO vo = JSON.parseObject("{...}", VO.class); //反序列化
支持泛型,支持流处理超大文本,支持枚举,支持序列化和反序列化扩展。
//(1)将对象转化成json
FastJsonExample example = new FastJsonExample();
example.setId(1);
example.setNick_name("男神");
example.setRealName("石叶");
String jsonExample = JSON.toJSONString(example);
System.out.println("java object convert to json="+jsonExample);
public static String toJSONString(Object object) {
return toJSONString(object, emptyFilters); // emptyFilters = new SerializeFilter[0]
}
public static String toJSONString(Object object, SerializeFilter[] filters, SerializerFeature... features) {
return toJSONString(object, SerializeConfig.globalInstance, filters, null, DEFAULT_GENERATE_FEATURE, features);
}
其中 SerializeConfig.globalInstance = new SerializeConfig();
目的主要是去初始化serializers
public SerializeConfig() {
this(IdentityHashMap.DEFAULT_SIZE); //默认大小8192
}
public SerializeConfig(int tableSize) {
this(tableSize, false);
}
public SerializeConfig(int tableSize, boolean fieldBase) {
//默认false
this.fieldBased = fieldBase;
serializers = new IdentityHashMap(tableSize);
this.mixInSerializers = new IdentityHashMap>(16);
try {
if (asm) {
asmFactory = new ASMSerializerFactory();
}
} catch (Throwable eror) {
asm = false;
}
//重点
initSerializers();
}
初始化serializers,将class类型 与对应的serializer做缓存,以1.2.62为例在com.alibaba.fastjson.serializer包下
private void initSerializers() {
put(Boolean.class, BooleanCodec.instance);
put(Character.class, CharacterCodec.instance);
put(Byte.class, IntegerCodec.instance);
put(Short.class, IntegerCodec.instance);
put(Integer.class, IntegerCodec.instance);
put(Long.class, LongCodec.instance);
put(Float.class, FloatCodec.instance);
put(Double.class, DoubleSerializer.instance);
put(BigDecimal.class, BigDecimalCodec.instance);
put(BigInteger.class, BigIntegerCodec.instance);
put(String.class, StringCodec.instance);
put(byte[].class, PrimitiveArraySerializer.instance);
put(short[].class, PrimitiveArraySerializer.instance);
put(int[].class, PrimitiveArraySerializer.instance);
put(long[].class, PrimitiveArraySerializer.instance);
put(float[].class, PrimitiveArraySerializer.instance);
put(double[].class, PrimitiveArraySerializer.instance);
put(boolean[].class, PrimitiveArraySerializer.instance);
put(char[].class, PrimitiveArraySerializer.instance);
put(Object[].class, ObjectArrayCodec.instance);
put(Class.class, MiscCodec.instance);
put(SimpleDateFormat.class, MiscCodec.instance);
put(Currency.class, new MiscCodec());
put(TimeZone.class, MiscCodec.instance);
put(InetAddress.class, MiscCodec.instance);
put(Inet4Address.class, MiscCodec.instance);
put(Inet6Address.class, MiscCodec.instance);
put(InetSocketAddress.class, MiscCodec.instance);
put(File.class, MiscCodec.instance);
put(Appendable.class, AppendableSerializer.instance);
put(StringBuffer.class, AppendableSerializer.instance);
put(StringBuilder.class, AppendableSerializer.instance);
put(Charset.class, ToStringSerializer.instance);
put(Pattern.class, ToStringSerializer.instance);
put(Locale.class, ToStringSerializer.instance);
put(URI.class, ToStringSerializer.instance);
put(URL.class, ToStringSerializer.instance);
put(UUID.class, ToStringSerializer.instance);
// atomic
put(AtomicBoolean.class, AtomicCodec.instance);
put(AtomicInteger.class, AtomicCodec.instance);
put(AtomicLong.class, AtomicCodec.instance);
put(AtomicReference.class, ReferenceCodec.instance);
put(AtomicIntegerArray.class, AtomicCodec.instance);
put(AtomicLongArray.class, AtomicCodec.instance);
put(WeakReference.class, ReferenceCodec.instance);
put(SoftReference.class, ReferenceCodec.instance);
put(LinkedList.class, CollectionCodec.instance);
}
public boolean put(Type type, ObjectSerializer value) {
Type mixin = JSON.getMixInAnnotations(type);
if (mixin != null) {
IdentityHashMap mixInClasses = this.mixInSerializers.get(type);
if (mixInClasses == null) {
//多线程下可能会重复创建,但不影响正确性
mixInClasses = new IdentityHashMap(4);
mixInSerializers.put(type, mixInClasses);
}
return mixInClasses.put(mixin, value);
}
return this.serializers.put(type, value);
}
public static String toJSONString(Object object, //
SerializeConfig config, //
SerializeFilter[] filters, //
String dateFormat, //
int defaultFeatures, //
SerializerFeature... features) {
//初始化SerializeWriter
SerializeWriter out = new SerializeWriter(null, defaultFeatures, features);
try {
//传入writer及config
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();
}
}
public SerializeWriter(Writer writer, int defaultFeatures, SerializerFeature... features){
this.writer = writer;
buf = bufLocal.get();
if (buf != null) {
bufLocal.set(null);
} else {
buf = new char[2048];
}
int featuresValue = defaultFeatures;
for (SerializerFeature feature : features) {
featuresValue |= feature.getMask();
}
this.features = featuresValue;
//使用&操作判断是否包含该features
computeFeatures();
}
public final void write(Object object) {
//如果为null则写入"null"
if (object == null) {
out.writeNull();
return;
}
//获取class
Class> clazz = object.getClass();
//获取class对应的serializer
ObjectSerializer writer = getObjectWriter(clazz);
try {
writer.write(this, object, null, null, 0);
} catch (IOException e) {
throw new JSONException(e.getMessage(), e);
}
}
public ObjectSerializer getObjectWriter(Class> clazz) {
return config.getObjectWriter(clazz);
}
public ObjectSerializer getObjectWriter(Class> clazz) {
return getObjectWriter(clazz, true);
}
private ObjectSerializer getObjectWriter(Class> clazz, boolean create) {
ObjectSerializer writer = get(clazz);
if (writer == null) {
try {
final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
for (Object o : ServiceLoader.load(AutowiredObjectSerializer.class, classLoader)) {
if (!(o instanceof AutowiredObjectSerializer)) {
continue;
}
AutowiredObjectSerializer autowired = (AutowiredObjectSerializer) o;
for (Type forType : autowired.getAutowiredFor()) {
put(forType, autowired);
}
}
} catch (ClassCastException ex) {
// skip
}
writer = get(clazz);
}
if (writer == null) {
final ClassLoader classLoader = JSON.class.getClassLoader();
if (classLoader != Thread.currentThread().getContextClassLoader()) {
try {
for (Object o : ServiceLoader.load(AutowiredObjectSerializer.class, classLoader)) {
if (!(o instanceof AutowiredObjectSerializer)) {
continue;
}
AutowiredObjectSerializer autowired = (AutowiredObjectSerializer) o;
for (Type forType : autowired.getAutowiredFor()) {
put(forType, autowired);
}
}
} catch (ClassCastException ex) {
// skip
}
writer = get(clazz);
}
}
for (Module module : modules) {
writer = module.createSerializer(this, clazz);
if (writer != null) {
put(clazz, writer);
return writer;
}
}
if (writer == null) {
String className = clazz.getName();
Class> superClass;
if (Map.class.isAssignableFrom(clazz)) {
put(clazz, writer = MapSerializer.instance);
} else if (List.class.isAssignableFrom(clazz)) {
put(clazz, writer = ListSerializer.instance);
} else if (Collection.class.isAssignableFrom(clazz)) {
put(clazz, writer = CollectionCodec.instance);
} else if (Date.class.isAssignableFrom(clazz)) {
put(clazz, writer = DateCodec.instance);
} else if (JSONAware.class.isAssignableFrom(clazz)) {
put(clazz, writer = JSONAwareSerializer.instance);
} else if (JSONSerializable.class.isAssignableFrom(clazz)) {
put(clazz, writer = JSONSerializableSerializer.instance);
} else if (JSONStreamAware.class.isAssignableFrom(clazz)) {
put(clazz, writer = MiscCodec.instance);
} else if (clazz.isEnum()) {
JSONType jsonType = TypeUtils.getAnnotation(clazz, JSONType.class);
if (jsonType != null && jsonType.serializeEnumAsJavaBean()) {
put(clazz, writer = createJavaBeanSerializer(clazz));
} else {
put(clazz, writer = EnumSerializer.instance);
}
} else if ((superClass = clazz.getSuperclass()) != null && superClass.isEnum()) {
JSONType jsonType = TypeUtils.getAnnotation(superClass, JSONType.class);
if (jsonType != null && jsonType.serializeEnumAsJavaBean()) {
put(clazz, writer = createJavaBeanSerializer(clazz));
} else {
put(clazz, writer = EnumSerializer.instance);
}
} else if (clazz.isArray()) {
Class> componentType = clazz.getComponentType();
ObjectSerializer compObjectSerializer = getObjectWriter(componentType);
put(clazz, writer = new ArraySerializer(componentType, compObjectSerializer));
} else if (Throwable.class.isAssignableFrom(clazz)) {
SerializeBeanInfo beanInfo = TypeUtils.buildBeanInfo(clazz, null, propertyNamingStrategy);
beanInfo.features |= SerializerFeature.WriteClassName.mask;
put(clazz, writer = new JavaBeanSerializer(beanInfo));
} else if (TimeZone.class.isAssignableFrom(clazz) || Map.Entry.class.isAssignableFrom(clazz)) {
put(clazz, writer = MiscCodec.instance);
} else if (Appendable.class.isAssignableFrom(clazz)) {
put(clazz, writer = AppendableSerializer.instance);
} else if (Charset.class.isAssignableFrom(clazz)) {
put(clazz, writer = ToStringSerializer.instance);
} else if (Enumeration.class.isAssignableFrom(clazz)) {
put(clazz, writer = EnumerationSerializer.instance);
} else if (Calendar.class.isAssignableFrom(clazz) //
|| XMLGregorianCalendar.class.isAssignableFrom(clazz)) {
put(clazz, writer = CalendarCodec.instance);
} else if (TypeUtils.isClob(clazz)) {
put(clazz, writer = ClobSeriliazer.instance);
} else if (TypeUtils.isPath(clazz)) {
put(clazz, writer = ToStringSerializer.instance);
} else if (Iterator.class.isAssignableFrom(clazz)) {
put(clazz, writer = MiscCodec.instance);
} else if (org.w3c.dom.Node.class.isAssignableFrom(clazz)) {
put(clazz, writer = MiscCodec.instance);
} else {
if (className.startsWith("java.awt.") //
&& AwtCodec.support(clazz) //
) {
// awt
if (!awtError) {
try {
String[] names = new String[]{
"java.awt.Color",
"java.awt.Font",
"java.awt.Point",
"java.awt.Rectangle"
};
for (String name : names) {
if (name.equals(className)) {
put(Class.forName(name), writer = AwtCodec.instance);
return writer;
}
}
} catch (Throwable e) {
awtError = true;
// skip
}
}
}
// jdk8
if ((!jdk8Error) //
&& (className.startsWith("java.time.") //
|| className.startsWith("java.util.Optional") //
|| className.equals("java.util.concurrent.atomic.LongAdder")
|| className.equals("java.util.concurrent.atomic.DoubleAdder")
)) {
try {
{
String[] names = new String[]{
"java.time.LocalDateTime",
"java.time.LocalDate",
"java.time.LocalTime",
"java.time.ZonedDateTime",
"java.time.OffsetDateTime",
"java.time.OffsetTime",
"java.time.ZoneOffset",
"java.time.ZoneRegion",
"java.time.Period",
"java.time.Duration",
"java.time.Instant"
};
for (String name : names) {
if (name.equals(className)) {
put(Class.forName(name), writer = Jdk8DateCodec.instance);
return writer;
}
}
}
{
String[] names = new String[]{
"java.util.Optional",
"java.util.OptionalDouble",
"java.util.OptionalInt",
"java.util.OptionalLong"
};
for (String name : names) {
if (name.equals(className)) {
put(Class.forName(name), writer = OptionalCodec.instance);
return writer;
}
}
}
{
String[] names = new String[]{
"java.util.concurrent.atomic.LongAdder",
"java.util.concurrent.atomic.DoubleAdder"
};
for (String name : names) {
if (name.equals(className)) {
put(Class.forName(name), writer = AdderSerializer.instance);
return writer;
}
}
}
} catch (Throwable e) {
// skip
jdk8Error = true;
}
}
if ((!oracleJdbcError) //
&& className.startsWith("oracle.sql.")) {
try {
String[] names = new String[] {
"oracle.sql.DATE",
"oracle.sql.TIMESTAMP"
};
for (String name : names) {
if (name.equals(className)) {
put(Class.forName(name), writer = DateCodec.instance);
return writer;
}
}
} catch (Throwable e) {
// skip
oracleJdbcError = true;
}
}
if ((!springfoxError) //
&& className.equals("springfox.documentation.spring.web.json.Json")) {
try {
put(Class.forName("springfox.documentation.spring.web.json.Json"), //
writer = SwaggerJsonSerializer.instance);
return writer;
} catch (ClassNotFoundException e) {
// skip
springfoxError = true;
}
}
if ((!guavaError) //
&& className.startsWith("com.google.common.collect.")) {
try {
String[] names = new String[] {
"com.google.common.collect.HashMultimap",
"com.google.common.collect.LinkedListMultimap",
"com.google.common.collect.LinkedHashMultimap",
"com.google.common.collect.ArrayListMultimap",
"com.google.common.collect.TreeMultimap"
};
for (String name : names) {
if (name.equals(className)) {
put(Class.forName(name), writer = GuavaCodec.instance);
return writer;
}
}
} catch (ClassNotFoundException e) {
// skip
guavaError = true;
}
}
if ((!jsonnullError) && className.equals("net.sf.json.JSONNull")) {
try {
put(Class.forName("net.sf.json.JSONNull"), writer = MiscCodec.instance);
return writer;
} catch (ClassNotFoundException e) {
// skip
jsonnullError = true;
}
}
if (!jsonobjectError && className.equals("org.json.JSONObject")) {
try {
put(Class.forName("org.json.JSONObject"), writer = JSONObjectCodec.instance);
return writer;
} catch (ClassNotFoundException e) {
// skip
jsonobjectError = true;
}
}
if ((!jodaError) && className.startsWith("org.joda.")) {
try {
String[] names = new String[] {
"org.joda.time.LocalDate",
"org.joda.time.LocalDateTime",
"org.joda.time.LocalTime",
"org.joda.time.Instant",
"org.joda.time.DateTime",
"org.joda.time.Period",
"org.joda.time.Duration",
"org.joda.time.DateTimeZone",
"org.joda.time.UTCDateTimeZone",
"org.joda.time.tz.CachedDateTimeZone",
"org.joda.time.tz.FixedDateTimeZone",
};
for (String name : names) {
if (name.equals(className)) {
put(Class.forName(name), writer = JodaCodec.instance);
return writer;
}
}
} catch (ClassNotFoundException e) {
// skip
jodaError = true;
}
}
if ("java.nio.HeapByteBuffer".equals(className)) {
put(clazz, writer = ByteBufferCodec.instance);
return writer;
}
if ("org.javamoney.moneta.Money".equals(className)) {
put(clazz, writer = MonetaCodec.instance);
return writer;
}
Class[] interfaces = clazz.getInterfaces();
if (interfaces.length == 1 && interfaces[0].isAnnotation()) {
put(clazz, AnnotationSerializer.instance);
return AnnotationSerializer.instance;
}
if (TypeUtils.isProxy(clazz)) {
Class> superClazz = clazz.getSuperclass();
ObjectSerializer superWriter = getObjectWriter(superClazz);
put(clazz, superWriter);
return superWriter;
}
if (Proxy.isProxyClass(clazz)) {
Class handlerClass = null;
if (interfaces.length == 2) {
handlerClass = interfaces[1];
} else {
for (Class proxiedInterface : interfaces) {
if (proxiedInterface.getName().startsWith("org.springframework.aop.")) {
continue;
}
if (handlerClass != null) {
handlerClass = null; // multi-matched
break;
}
handlerClass = proxiedInterface;
}
}
if (handlerClass != null) {
ObjectSerializer superWriter = getObjectWriter(handlerClass);
put(clazz, superWriter);
return superWriter;
}
}
//以上都不符合 创建serializer
if (create) {
writer = createJavaBeanSerializer(clazz);
put(clazz, writer);
}
}
if (writer == null) {
writer = get(clazz);
}
}
return writer;
}
public final ObjectSerializer createJavaBeanSerializer(Class> clazz) {
//获取class名称
String className = clazz.getName();
//转换成hashcode
long hashCode64 = TypeUtils.fnv1a_64(className);
if (Arrays.binarySearch(denyClasses, hashCode64) >= 0) {
throw new JSONException("not support class : " + className);
}
//将对象信息转化成SerializeBeanInfo
SerializeBeanInfo beanInfo = TypeUtils.buildBeanInfo(clazz, null, propertyNamingStrategy, fieldBased);
if (beanInfo.fields.length == 0 && Iterable.class.isAssignableFrom(clazz)) {
return MiscCodec.instance;
}
//创建真正的JavaBeanSerializer
return createJavaBeanSerializer(beanInfo);
}
public JavaBeanSerializer(SerializeBeanInfo beanInfo) {
this.beanInfo = beanInfo;
//字段的Serializer
sortedGetters = new FieldSerializer[beanInfo.sortedFields.length];
for (int i = 0; i < sortedGetters.length; ++i) {
sortedGetters[i] = new FieldSerializer(beanInfo.beanType, beanInfo.sortedFields[i]);
}
if (beanInfo.fields == beanInfo.sortedFields) {
getters = sortedGetters;
} else {
getters = new FieldSerializer[beanInfo.fields.length];
boolean hashNotMatch = false;
for (int i = 0; i < getters.length; ++i) {
FieldSerializer fieldSerializer = getFieldSerializer(beanInfo.fields[i].name);
if (fieldSerializer == null) {
hashNotMatch = true;
break;
}
getters[i] = fieldSerializer;
}
if (hashNotMatch) {
System.arraycopy(sortedGetters, 0, getters, 0, sortedGetters.length);
}
}
if (beanInfo.jsonType != null) {
for (Class extends SerializeFilter> filterClass : beanInfo.jsonType.serialzeFilters()) {
try {
SerializeFilter filter = filterClass.getConstructor().newInstance();
this.addFilter(filter);
} catch (Exception e) {
// skip
}
}
}
if (beanInfo.jsonType != null) {
for (Class extends SerializeFilter> filterClass : beanInfo.jsonType.serialzeFilters()) {
try {
SerializeFilter filter = filterClass.getConstructor().newInstance();
this.addFilter(filter);
} catch (Exception e) {
// skip
}
}
}
}
针对转化有许多优化如使用buffer缓冲,string.subline 针对asm spring的特殊优化等
问题1 1.2.14版本前对 “_” 等特殊符号开头的字段兼容不够
问题2 存在硬编码
问题3 存在漏洞
问题4 社区不完善,英文文档不完善