gson和fastjson将json对象转换成javaBean 简单对照

今天在网上看代码时,发现项目使用了Gson,用于将json字符串转换成javaBean.

以前没使用过Gson,随即,简单入了个们,

想起fastjson也有将json字符串转换成javaBean的API,随即简单比较了下源码.

fastjson中的API如下:

    /**
     * @since 1.2.9
     */
    public <T> T toJavaObject(Class<T> clazz) {
        return TypeUtils.cast(this, clazz, ParserConfig.getGlobalInstance());
    }



    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static <T> T cast(Object obj, Class<T> clazz, ParserConfig config) {
        if (obj == null) {
            return null;
        }

        if (clazz == null) {
            throw new IllegalArgumentException("clazz is null");
        }

        if (clazz == obj.getClass()) {
            return (T) obj;
        }

        if (obj instanceof Map) {
            if (clazz == Map.class) {
                return (T) obj;
            }

            Map map = (Map) obj;
            if (clazz == Object.class && !map.containsKey(JSON.DEFAULT_TYPE_KEY)) {
                return (T) obj;
            }

            return castToJavaBean((Map<String, Object>) obj, clazz, config);
        }

        if (clazz.isArray()) {
            if (obj instanceof Collection) {

                Collection collection = (Collection) obj;
                int index = 0;
                Object array = Array.newInstance(clazz.getComponentType(), collection.size());
                for (Object item : collection) {
                    Object value = cast(item, clazz.getComponentType(), config);
                    Array.set(array, index, value);
                    index++;
                }

                return (T) array;
            }

            if (clazz == byte[].class) {
                return (T) castToBytes(obj);
            }
        }

        if (clazz.isAssignableFrom(obj.getClass())) {
            return (T) obj;
        }

        if (clazz == boolean.class || clazz == Boolean.class) {
            return (T) castToBoolean(obj);
        }

        if (clazz == byte.class || clazz == Byte.class) {
            return (T) castToByte(obj);
        }

        // if (clazz == char.class || clazz == Character.class) {
        // return (T) castToCharacter(obj);
        // }

        if (clazz == short.class || clazz == Short.class) {
            return (T) castToShort(obj);
        }

        if (clazz == int.class || clazz == Integer.class) {
            return (T) castToInt(obj);
        }

        if (clazz == long.class || clazz == Long.class) {
            return (T) castToLong(obj);
        }

        if (clazz == float.class || clazz == Float.class) {
            return (T) castToFloat(obj);
        }

        if (clazz == double.class || clazz == Double.class) {
            return (T) castToDouble(obj);
        }

        if (clazz == String.class) {
            return (T) castToString(obj);
        }

        if (clazz == BigDecimal.class) {
            return (T) castToBigDecimal(obj);
        }

        if (clazz == BigInteger.class) {
            return (T) castToBigInteger(obj);
        }

        if (clazz == Date.class) {
            return (T) castToDate(obj);
        }

        if (clazz == java.sql.Date.class) {
            return (T) castToSqlDate(obj);
        }

        if (clazz == java.sql.Timestamp.class) {
            return (T) castToTimestamp(obj);
        }

        if (clazz.isEnum()) {
            return (T) castToEnum(obj, clazz, config);
        }

        if (Calendar.class.isAssignableFrom(clazz)) {
            Date date = castToDate(obj);
            Calendar calendar;
            if (clazz == Calendar.class) {
                calendar = Calendar.getInstance(JSON.defaultTimeZone, JSON.defaultLocale);
            } else {
                try {
                    calendar = (Calendar) clazz.newInstance();
                } catch (Exception e) {
                    throw new JSONException("can not cast to : " + clazz.getName(), e);
                }
            }
            calendar.setTime(date);
            return (T) calendar;
        }

        if (obj instanceof String) {
            String strVal = (String) obj;

            if (strVal.length() == 0 //
                || "null".equals(strVal) //
                || "NULL".equals(strVal)) {
                return null;
            }

            if (clazz == java.util.Currency.class) {
                return (T) java.util.Currency.getInstance(strVal);
            }
        }

        throw new JSONException("can not cast to : " + clazz.getName());
    }





    @SuppressWarnings({ "unchecked" })
    public static <T> T castToJavaBean(Map<String, Object> map, Class<T> clazz, ParserConfig config) {
        try {
            if (clazz == StackTraceElement.class) {
                String declaringClass = (String) map.get("className");
                String methodName = (String) map.get("methodName");
                String fileName = (String) map.get("fileName");
                int lineNumber;
                {
                    Number value = (Number) map.get("lineNumber");
                    if (value == null) {
                        lineNumber = 0;
                    } else {
                        lineNumber = value.intValue();
                    }
                }

                return (T) new StackTraceElement(declaringClass, methodName, fileName, lineNumber);
            }

            {
                Object iClassObject = map.get(JSON.DEFAULT_TYPE_KEY);
                if (iClassObject instanceof String) {
                    String className = (String) iClassObject;

                    Class<?> loadClazz = (Class<T>) loadClass(className);

                    if (loadClazz == null) {
                        throw new ClassNotFoundException(className + " not found");
                    }

                    if (!loadClazz.equals(clazz)) {
                        return (T) castToJavaBean(map, loadClazz, config);
                    }
                }
            }

            if (clazz.isInterface()) {
                JSONObject object;

                if (map instanceof JSONObject) {
                    object = (JSONObject) map;
                } else {
                    object = new JSONObject(map);
                }

                return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                                                  new Class<?>[] { clazz }, object);
            }

            if (config == null) {
                config = ParserConfig.getGlobalInstance();
            }

            JavaBeanDeserializer javaBeanDeser = null;
            ObjectDeserializer deserizer = config.getDeserializer(clazz);
            if (deserizer instanceof JavaBeanDeserializer) {
                javaBeanDeser = (JavaBeanDeserializer) deserizer;
            }
            
            if (javaBeanDeser == null) {
                throw new JSONException("can not get javaBeanDeserializer");
            }
            
            return (T) javaBeanDeser.createInstance(map, config);
        } catch (Exception e) {
            throw new JSONException(e.getMessage(), e);
        }
    }

  简单捋了一遍,看到代码中标黄的部分代码,可知,是利用反射原理来获得javaBean的.

