Package com.firefly.utils.json

Source Code of com.firefly.utils.json.JsonSerializer

package com.firefly.utils.json;

import static com.firefly.utils.json.JsonStringSymbol.ARRAY_PRE;
import static com.firefly.utils.json.JsonStringSymbol.ARRAY_SUF;
import static com.firefly.utils.json.JsonStringSymbol.NULL;
import static com.firefly.utils.json.JsonStringSymbol.OBJ_PRE;
import static com.firefly.utils.json.JsonStringSymbol.OBJ_SEPARATOR;
import static com.firefly.utils.json.JsonStringSymbol.OBJ_SUF;
import static com.firefly.utils.json.JsonStringSymbol.QUOTE;
import static com.firefly.utils.json.JsonStringSymbol.SEPARATOR;

import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import com.firefly.utils.json.support.JsonClassCache;
import com.firefly.utils.json.support.JsonObjMetaInfo;
import com.firefly.utils.json.support.TypeVerify;
import com.firefly.utils.time.SafeSimpleDateFormat;

class JsonSerializer {
  private Writer writer;
  private Set<Object> existence; // 防止循环引用
  private ClassCache classCache;
  private static final JsonObjMetaInfo[] JOM = new JsonObjMetaInfo[0];

  public JsonSerializer(Writer writer) {
    this.writer = writer;
    existence = new HashSet<Object>();
    classCache = JsonClassCache.getInstance();
  }

  JsonSerializer toJson(Object obj) throws IOException {
    if (obj == null) {
      writer.append(NULL);
      return this;
    }
    Class<?> clazz = obj.getClass();
    if (TypeVerify.isNumberOrBool(clazz)) { // 数字,布尔类型
      writer.append(obj.toString());
    } else if (clazz.isEnum()) { // 枚举类型
      string2Json(((Enum<?>) obj).name());
    } else if (TypeVerify.isString(clazz)) { // 字符串或字符类型
      string2Json(obj.toString());
    } else if (TypeVerify.isDateLike(clazz)) {
      string2Json(SafeSimpleDateFormat.defaultDateFormat
          .format((Date) obj));
    } else if (existence.contains(obj)) { // 防止循环引用,此处会影响一些性能
      writer.append(NULL);
    } else {
      existence.add(obj);
      if (obj instanceof Map<?, ?>) {
        map2Json((Map<?, ?>) obj);
      } else if (obj instanceof Collection<?>) {
        collection2Json((Collection<?>) obj);
      } else if (clazz.isArray()) {
        array2Json(obj);
      } else { // pojo类型
        pojo2Json(obj);
      }
      existence.remove(obj);
    }
    return this;
  }

