Package siena.embed

Source Code of siena.embed.JsonSerializer

package siena.embed;

import static siena.Json.list;
import static siena.Json.map;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import siena.Json;
import siena.Query;
import siena.SienaException;
import siena.Util;

public class JsonSerializer {
 
  public static Json serialize(Object obj) {
    return serialize(obj, null);
  }
 
  public static Json serialize(Object obj, Field f) {
    if(obj == null) return new Json(null);
   
    Class<?> clazz = obj.getClass();
   
    //if(obj instanceof Map<?, ?>) {
    if(Map.class.isAssignableFrom(clazz)){
      Map<?, ?> map = (Map<?, ?>) obj;
      Json result = map();
      for (Map.Entry<?, ?> entry : map.entrySet()) {
        String key = entry.getKey().toString();
        Json value = serialize(entry.getValue(), null);
        result.put(key, value);
      }
      return result;
    }

    //if(obj instanceof Collection<?>) {
    if(Collection.class.isAssignableFrom(clazz)){
      Json result = list();
      Collection<?> col = (Collection<?>) obj;
      for (Object object : col) {
        result.add(serialize(object));
      }
      return result;
    }

    if(Json.class.isAssignableFrom(clazz)){
      return new Json(obj);
    }
   
    if(Field.class.isAssignableFrom(clazz)){
      return new Json(obj);
    }
   
    if(clazz.isArray()){
      return new Json(obj);
    }
   
    if(clazz == Class.class){
      return new Json(obj);
    }
   
    if(JsonDumpable.class.isAssignableFrom(obj.getClass())) {
      return ((JsonDumpable)obj).dump();
    }

    try {
      EmbeddedList list = obj.getClass().getAnnotation(EmbeddedList.class);
      if(list != null) {
        return serializeList(obj);
      }
      EmbeddedMap map = obj.getClass().getAnnotation(EmbeddedMap.class);
      if(map != null) {
        return serializeMap(obj);
      }
    } catch(SienaException e) {
      throw e;
    } catch(Exception e) {
      throw new SienaException(e);
    }
   
    if(f != null) {
      Format format = f.getAnnotation(Format.class);
      if(format != null) {
        if(obj.getClass() == Date.class) {
          Date date = (Date) obj;
          SimpleDateFormat sdf = new SimpleDateFormat(format.value());
          return new Json(sdf.format(date));
        }
      }
    }
   
    return new Json(obj);
  }
 
  public static Json serializeMap(Object obj) throws Exception {
    Field[] fields = obj.getClass().getDeclaredFields();
    Json result = map();
    for (Field f : fields) {
      if(mustIgnore(f)) continue;
     
      Key k = f.getAnnotation(Key.class);
      if(k != null) {
        result.put(k.value(), serialize(f.get(obj), f));
      } else {
        result.put(f.getName(), serialize(f.get(obj), f));
      }
    }
   
    // TEST
    // serializes super classes
    Class<?> clazz = obj.getClass().getSuperclass();
    while(clazz!=null){
      fields = clazz.getDeclaredFields();
      for (Field f : fields) {
        if(mustIgnore(f)) continue;
       
        Key k = f.getAnnotation(Key.class);
        if(k != null) {
          result.put(k.value(), serialize(Util.readField(obj, f), f));
        } else {
          result.put(f.getName(), serialize(Util.readField(obj, f), f));
        }
      }
      clazz = clazz.getSuperclass();
    }
    // TEST
    return result;
  }
 
  public static Json serializeList(Object obj) throws Exception {
    Field[] fields = obj.getClass().getDeclaredFields();
    Json result = list();
    for (Field f : fields) {
      if(mustIgnore(f)) continue;
     
      At at = f.getAnnotation(At.class);
      if(at == null) throw new SienaException("Field "+obj.getClass()+"."+f.getName()+" must be annotated with @At(n)");
      result.addAt(at.value(), serialize(f.get(obj), f));
    }
   
    // TEST
    // serializes super classes
    Class<?> clazz = obj.getClass().getSuperclass();
    while(clazz!=null){
      fields = clazz.getDeclaredFields();
      for (Field f : fields) {
        if(mustIgnore(f)) continue;
       
        At at = f.getAnnotation(At.class);
        if(at == null) throw new SienaException("Field "+obj.getClass()+"."+f.getName()+" must be annotated with @At(n)");
        result.addAt(at.value(), serialize(f.get(obj), f));
      }
      clazz = clazz.getSuperclass();
    }
    // TEST
    return result;
  }
 