如下,为Gson的demo:

 1 package cn.code.gson;
 2 
 3 import java.io.*;
 4 
 5 import java.util.Map;
 6 
 7 import com.google.gson.Gson;
 8 import com.google.gson.GsonBuilder;
 9 
10 import cn.code.entity.Person;
11 
12 /**
13  * Created by zq on 2017/6/16.
14  */
15 public class GsonTest {
16 
17     /**
18      * @param args  主函数形参
19      */
20     public static void main(String[] args) {
21         Gson gson = new GsonBuilder().create();
22 
23         gson.toJson("Hello", System.out);
24         gson.toJson("123", System.out);
25         System.out.println();
26 
27 //      try (Writer writer = new FileWriter("d:\gson.txt")) {
28 //          gson.toJson("Hello", writer);
29 //          gson.toJson("123", writer);
30 //      } catch (IOException e) {
31 //          e.printStackTrace();
32 //      }
33         FileInputStream fileInputStream = null;
34 
35         try {
36             fileInputStream = new FileInputStream("d:\gson.txt");
37         } catch (FileNotFoundException e) {
38             e.printStackTrace();
39         }
40 
41         Person person = getJavaBean(fileInputStream);
42 
43         System.out.println(person);
44     }
45 
46     /**
47      *
48      * @param fileInputStream 根据附件字节流 返回java类
49      * @return
50      */
51     public static Person getJavaBean(FileInputStream fileInputStream) {
52         Gson   gson   = new GsonBuilder().create();
53         Person person = null;
54 
55         try (Reader reader = new InputStreamReader(fileInputStream)) {
56             person = gson.fromJson(reader, Person.class);
57         } catch (FileNotFoundException e) {
58             e.printStackTrace();
59         } catch (IOException e) {
60             e.printStackTrace();
61         }
62 
63         return person;
64     }
65 }
66 
67 
68 //~ Formatted by Jindent --- http://www.jindent.com
View Code

 Gson中使用了如下代码获取javaBean:

person = gson.fromJson(reader, Person.class);
源码如下(版本:2.2.4):
 1   public <T> T fromJson(Reader json, Class<T> classOfT) throws JsonSyntaxException, JsonIOException {
 2     JsonReader jsonReader = new JsonReader(json);
 3     Object object = fromJson(jsonReader, classOfT);
 4     assertFullConsumption(object, jsonReader);
 5     return Primitives.wrap(classOfT).cast(object);
 6   }
 7 
 8 
 9   @SuppressWarnings("unchecked")