  private void pojo2Json(Object obj) throws IOException {
    if (obj == null)
      return;
    Class<?> clazz = obj.getClass();
    writer.append(OBJ_PRE);
    JsonObjMetaInfo[] jsonObjMetaInfo = classCache.get(clazz);
    if (jsonObjMetaInfo == null) {
      List<JsonObjMetaInfo> fieldList = new ArrayList<JsonObjMetaInfo>();
      Method[] methods = clazz.getMethods();
      for (int i = 0; i < methods.length; i++) {
        Method method = methods[i];
        method.setAccessible(true);
        String methodName = method.getName();

        if (Modifier.isStatic(method.getModifiers())
            || method.getReturnType().equals(Void.TYPE)
            || method.getParameterTypes().length != 0) {
          continue;
        }

        if (methodName.startsWith("get")) { // 取get方法的返回值
          if (methodName.length() < 4
              || methodName.equals("getClass")
              || !Character.isUpperCase(methodName.charAt(3))) {
            continue;
          }

          String propertyName = Character.toLowerCase(methodName
              .charAt(3)) + methodName.substring(4);

          Field field = null;
          try {
            field = clazz.getDeclaredField(propertyName);
          } catch (SecurityException e) {
            e.printStackTrace();
          } catch (NoSuchFieldException e) {
            e.printStackTrace();
          }

          if (field != null
              && Modifier.isTransient(field.getModifiers())) {
            continue;
          }

          try {
            JsonObjMetaInfo fieldSerializer = new JsonObjMetaInfo();
            fieldSerializer.setPropertyName(propertyName);
            fieldSerializer.setMethod(method);
            fieldList.add(fieldSerializer);
          } catch (IllegalArgumentException e) {
            e.printStackTrace();
          }
        } else if (methodName.startsWith("is")) { // 取is方法的返回值
          if (methodName.length() < 3
              || !Character.isUpperCase(methodName.charAt(2))) {
            continue;
          }

          String propertyName = Character.toLowerCase(methodName
              .charAt(2)) + methodName.substring(3);

          Field field = null;
          try {
            field = clazz.getDeclaredField(propertyName);
          } catch (SecurityException e) {
            e.printStackTrace();
          } catch (NoSuchFieldException e) {
            e.printStackTrace();
          }
          if (field != null
              && Modifier.isTransient(field.getModifiers())) {
            continue;
          }

          try {
            JsonObjMetaInfo fieldSerializer = new JsonObjMetaInfo();
            fieldSerializer.setPropertyName(propertyName);
            fieldSerializer.setMethod(method);
            fieldList.add(fieldSerializer);
          } catch (IllegalArgumentException e) {
            e.printStackTrace();
          }
        }
      }

      jsonObjMetaInfo = fieldList.toArray(JOM);
      classCache.put(clazz, jsonObjMetaInfo);
    }

    for (int i = 0; i < jsonObjMetaInfo.length; i++) {
      try {
        appendPair(jsonObjMetaInfo[i].getPropertyName(),
            jsonObjMetaInfo[i].getMethod().invoke(obj));
        if (i < jsonObjMetaInfo.length - 1)
          writer.append(SEPARATOR);
      } catch (IllegalArgumentException e) {
        e.printStackTrace();
      } catch (IllegalAccessException e) {
        e.printStackTrace();
      } catch (InvocationTargetException e) {
        e.printStackTrace();
      }
    }

    writer.append(OBJ_SUF);
  }

  @SuppressWarnings("unchecked")
  private void map2Json(Map map) throws IOException {
    if (map == null)
      return;
    writer.append(OBJ_PRE);
    Set<Entry<?, ?>> entrySet = map.entrySet();
    for (Iterator<Entry<?, ?>> it = entrySet.iterator(); it.hasNext();) {
      Entry<?, ?> entry = it.next();
      String name = entry.getKey() == null ? NULL : entry.getKey()
          .toString();
      Object val = entry.getValue();
      appendPair(name, val);
      if (it.hasNext())
        writer.append(SEPARATOR);
    }
    writer.append(OBJ_SUF);
  }

  private void string2Json(String s) throws IOException {
    if (s == null)
      writer.append(NULL);
    else {
      char[] cs = s.toCharArray();
      writer.append(QUOTE);
      for (char ch : cs) {
        switch (ch) {
        case '"':
          writer.append("\\\"");
          break;
        case '\b':
          writer.append("\\b");
          break;
        case '\n':
          writer.append("\\n");
          break;
        case '\t':
          writer.append("\\t");
          break;
        case '\f':
          writer.append("\\f");
          break;
        case '\r':
          writer.append("\\r");
          break;
        case '\\':
          writer.append("\\\\");
          break;
        default:
          writer.append(ch);
        }
      }
      writer.append(QUOTE);
    }
  }

  private void collection2Json(Collection<?> obj) throws IOException {
    writer.append(ARRAY_PRE);
    for (Iterator<?> it = obj.iterator(); it.hasNext();) {
      toJson(it.next());
      if (it.hasNext())
        writer.append(SEPARATOR);
    }
    writer.append(ARRAY_SUF);
  }

  private void array2Json(Object obj) throws IOException {
    writer.append(ARRAY_PRE);
    int len = Array.getLength(obj) - 1;
    if (len > -1) {
      int i;
      for (i = 0; i < len; i++) {
        toJson(Array.get(obj, i));
        writer.append(SEPARATOR);
      }
      toJson(Array.get(obj, i));
    }
    writer.append(ARRAY_SUF);
  }

  private void appendPair(String name, Object val) throws IOException {
    string2Json(name);
    writer.append(OBJ_SEPARATOR);
    toJson(val);
  }

  @Override
  public String toString() {
    return writer.toString();
  }
}
TOP

Related Classes of com.firefly.utils.json.JsonSerializer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.