  public static Object deserializeMap(Class<?> clazz, Json data) {
    if(!data.isMap()) {
      throw new SienaException("Error while deserializating class "+clazz
          +". A Json map is needed but found: "+data);
    }
    Object obj = Util.createObjectInstance(clazz);
    Field[] fields = clazz.getDeclaredFields();
    for (Field f : fields) {
      if(mustIgnore(f)) continue;
     
      Key key = f.getAnnotation(Key.class);
      if(key != null)
        Util.setField(obj, f, deserialize(f, data.get(key.value())));
      else
        Util.setField(obj, f, deserialize(f, data.get(f.getName())));
    }
   
    // deserializes super classes
    Class<?> superclazz = obj.getClass().getSuperclass();
    while(superclazz!=null){
      fields = superclazz.getDeclaredFields();
      for (Field f : fields) {
        if(mustIgnore(f)) continue;
       
        Key key = f.getAnnotation(Key.class);
        if(key != null)
          Util.setField(obj, f, deserialize(f, data.get(key.value())));
        else
          Util.setField(obj, f, deserialize(f, data.get(f.getName())));
      }
      superclazz = superclazz.getSuperclass();
    }
    return obj;
  }
 
  public static Object deserialize(Class<?> clazz, Json data) {
    try {
      EmbeddedMap map = clazz.getAnnotation(EmbeddedMap.class);
      if(map != null) {
        if(!data.isMap()) {
          throw new SienaException("Error while deserializating class "+clazz
              +". A Json map is needed but found: "+data);
        }
        Object obj = Util.createObjectInstance(clazz);
        Field[] fields = clazz.getDeclaredFields();
        for (Field f : fields) {
          if(mustIgnore(f)) continue;
         
          Key key = f.getAnnotation(Key.class);
          if(key != null)
            Util.setField(obj, f, deserialize(f, data.get(key.value())));
          else
            Util.setField(obj, f, deserialize(f, data.get(f.getName())));
        }
       
        // deserializes super classes
        Class<?> superclazz = obj.getClass().getSuperclass();
        while(superclazz!=null){
          fields = superclazz.getDeclaredFields();
          for (Field f : fields) {
            if(mustIgnore(f)) continue;
           
            Key key = f.getAnnotation(Key.class);
            if(key != null)
              Util.setField(obj, f, deserialize(f, data.get(key.value())));
            else
              Util.setField(obj, f, deserialize(f, data.get(f.getName())));
          }
          superclazz = superclazz.getSuperclass();
        }
        return obj;
      }
     
      EmbeddedList list = clazz.getAnnotation(EmbeddedList.class);
      if(list != null) {
        if(!data.isList()) {
          throw new SienaException("Error while deserializating class "+clazz
              +". A Json list is needed but found: "+data);
        }
        Object obj = Util.createObjectInstance(clazz);
        Field[] fields = clazz.getDeclaredFields();
        for (Field f : fields) {
          if(mustIgnore(f)) continue;
         
          At at = f.getAnnotation(At.class);
          if(at == null) throw new SienaException("Field "+obj.getClass()+"."+f.getName()+" must be annotated with @At(n)");
          Json value = data.at(at.value());
          Util.setField(obj, f, deserialize(f, value));
        }
       
        // deserializes super classes
        Class<?> superclazz = obj.getClass().getSuperclass();
        while(superclazz!=null){
          fields = superclazz.getDeclaredFields();
          for (Field f : fields) {
            if(mustIgnore(f)) continue;
           
            At at = f.getAnnotation(At.class);
            if(at == null) throw new SienaException("Field "+obj.getClass()+"."+f.getName()+" must be annotated with @At(n)");
            Json value = data.at(at.value());
            Util.setField(obj, f, deserialize(f, value));
          }
          superclazz = superclazz.getSuperclass();
        }
        return obj;
      }
      if(Json.class.isAssignableFrom(clazz)){
        return data;
      }
      JsonDeserializeAs as = clazz.getAnnotation(JsonDeserializeAs.class);
      if(as != null) {
        if(as.value() == String.class) {
          return data.asString();
        }
        else {
          Class<?> asClazz = as.value();
          Object ret = deserialize(as.value(), data);
          if(JsonRestorable.class.isAssignableFrom(asClazz)){
            return ((JsonRestorable<?>)ret).restore();
          }
          return ret;
        }
      }
      return deserializePlain(clazz, data);
    } catch(Exception e) {
      throw new SienaException(e);
    }
  }
 
