• 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);
    }
    }
    }

      

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



  • 相关阅读:
    改造MFC程序,使原来不支持winsocket的工程支持winsocket
    算术移位和逻辑移位实现分析
    MFC 编辑框中字体大小改变,行高不能改变,只能显示一半的问题,已解决。
    在MFC中,使用控制台Console输出调试信息
    在MFC中使用GDI+的一般方法,以VC6.0编译器为例
    WinForm 实现主程序(exe)与其关联类库(*.dll)分开存放
    Deserializing/Serializing SOAP Messages in C#
    List分页
    ConvertJavaMiliSecondToDateTime
    中文数字大小写转阿拉伯数字
  • 原文地址:https://www.cnblogs.com/zqsky/p/7028577.html
Copyright © 2020-2023  润新知