10   public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException {
11     boolean isEmpty = true;
12     boolean oldLenient = reader.isLenient();
13     reader.setLenient(true);
14     try {
15       reader.peek();
16       isEmpty = false;
17       TypeToken<T> typeToken = (TypeToken<T>) TypeToken.get(typeOfT);
18       TypeAdapter<T> typeAdapter = getAdapter(typeToken);
19       T object = typeAdapter.read(reader);
20       return object;
21     } catch (EOFException e) {
22       /*
23        * For compatibility with JSON 1.5 and earlier, we return null for empty
24        * documents instead of throwing.
25        */
26       if (isEmpty) {
27         return null;
28       }
29       throw new JsonSyntaxException(e);
30     } catch (IllegalStateException e) {
31       throw new JsonSyntaxException(e);
32     } catch (IOException e) {
33       // TODO(inder): Figure out whether it is indeed right to rethrow this as JsonSyntaxException
34       throw new JsonSyntaxException(e);
35     } finally {
36       reader.setLenient(oldLenient);
37     }
38   }

以上版本中,Json和javabean之间依赖于各类的TypeAdapter(类型转换器集合)获得:

TypeAdapter<?> cached = typeTokenCache.get(type);
if (cached != null) {
return (TypeAdapter<T>) cached;
}


以下是版本1.6中的部分核心源码:
private <T> T fromJsonObject(Type typeOfT, JsonObject jsonObject,
      JsonDeserializationContext context) throws JsonParseException {
    JsonObjectDeserializationVisitor<T> visitor = new JsonObjectDeserializationVisitor<T>(
        jsonObject, typeOfT, navigatorFactory, objectConstructor, deserializers, context);
    ObjectNavigator on = navigatorFactory.create(new ObjectTypePair(null, typeOfT, true));   //适配器模式
    on.accept(visitor);
    return visitor.getTarget();
  }


  /**
   * Navigate all the fields of the specified object. If a field is null, it
   * does not get visited.
   */
  public void accept(Visitor visitor) {
    TypeInfo objTypeInfo = new TypeInfo(objTypePair.type);
    if (exclusionStrategy.shouldSkipClass(objTypeInfo.getRawClass())) {
      return;
    }
    boolean visitedWithCustomHandler = visitor.visitUsingCustomHandler(objTypePair);
    if (!visitedWithCustomHandler) {
      Object obj = objTypePair.getObject();
      Object objectToVisit = (obj == null) ? visitor.getTarget() : obj;
      if (objectToVisit == null) {
        return;
      }
      objTypePair.setObject(objectToVisit);
      visitor.start(objTypePair);
      try {
        if (objTypeInfo.isArray()) {
          visitor.visitArray(objectToVisit, objTypePair.type);
        } else if (objTypeInfo.getActualType() == Object.class
            && isPrimitiveOrString(objectToVisit)) {
          // TODO(Joel): this is only used for deserialization of "primitives"
          // we should rethink this!!!
          visitor.visitPrimitive(objectToVisit);
          objectToVisit = visitor.getTarget();
        } else {
          visitor.startVisitingObject(objectToVisit);
          ObjectTypePair currObjTypePair = objTypePair.toMoreSpecificType();
          Class<?> topLevelClass = new TypeInfo(currObjTypePair.type).getRawClass();
          for (Class<?> curr = topLevelClass; curr != null && !curr.equals(Object.class); curr =
              curr.getSuperclass()) {
            if (!curr.isSynthetic()) {
              navigateClassFields(objectToVisit, curr, visitor);
            }
          }
        }
      } finally {
        visitor.end(objTypePair);
      }
    }
  }
private void navigateClassFields(Object obj, Class<?> clazz, Visitor visitor) {
Field[] fields = clazz.getDeclaredFields();
AccessibleObject.setAccessible(fields, true);
for (Field f : fields) { //遍历javabean 的field 赋值
FieldAttributes fieldAttributes = new FieldAttributes(clazz, f);
if (exclusionStrategy.shouldSkipField(fieldAttributes)
|| exclusionStrategy.shouldSkipClass(fieldAttributes.getDeclaredClass())) {
continue; // skip
}
TypeInfo fieldTypeInfo = TypeInfoFactory.getTypeInfoForField(f, objTypePair.type);
Type declaredTypeOfField = fieldTypeInfo.getActualType();
boolean visitedWithCustomHandler =
visitor.visitFieldUsingCustomHandler(fieldAttributes, declaredTypeOfField, obj);
if (!visitedWithCustomHandler) {
if (fieldTypeInfo.isArray()) {
visitor.visitArrayField(fieldAttributes, declaredTypeOfField, obj);
} else {
visitor.visitObjectField(fieldAttributes, declaredTypeOfField, obj);
}
}
}

  

以上为粗略了解,甚至不算入门,有兴趣的小伙伴们可自行阅读源码.



原文地址:https://www.cnblogs.com/zqsky/p/7028577.html