  private static boolean mustIgnore(Field field) {
    if(Query.class.isAssignableFrom(field.getType())) return true;
    if(field.isAnnotationPresent(EmbedIgnore.class)) return true;
    boolean b = (field.getModifiers() & Modifier.TRANSIENT) == Modifier.TRANSIENT ||
      (field.getModifiers() & Modifier.STATIC) == Modifier.STATIC ||
      field.isSynthetic();
    if(!field.isAccessible())
      field.setAccessible(true);
   
    return b;
  }
 
  public static Object deserialize(Field f, Json data) {
    if(data == null || data.isNull()) return deserializePlain(f.getType(), data);
   
    Class<?> clazz = f.getType();
    if(Map.class.isAssignableFrom(clazz)) {
      if(!data.isMap()) {
        throw new SienaException("Error while deserializating field "+f.getDeclaringClass()
            +"."+f.getName()+" of type "+clazz
            +". A Json map is needed but found: "+data);
      }
      Map<String, Object> map = new HashMap<String, Object>();
      for (String key : data.keys()) {
        map.put(key, deserialize(Util.getGenericClass(f, 1), data.get(key)));
      }
      return map;
    }
    else if(Collection.class.isAssignableFrom(clazz)) {
      if(!data.isList()) {
        throw new SienaException("Error while deserializating field "+f.getDeclaringClass()
            +"."+f.getName()+" of type "+clazz
            +". A Json list is needed but found: "+data);
      }
      Collection<Object> collection = null;
      if(clazz == List.class) {
        collection = new ArrayList<Object>(data.size());
      } else {
        collection = new HashSet<Object>();
      }
      for (Json value : data) {
        collection.add(deserialize(Util.getGenericClass(f, 0), value));
      }
      return collection;
    }
    else if(Json.class.isAssignableFrom(clazz)){
      return data;
    }
    else if(Field.class.isAssignableFrom(clazz)){
      String fieldName = data.get("fieldName").asString();
      String parentClass = data.get("parentClass").asString();
      try {
        Class<?> cl = Class.forName(parentClass);
        Field fi = cl.getField(fieldName);
       
        return fi;
      }catch(ClassNotFoundException ex){
        throw new SienaException(ex);
      }catch(NoSuchFieldException ex){
        throw new SienaException(ex);
      }
    }
    else if(clazz.isArray()){
      Class<?> arrClazz = clazz.getComponentType();
      Object arr = Array.newInstance(arrClazz, data.size());
      int i=0;
      for (Json value : data) {
        Array.set(arr, i++, deserialize(arrClazz, value));
      }
     
      return arr;
    }else if(clazz == Class.class){
      String className = data.get("className").asString();
      try {
        Class<?> cl = Class.forName(className);
        return cl;
      }catch(ClassNotFoundException ex){
        throw new SienaException(ex);
      }
    }
   
    Format format = f.getAnnotation(Format.class);
    if(format != null) {
      if(f.getType() == Date.class) {
        SimpleDateFormat sdf = new SimpleDateFormat(format.value());
        try {
          return sdf.parse(data.str());
        } catch (ParseException e) {
          throw new SienaException(e);
        }
      }
    }
   
    JsonDeserializeAs as = f.getAnnotation(JsonDeserializeAs.class);
    if(as != null) {
      if(as.value() == String.class) {
        return data.asString();
      }
      else {
        return deserialize(as.value(), data);
      }
    }
   
    return deserialize(clazz, data);
  }
 
  private static Object deserializePlain(Class<?> type, Json data) {
    if(Boolean.class == type || boolean.class == type) {
      return data!=null ? data.asBoolean() : 0;
    }
    if(type == Byte.class || type == Byte.TYPE)    {
      return data!=null ? data.asBoolean() : 0;
    }
    else if(type == Short.class || type == Short.TYPE)   {
      return data!=null ? data.asShort() : 0;
    }
    else if(type == Integer.class || type == Integer.TYPE) {
      return data!=null ? data.asInt() : 0;
    }
    else if(type == Long.class || type == Long.TYPE)    {
      return data!=null ? data.asLong() : 0;
    }
    else if(type == Float.class || type == Float.TYPE)   {
      return data!=null ? data.asFloat() : 0;
    }
    else if(type == Double.class || type == Double.TYPE)  {
      return data!=null ? data.asDouble() : 0;
    }
    else if(type == String.class)  {
      return data!=null ? data.str() : null;
    }
    else if(type.isEnum()) {
      if(data!=null){
        String str = data.str();
        if(str != null) return Enum.valueOf((Class<Enum>) type, data.str());
      }
      return null;
    }else if(type == Date.class){
      return data!=null ? data.asDate() : null;
    }
    return null;
  }

}
TOP

Related Classes of siena.embed.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.