Commits

John Marsden committed 24f9840

Refactor and re-alignment with specifications 3.1 (Dont use this version - marshaler is broken/does not compile)

Comments (0)

Files changed (12)

src/main/java/cc/plural/jsonij/JSONMarshaler.java

-/**
- * Copyright (C) 2010-2011 J.W.Marsden
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- **/
-package cc.plural.jsonij;
-
-import java.io.IOException;
-
-import cc.plural.jsonij.marshal.JSONDocumentMarshaler;
-import cc.plural.jsonij.marshal.JSONMarshalerException;
-import cc.plural.jsonij.marshal.JavaMarshaler;
-import cc.plural.jsonij.parser.ParserException;
-import java.io.InputStream;
-
-/**
- *
- * @author openecho
- */
-public class JSONMarshaler {
-
-    protected static final JavaMarshaler javaMarshaler;
-    protected static final JSONDocumentMarshaler jsonMarshaler;
-
-    static {
-        javaMarshaler = new JavaMarshaler();
-        jsonMarshaler = new JSONDocumentMarshaler();
-    }
-
-    public static JSON marshalObject(Object o) {
-        Value mashaledObject = javaMarshaler.marshalObject(o);
-        return new JSON(mashaledObject);
-    }
-
-    public static JSON marshalObject(boolean[] a) {
-        Value marshaledArray = javaMarshaler.marshalObject(a);
-        return new JSON(marshaledArray);
-    }
-
-    public static JSON marshalObject(Boolean[] a) {
-        Value marshaledArray = javaMarshaler.marshalObject(a);
-        return new JSON(marshaledArray);
-    }
-
-    public static JSON marshalObject(int[] a) {
-        Value marshaledArray = javaMarshaler.marshalObject(a);
-        return new JSON(marshaledArray);
-    }
-
-    public static JSON marshalObject(Integer[] a) {
-        Value marshaledArray = javaMarshaler.marshalObject(a);
-        return new JSON(marshaledArray);
-    }
-
-    public static JSON marshalObject(char[] a) {
-        Value marshaledArray = javaMarshaler.marshalObject(a);
-        return new JSON(marshaledArray);
-    }
-
-    public static JSON marshalObject(Character[] a) {
-        Value marshaledArray = javaMarshaler.marshalObject(a);
-        return new JSON(marshaledArray);
-    }
-
-    public static JSON marshalObject(double[] a) {
-        Value marshaledArray = javaMarshaler.marshalObject(a);
-        return new JSON(marshaledArray);
-    }
-
-    public static JSON marshalObject(Double[] a) {
-        Value marshaledArray = javaMarshaler.marshalObject(a);
-        return new JSON(marshaledArray);
-    }
-
-    public static JSON marshalObject(float[] a) {
-        Value marshaledArray = javaMarshaler.marshalObject(a);
-        return new JSON(marshaledArray);
-    }
-
-    public static JSON marshalObject(Float[] a) {
-        Value marshaledArray = javaMarshaler.marshalObject(a);
-        return new JSON(marshaledArray);
-    }
-
-    public static JSON marshalObject(short[] a) {
-        Value marshaledArray = javaMarshaler.marshalObject(a);
-        return new JSON(marshaledArray);
-    }
-
-    public static JSON marshalObject(Short[] a) {
-        Value marshaledArray = javaMarshaler.marshalObject(a);
-        return new JSON(marshaledArray);
-    }
-
-    public static JSON marshalObject(long[] a) {
-        Value marshaledArray = javaMarshaler.marshalObject(a);
-        return new JSON(marshaledArray);
-    }
-
-    public static JSON marshalObject(Long[] a) {
-        Value marshaledArray = javaMarshaler.marshalObject(a);
-        return new JSON(marshaledArray);
-    }
-
-    public static JSON marshalObject(String[] a) {
-        Value marshaledArray = javaMarshaler.marshalObject(a);
-        return new JSON(marshaledArray);
-    }
-
-    public static JSON marshalObject(Object[] a) {
-        Value marshaledArray = javaMarshaler.marshalObject(a);
-        return new JSON(marshaledArray);
-    }
-    
-    public static Object marshalJSON(String json, Class<?> c) throws JSONMarshalerException, IOException, ParserException {
-        Object marshaledObject = jsonMarshaler.marshalJSONDocument(JSON.parse(json), c);
-        return marshaledObject;
-    }
-    
-    public static Object marshalJSON(JSON json, Class<?> c) throws JSONMarshalerException {
-        Object marshaledObject = jsonMarshaler.marshalJSONDocument(json, c);
-        return marshaledObject;
-    }
-    
-    public static Object marshalJSON(Value value, Class<?> c) throws JSONMarshalerException {
-        Object marshaledObject = jsonMarshaler.marshalJSONDocument(value, c);
-        return marshaledObject;
-    }
-    
-    public static Object marshalJSON(InputStream stream, Class<?> c) throws JSONMarshalerException {
-        Object marshaledObject = jsonMarshaler.marshalJSONDocument(stream, c);
-        return marshaledObject;
-    }
-}

src/main/java/cc/plural/jsonij/marshal/Inspector.java

  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- **/
+ *
+ */
 package cc.plural.jsonij.marshal;
 
+import java.lang.annotation.Annotation;
 import java.lang.reflect.AccessibleObject;
 import java.lang.reflect.Array;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
 import cc.plural.jsonij.marshal.InspectorProperty.TYPE;
 import cc.plural.jsonij.marshal.annotation.JSONAccessor;
+import cc.plural.jsonij.marshal.annotation.JSONCollector;
 import cc.plural.jsonij.marshal.annotation.JSONIgnore;
 import cc.plural.jsonij.marshal.annotation.JSONMutator;
 import cc.plural.jsonij.marshal.annotation.JSONName;
+import cc.plural.jsonij.reflect.InspectionFilter;
 
 /**
  *
 public class Inspector {
 
     public static final String IS_PREFIX;
+
     public static final String SET_PREFIX;
+
     public static final String GET_PREFIX;
-    Object o;
-    Class<?> c;
-    InspectorProperty[] properties;
-    InspectorFilter filter;
-    boolean innerArray;
-    boolean innerObject;
+
+    private Object o;
+
+    private Class<?> c;
+
+    private InspectorProperty[] properties;
+
+    private InspectionFilter filter;
+
+    private boolean innerArray;
+
+    private boolean innerObject;
 
     static {
         IS_PREFIX = "is";
         this.c = c;
         this.o = null;
         properties = null;
-        filter = InspectorFilter.getDefaultFilters();
+        filter = InspectionFilter.getDefaultFilters();
         innerArray = false;
         innerObject = false;
     }
     public Inspector(Object o) {
         this.o = o;
         properties = null;
-        filter = InspectorFilter.getDefaultFilters();
+        filter = InspectionFilter.getDefaultFilters();
         innerArray = false;
         innerObject = false;
     }
     public boolean hasInnerObject() {
         return innerObject;
     }
-    
+
     public boolean hasProperty(String name) {
-        for(InspectorProperty property: properties) {
+        for(InspectorProperty property : properties) {
             if(property.getPropertyName().equals(name)) {
                 return true;
             }
         }
         return false;
     }
-    
+
     public InspectorProperty getProperty(String name) {
-        for(InspectorProperty property: properties) {
+        for(InspectorProperty property : properties) {
             if(property.getPropertyName().equals(name)) {
                 return property;
             }
         }
         return null;
     }
-    
 
     public void inspect() {
-        if (o == null && c == null) {
+        if(o == null && c == null) {
             return;
         }
-        if (o != null) {
+        if(o != null) {
             c = o.getClass();
         }
         Class<?> objectClass = c;
         // Inspect Properties
         InspectorProperty[] propertyList = getMethodProperties(objectClass);
-        if (propertyList != null) {
+        if(propertyList != null) {
             InspectorProperty[] fieldPropertyList = getAttributeProperties(objectClass);
-            if (fieldPropertyList != null) {
+            if(fieldPropertyList != null) {
                 HashMap<String, InspectorProperty> propertiesMap = new HashMap<String, InspectorProperty>();
-                for (InspectorProperty prop : propertyList) {
+                for(InspectorProperty prop : propertyList) {
                     propertiesMap.put(prop.getPropertyName(), prop);
                 }
-                for (InspectorProperty prop : fieldPropertyList) {
-                    if (propertiesMap.containsKey(prop.getPropertyName())) {
+                for(InspectorProperty prop : fieldPropertyList) {
+                    if(propertiesMap.containsKey(prop.getPropertyName())) {
                         InspectorProperty existingProp = propertiesMap.get(prop.getPropertyName());
-                        if (!existingProp.hasAccessor()) {
+                        if(!existingProp.hasAccessor()) {
                             existingProp.setAccessName(prop.getAccessName());
                             existingProp.setAccessPropertyType(TYPE.FIELD);
                         }
-                        if (!existingProp.hasMutator()) {
+                        if(!existingProp.hasMutator()) {
                             existingProp.setMutateName(prop.getMutateName());
                             existingProp.setMutatePropertyType(TYPE.FIELD);
                         }
+                        if(prop.getAnnotations() != null && existingProp.getAnnotations() != null) {
+                            existingProp.getAnnotations().addAll(prop.getAnnotations());
+                        } else if(prop.getAnnotations() != null && existingProp.getAnnotations() == null) {
+                            existingProp.setAnnotations(prop.getAnnotations());
+                        }
                     } else {
                         propertiesMap.put(prop.getPropertyName(), prop);
                     }
             propertyList = getAttributeProperties(objectClass);
         }
 
-        if (propertyList == null) {
+        if(propertyList == null) {
             propertyList = new InspectorProperty[0];
         }
         properties = propertyList;
 
         // Inspect inner array (List type) and Inspect inner object (Map type)
-        Class<?>[] interfaces = null;
+        Class<?>[] interfaces;
         Class<?> parent = objectClass.getSuperclass();
-        if (parent != null) {
+        if(parent != null) {
             do {
                 interfaces = parent.getInterfaces();
-                for (int i = 0; i < Array.getLength(interfaces); i++) {
-                    if (interfaces[i] == List.class) {
+                for(int i = 0; i < Array.getLength(interfaces); i++) {
+                    if(interfaces[i] == List.class) {
                         innerArray = true;
                     }
-                    if (interfaces[i] == Map.class) {
+                    if(interfaces[i] == Map.class) {
                         innerObject = true;
                     }
-                    if (innerArray && innerObject) {
+                    if(innerArray && innerObject) {
                         break;
                     }
                 }
-                if (innerArray && innerObject) {
+                if(innerArray && innerObject) {
                     break;
                 }
-            } while (( parent = parent.getSuperclass() ) != null);
+            } while((parent = parent.getSuperclass()) != null);
         }
-
     }
 
     public InspectorProperty[] getAttributeProperties(Class<?> objectClass) {
         InspectorProperty[] result = null;
         HashMap<String, InspectorProperty> attributeProperties = new HashMap<String, InspectorProperty>();
         Field[] objectFields = objectClass.getFields();
-        for (Field field : objectFields) {
-            if (isJSONIgnored(field) || filter.isFiltered(field.getDeclaringClass())) {
+        for(Field field : objectFields) {
+            if(isJSONIgnored(field) || filter.isFiltered(field.getDeclaringClass())) {
                 continue;
             }
             InspectionData fieldInspectionData = getFieldInspectionData(field);
-            if (fieldInspectionData == null || !fieldInspectionData.hasPropertyName()) {
+            if(fieldInspectionData == null || !fieldInspectionData.hasPropertyName()) {
                 continue;
             }
             String propertyName = fieldInspectionData.getPropertyName();
             InspectorProperty property = null;
-            if (!attributeProperties.containsKey(propertyName)) {
+            if(!attributeProperties.containsKey(propertyName)) {
                 property = new InspectorProperty(propertyName, TYPE.FIELD);
                 attributeProperties.put(propertyName, property);
                 property.setPropertyName(propertyName);
                 property.setMutateName(fieldInspectionData.getName());
                 property.setAccessReturnType(fieldInspectionData.getReturnType());
                 property.setMutateInputType(fieldInspectionData.getArgumentType());
+
+                if(field.getAnnotations() != null) {
+                    property.annotations = new ArrayList<Annotation>();
+                    property.annotations.addAll(Arrays.asList(field.getAnnotations()));
+                }
             }
         }
-        if (!attributeProperties.isEmpty()) {
+        if(!attributeProperties.isEmpty()) {
             result = new InspectorProperty[attributeProperties.size()];
             attributeProperties.values().toArray(result);
         }
         InspectorProperty[] result = null;
         HashMap<String, InspectorProperty> methodProperties = new HashMap<String, InspectorProperty>();
         Method[] objectMethods = objectClass.getMethods();
-        for (Method method : objectMethods) {
-            if (isJSONIgnored(method) || filter.isFiltered(method.getDeclaringClass())) {
+        for(Method method : objectMethods) {
+            if(isJSONIgnored(method) || filter.isFiltered(method.getDeclaringClass())) {
                 continue;
             }
             InspectionData methodInspectionData = getMethodInspectionData(method);
-            if (methodInspectionData == null || !methodInspectionData.hasPropertyName()) {
+            if(methodInspectionData == null || !methodInspectionData.hasPropertyName()) {
                 continue;
             }
             String propertyName = methodInspectionData.getPropertyName();
-            InspectorProperty property = null;
-            if (methodProperties.containsKey(propertyName)) {
+            InspectorProperty property;
+            if(methodProperties.containsKey(propertyName)) {
                 property = methodProperties.get(propertyName);
             } else {
                 property = new InspectorProperty(propertyName, TYPE.METHOD);
                 methodProperties.put(propertyName, property);
             }
-            if (methodInspectionData.getAccessType() == ACCESS_TYPE.ACCESS && !property.hasAccessor()) {
+            if(methodInspectionData.getAccessType() == ACCESS_TYPE.ACCESS && !property.hasAccessor()) {
                 property.setAccessName(methodInspectionData.getName());
                 property.setAccessReturnType(methodInspectionData.getReturnType());
-            } else if (methodInspectionData.getAccessType() == ACCESS_TYPE.MUTATE && !property.hasMutator()) {
+            } else if(methodInspectionData.getAccessType() == ACCESS_TYPE.MUTATE && !property.hasMutator()) {
                 property.setMutateName(methodInspectionData.getName());
                 property.setMutateInputType(methodInspectionData.getArgumentType());
             }
+
+            if(method.getAnnotations() != null && property != null) {
+                property.annotations = new ArrayList<Annotation>();
+                property.annotations.addAll(Arrays.asList(method.getAnnotations()));
+            }
         }
-        if (!methodProperties.isEmpty()) {
+        if(!methodProperties.isEmpty()) {
             result = new InspectorProperty[methodProperties.size()];
             methodProperties.values().toArray(result);
         }
         fieldInspectionData.setName(field.getName());
         fieldInspectionData.setAccessType(ACCESS_TYPE.BOTH);
         String jsonName = Inspector.getJSONName(field);
-        if (jsonName != null) {
+        if(jsonName != null) {
             fieldInspectionData.setPropertyName(jsonName);
         }
-        if (!fieldInspectionData.hasPropertyName()) {
+        if(!fieldInspectionData.hasPropertyName()) {
             fieldInspectionData.setPropertyName(fieldInspectionData.getName());
         }
         fieldInspectionData.setArgumentType(field.getType());
         InspectionData methodInspectionData = new InspectionData();
         methodInspectionData.setName(method.getName());
         String jsonName = Inspector.getJSONName(method);
-        if (jsonName != null) {
+        if(jsonName != null) {
             methodInspectionData.setPropertyName(jsonName);
         }
-        if (!methodInspectionData.hasPropertyName()) {
+        if(!methodInspectionData.hasPropertyName()) {
             String accessorName = Inspector.getJSONAccessor(method);
-            if (accessorName != null) {
+            if(accessorName != null) {
                 methodInspectionData.setPropertyName(accessorName);
                 methodInspectionData.setAccessType(ACCESS_TYPE.ACCESS);
             }
         }
-        if (!methodInspectionData.hasPropertyName()) {
+        if(!methodInspectionData.hasPropertyName()) {
             String mutatorName = Inspector.getJSONMutator(method);
-            if (mutatorName != null) {
+            if(mutatorName != null) {
                 methodInspectionData.setPropertyName(mutatorName);
                 methodInspectionData.setAccessType(ACCESS_TYPE.MUTATE);
             }
         }
         methodInspectionData.setReturnType(method.getReturnType());
-        if (!methodInspectionData.hasPropertyName()) {
+        if(!methodInspectionData.hasPropertyName()) {
             char ch;
-            String propertyName = null;
+            String propertyName;
             String methodName = methodInspectionData.getName();
             Class<?> returnType = methodInspectionData.getReturnType();
-            if (methodName.length() > IS_PREFIX.length() && methodName.startsWith(IS_PREFIX) && returnType == boolean.class && Character.isUpperCase(ch = methodName.charAt(IS_PREFIX.length()))) {
+            if(methodName.length() > IS_PREFIX.length() && methodName.startsWith(IS_PREFIX) && returnType == boolean.class && Character.isUpperCase(ch = methodName.charAt(IS_PREFIX.length()))) {
                 propertyName = Character.toLowerCase(ch) + methodName.substring(IS_PREFIX.length() + 1, methodName.length());
                 methodInspectionData.setPropertyName(propertyName);
                 methodInspectionData.setAccessType(ACCESS_TYPE.ACCESS);
-            } else if (methodName.length() > SET_PREFIX.length() && methodName.startsWith(SET_PREFIX) && Character.isUpperCase(ch = methodName.charAt(SET_PREFIX.length()))) {
+            } else if(methodName.length() > SET_PREFIX.length() && methodName.startsWith(SET_PREFIX) && Character.isUpperCase(ch = methodName.charAt(SET_PREFIX.length()))) {
                 propertyName = Character.toLowerCase(ch) + methodName.substring(SET_PREFIX.length() + 1, methodName.length());
                 methodInspectionData.setPropertyName(propertyName);
                 methodInspectionData.setAccessType(ACCESS_TYPE.MUTATE);
-            } else if (methodName.length() > GET_PREFIX.length() && methodName.startsWith(GET_PREFIX) && Character.isUpperCase(ch = methodName.charAt(GET_PREFIX.length())) && returnType != null) {
+            } else if(methodName.length() > GET_PREFIX.length() && methodName.startsWith(GET_PREFIX) && Character.isUpperCase(ch = methodName.charAt(GET_PREFIX.length())) && returnType != null) {
                 propertyName = Character.toLowerCase(ch) + methodName.substring(GET_PREFIX.length() + 1, methodName.length());
                 methodInspectionData.setPropertyName(propertyName);
                 methodInspectionData.setAccessType(ACCESS_TYPE.ACCESS);
             }
         }
-        if (methodInspectionData.getAccessType() == ACCESS_TYPE.ACCESS) {
+        if(methodInspectionData.getAccessType() == ACCESS_TYPE.ACCESS) {
             Class<?> returnType = method.getReturnType();
-            if (returnType != null) {
+            if(returnType != null) {
                 methodInspectionData.setReturnType(returnType);
             } else {
                 return null;
             }
-        } else if (methodInspectionData.getAccessType() == ACCESS_TYPE.MUTATE) {
+        } else if(methodInspectionData.getAccessType() == ACCESS_TYPE.MUTATE) {
             Class<?>[] parameterTypes = method.getParameterTypes();
-            if (Array.getLength(parameterTypes) == 1) {
+            if(Array.getLength(parameterTypes) == 1) {
                 Class<?> parameterType = parameterTypes[0];
                 methodInspectionData.setArgumentType(parameterType);
             } else {
     }
 
     public InspectorProperty[] getProperties() {
-        if (o != null && properties == null) {
+        if(o != null && properties == null) {
             inspect();
         }
         return properties;
     }
 
+    public boolean hasCollector() {
+        for(InspectorProperty prop : properties) {
+            if(prop.getAnnotations() != null) {
+                for(Annotation annotation : prop.getAnnotations()) {
+                    if(annotation instanceof JSONCollector) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+    public InspectorProperty getCollector() {
+        for(InspectorProperty prop : properties) {
+            if(prop.getAnnotations() != null) {
+                for(Annotation annotation : prop.getAnnotations()) {
+                    if(annotation instanceof JSONCollector) {
+                        return prop;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
     public void setProperties(InspectorProperty[] properties) {
         this.properties = properties;
     }
 
-    public boolean isJSONIgnored(AccessibleObject object) {
+    private boolean isJSONIgnored(AccessibleObject object) {
         return object.getAnnotation(JSONIgnore.class) != null;
     }
 
-    public static String getAnnotatedName(AccessibleObject object) {
+    private static String getAnnotatedName(AccessibleObject object) {
         String name = getJSONName(object);
-        if (name == null) {
+        if(name == null) {
             name = getJSONMutator(object);
         }
-        if (name == null) {
+        if(name == null) {
             name = getJSONAccessor(object);
         }
         return name;
     }
 
-    public static String getJSONName(AccessibleObject object) {
+    private static String getJSONName(AccessibleObject object) {
         String name = null;
         JSONName jsonNameAnnotation = object.getAnnotation(JSONName.class);
-        if (jsonNameAnnotation != null) {
+        if(jsonNameAnnotation != null) {
             name = jsonNameAnnotation.value();
         }
         return name;
     }
 
-    public static String getJSONMutator(AccessibleObject object) {
+    private static String getJSONMutator(AccessibleObject object) {
         String name = null;
         JSONMutator jsonMutatorAnnotation = object.getAnnotation(JSONMutator.class);
-        if (jsonMutatorAnnotation != null) {
+        if(jsonMutatorAnnotation != null) {
             name = jsonMutatorAnnotation.value();
         }
         return name;
     }
 
-    public static String getJSONAccessor(AccessibleObject object) {
+    private static String getJSONAccessor(AccessibleObject object) {
         String name = null;
         JSONAccessor jsonAccessorAnnotation = object.getAnnotation(JSONAccessor.class);
-        if (jsonAccessorAnnotation != null) {
+        if(jsonAccessorAnnotation != null) {
             name = jsonAccessorAnnotation.value();
         }
         return name;
 
     public enum ACCESS_TYPE {
 
-        ACCESS, MUTATE, BOTH
+        ACCESS,
+        MUTATE,
+        BOTH
+
     }
 
     public static class InspectionData {
 
         protected String name;
+
         protected String propertyName;
+
         protected Class<?> returnType;
+
         protected Class<?> argumentType;
+
         protected ACCESS_TYPE accessType;
 
+        protected Annotation[] annotations;
+
         public InspectionData() {
             name = null;
             propertyName = null;
             returnType = null;
+            accessType = null;
+            annotations = null;
         }
 
         public String getName() {
         public void setAccessType(ACCESS_TYPE accessType) {
             this.accessType = accessType;
         }
+
+        public Annotation[] getAnnotations() {
+            return annotations;
+        }
+
+        public void setAnnotations(Annotation[] annotations) {
+            this.annotations = annotations;
+        }
+    }
+
+    public static boolean isMapType(Class<?> c) {
+        Class<?> currentClass = c;
+        do {
+            Class<?>[] interfaces = currentClass.getInterfaces();
+            for(Class<?> i : interfaces) {
+                if(i == Map.class) {
+                    return true;
+                }
+            }
+        } while((currentClass = currentClass.getSuperclass()) != null);
+        return false;
+    }
+
+    public static boolean isListType(Class<?> c) {
+        Class<?> currentClass = c;
+        do {
+            Class<?>[] interfaces = currentClass.getInterfaces();
+            for(Class<?> i : interfaces) {
+                if(i == List.class) {
+                    return true;
+                }
+            }
+        } while((currentClass = currentClass.getSuperclass()) != null);
+        return false;
     }
 }

src/main/java/cc/plural/jsonij/marshal/InspectorFilter.java

-/*
- *  Copyright 2011 jmarsden.
- * 
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- * 
- *       http://www.apache.org/licenses/LICENSE-2.0
- * 
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *  under the License.
- */
-package cc.plural.jsonij.marshal;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @deprecated 
- */
-public class InspectorFilter {
-
-    protected List<Class<?>> classFilter;
-
-    protected static InspectorFilter defaultFilters;
-    
-    static {
-        defaultFilters = null;
-    }
-    
-    public InspectorFilter() {
-        classFilter = new ArrayList<Class<?>>();
-    }
-
-    public boolean isFiltered(Class<?> clazz) {
-        return classFilter.contains(clazz);
-    }
-    
-    protected static void createDefaultInstance() {
-        defaultFilters = new InspectorFilter();
-	defaultFilters.classFilter.add(java.lang.Class.class);
-        defaultFilters.classFilter.add(java.lang.Object.class);
-        defaultFilters.classFilter.add(java.util.List.class);
-        defaultFilters.classFilter.add(java.util.ArrayList.class);
-        defaultFilters.classFilter.add(java.util.Map.class);
-        defaultFilters.classFilter.add(java.util.HashMap.class);	
-    }
-    
-    public static InspectorFilter getDefaultFilters() {
-        if(defaultFilters == null) {
-            createDefaultInstance();
-        }
-        return defaultFilters;
-    }
-}

src/main/java/cc/plural/jsonij/marshal/InspectorProperty.java

  */
 package cc.plural.jsonij.marshal;
 
+import java.lang.annotation.Annotation;
+import java.util.List;
+
 /**
  * @deprecated 
  */
 public class InspectorProperty {
 
     public enum TYPE {
-        FIELD, METHOD
+
+        FIELD,
+        METHOD
+
     }
     public String propertyName;
+
     public String accessName;
+
     public String mutateName;
+
     public TYPE accessPropertyType;
+
     public TYPE mutatePropertyType;
+
     public Class<?> accessReturnType;
+
     public Class<?> mutateInputType;
 
+    public List<Annotation> annotations;
+
     public InspectorProperty() {
         propertyName = null;
         accessPropertyType = null;
         mutatePropertyType = null;
         accessName = null;
         mutateName = null;
+        annotations = null;
     }
 
     public InspectorProperty(String name, TYPE accessType) {
     }
 
     public boolean hasAccessor() {
-        return accessPropertyType == TYPE.FIELD || ( accessName != null );
+        return accessPropertyType == TYPE.FIELD || (accessName != null);
     }
 
     public boolean hasMutator() {
-        return mutatePropertyType == TYPE.FIELD || ( mutateName != null );
+        return mutatePropertyType == TYPE.FIELD || (mutateName != null);
+    }
+
+    public List<Annotation> getAnnotations() {
+        return annotations;
+    }
+
+    public void setAnnotations(List<Annotation> annotations) {
+        this.annotations = annotations;
     }
 
     @Override

src/main/java/cc/plural/jsonij/marshal/JSONDocumentMarshaler.java

-/*
- * Copyright 2011 jmarsden.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package cc.plural.jsonij.marshal;
-
-import cc.plural.jsonij.reflect.JavaType;
-import java.lang.reflect.Array;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import cc.plural.jsonij.JSON;
-import cc.plural.jsonij.Value;
-import cc.plural.jsonij.parser.ParserException;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- *
- * @author jmarsden
- */
-public class JSONDocumentMarshaler {
-
-    public static String innerArrayAttribute;
-
-    public static String innerObjectAttribute;
-
-    static {
-        innerArrayAttribute = "_innerArray";
-        innerObjectAttribute = "_innerObject";
-    }
-
-    public Object marshalJSONDocument(JSON json, Class<?> objectClass) throws JSONMarshalerException {
-        Object resultObject = null;
-        Value jsonRoot = json.getRoot();
-        if(jsonRoot.type() == Value.TYPE.OBJECT) {
-            JSON.Object<CharSequence, Value> jsonObjectRoot = (JSON.Object<CharSequence, Value>) jsonRoot;
-            resultObject = marshalJSONDocumentObject(jsonObjectRoot, objectClass);
-        } else if(jsonRoot.type() == Value.TYPE.ARRAY) {
-            JSON.Array<Value> jsonArrayRoot = (JSON.Array<Value>) jsonRoot;
-            resultObject = marshalJSONDocumentArray(jsonArrayRoot, objectClass);
-        } else {
-            //throw new Exception();
-        }
-        return resultObject;
-    }
-
-    public Object marshalJSONDocument(Value value, Class<?> objectClass) throws JSONMarshalerException {
-        Object resultObject = null;
-        if(value.type() == Value.TYPE.OBJECT) {
-            JSON.Object<CharSequence, Value> jsonObjectRoot = (JSON.Object<CharSequence, Value>) value;
-            resultObject = marshalJSONDocumentObject(jsonObjectRoot, objectClass);
-        } else if(value.type() == Value.TYPE.ARRAY) {
-            JSON.Array<Value> jsonArrayRoot = (JSON.Array<Value>) value;
-            resultObject = marshalJSONDocumentArray(jsonArrayRoot, objectClass);
-        } else {
-            //throw new Exception();
-        }
-        return resultObject;
-    }
-
-    public Object marshalJSONDocumentObject(JSON.Object<CharSequence, Value> jsonObject, Class<?> objectClass) throws JSONMarshalerException {
-        Object resultObject = null;
-
-        Set<Entry<CharSequence, Value>> entrySet = jsonObject.entrySet();
-        Iterator<Entry<CharSequence, Value>> entrySetIterator = entrySet.iterator();
-        Entry<CharSequence, Value> entry = null;
-        Inspector inspector = new Inspector(objectClass);
-        inspector.inspect();
-
-        List<MarshalerPropertyValue> marshalPropertyValues = new ArrayList<MarshalerPropertyValue>();
-        while(entrySetIterator.hasNext()) {
-            entry = entrySetIterator.next();
-            if(entry.getKey().toString().equals(innerObjectAttribute) && inspector.hasInnerObject()) {
-                /**
-                 * todo: handle the inner object
-                 */
-            }
-            String propertyName = entry.getKey().toString();
-            if(inspector.hasProperty(propertyName)) {
-                MarshalerPropertyValue propertyValue = new MarshalerPropertyValue(propertyName, inspector.getProperty(propertyName), entry.getValue());
-                marshalPropertyValues.add(propertyValue);
-            }
-        }
-
-
-        try {
-            resultObject = objectClass.newInstance();
-            for(MarshalerPropertyValue propertyValue : marshalPropertyValues) {
-                if(propertyValue.getValue().isNull()) {
-                    // TODO: Handle Null
-                }
-                InspectorProperty property = propertyValue.getProperty();
-                if(property.getAccessPropertyType() == InspectorProperty.TYPE.METHOD) {
-                    Method method = objectClass.getMethod(property.getMutateName(), property.getMutateInputType());
-                    JavaType mutateType = JavaType.inspectObjectType(property.getMutateInputType());
-
-                    JSON.Array<Value> arrayJSON = null;
-
-                    switch(mutateType) {
-                        case BOOLEAN:
-                            method.invoke(resultObject, propertyValue.getValue().getBoolean());
-                            break;
-                        case BYTE:
-                            method.invoke(resultObject, propertyValue.getValue().getNumber().byteValue());
-                            break;
-                        case INTEGER:
-                            method.invoke(resultObject, propertyValue.getValue().getNumber().intValue());
-                            break;
-                        case SHORT:
-                            method.invoke(resultObject, propertyValue.getValue().getNumber().shortValue());
-                            break;
-                        case FLOAT:
-                            method.invoke(resultObject, propertyValue.getValue().getNumber().floatValue());
-                            break;
-                        case LONG:
-                            method.invoke(resultObject, propertyValue.getValue().getNumber().longValue());
-                            break;
-                        case DOUBLE:
-                            method.invoke(resultObject, propertyValue.getValue().getNumber().doubleValue());
-                            break;
-                        case STRING:
-                            method.invoke(resultObject, propertyValue.getValue().getString());
-                            break;
-                        case ENUM:
-                            method.invoke(resultObject, propertyValue.getValue().getString());
-                            break;
-                        case MAP:
-
-                            break;
-                        case LIST:
-
-                            break;
-                        case OBJECT:
-                            JSON.Object<CharSequence, Value> objectJSON = (JSON.Object<CharSequence, Value>) propertyValue.getValue();
-                            method.invoke(resultObject, marshalJSONDocumentObject(objectJSON, property.getMutateInputType()));
-                            break;
-                        case ARRAY:
-                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-                            method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-                            break;
-                        case ARRAY_BYTE:
-                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-                            method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-                            break;
-                        case ARRAY_SHORT:
-                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-                            method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-                            break;
-                        case ARRAY_INTEGER:
-                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-                            method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-                            break;
-                        case ARRAY_FLOAT:
-                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-                            method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-                            break;
-                        case ARRAY_DOUBLE:
-                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-                            method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-                            break;
-                        case ARRAY_LONG:
-                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-                            method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-                            break;
-                        case ARRAY_STRING:
-                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-                            method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-                            break;
-                        case ARRAY_ENUM:
-                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-                            method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-                            break;
-                        case ARRAY_LIST:
-                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-                            method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-                            break;
-                        case ARRAY_MAP:
-                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-                            method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-                            break;
-                        default:
-
-                            break;
-                    }
-                } else if(property.getAccessPropertyType() == InspectorProperty.TYPE.FIELD) {
-                    Field field = objectClass.getField(propertyValue.getProperty().getMutateName());
-                    JavaType mutateType = JavaType.inspectObjectType(property.getMutateInputType());
-
-                    JSON.Array<Value> arrayJSON = null;
-
-                    switch(mutateType) {
-                        case BOOLEAN:
-                            field.set(resultObject, propertyValue.getValue().getBoolean());
-                            break;
-                        case BYTE:
-                            field.set(resultObject, propertyValue.getValue().getNumber().byteValue());
-                            break;
-                        case INTEGER:
-                            field.set(resultObject, propertyValue.getValue().getNumber().intValue());
-                            break;
-                        case SHORT:
-                            field.set(resultObject, propertyValue.getValue().getNumber().shortValue());
-                            break;
-                        case FLOAT:
-                            field.set(resultObject, propertyValue.getValue().getNumber().floatValue());
-                            break;
-                        case LONG:
-                            field.set(resultObject, propertyValue.getValue().getNumber().longValue());
-                            break;
-                        case DOUBLE:
-                            field.set(resultObject, propertyValue.getValue().getNumber().doubleValue());
-                            break;
-                        case STRING:
-                            field.set(resultObject, propertyValue.getValue().getString());
-                            break;
-                        case ENUM:
-
-                            break;
-                        case MAP:
-
-                            break;
-                        case LIST:
-
-                            break;
-                        case OBJECT:
-                            JSON.Object<CharSequence, Value> objectJSON = (JSON.Object<CharSequence, Value>) propertyValue.getValue();
-                            field.set(resultObject, marshalJSONDocumentObject(objectJSON, property.getMutateInputType()));
-                            break;
-                        case ARRAY:
-                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-                            break;
-                        case ARRAY_BYTE:
-                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-                            break;
-                        case ARRAY_SHORT:
-                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-                            break;
-                        case ARRAY_INTEGER:
-                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-                            break;
-                        case ARRAY_FLOAT:
-                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-                            break;
-                        case ARRAY_DOUBLE:
-                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-                            break;
-                        case ARRAY_LONG:
-                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-                            break;
-                        case ARRAY_STRING:
-                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-                            break;
-                        case ARRAY_ENUM:
-                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-                            break;
-                        case ARRAY_LIST:
-                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-                            break;
-                        case ARRAY_MAP:
-                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-                            break;
-                        case ARRAY_ARRAY:
-                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
-                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
-                            break;
-                        default:
-
-                            break;
-                    }
-                }
-
-            }
-
-        } catch(InstantiationException ex) {
-            Logger.getLogger(JSONDocumentMarshaler.class.getName()).log(Level.SEVERE, null, ex);
-        } catch(IllegalAccessException ex) {
-            Logger.getLogger(JSONDocumentMarshaler.class.getName()).log(Level.SEVERE, null, ex);
-        } catch(NoSuchFieldException ex) {
-            Logger.getLogger(JSONDocumentMarshaler.class.getName()).log(Level.SEVERE, null, ex);
-        } catch(NoSuchMethodException ex) {
-            Logger.getLogger(JSONDocumentMarshaler.class.getName()).log(Level.SEVERE, null, ex);
-        } catch(InvocationTargetException ex) {
-            Logger.getLogger(JSONDocumentMarshaler.class.getName()).log(Level.SEVERE, null, ex);
-        }
-        return resultObject;
-    }
-
-    public Object marshalJSONDocument(InputStream stream, Class<?> objectClass) throws JSONMarshalerException {
-        JSON json;
-        try {
-            json = JSON.parse(stream);
-
-        } catch(ParserException ex) {
-            throw new JSONMarshalerException("", ex);
-        } catch(IOException ex) {
-            throw new JSONMarshalerException("", ex);
-        }
-        return marshalJSONDocument(json, objectClass);
-    }
-
-    public Object marshalJSONDocument(String jsonString, Class<?> objectClass) throws JSONMarshalerException {
-        JSON json;
-        try {
-            json = JSON.parse(jsonString);
-
-        } catch(ParserException ex) {
-            throw new JSONMarshalerException("", ex);
-        } catch(IOException ex) {
-            throw new JSONMarshalerException("", ex);
-        }
-        return marshalJSONDocument(json, objectClass);
-    }
-
-    /*
-     * public Object marshalJSONDocumentArray(JSON.Array<Value> jsonArray,
-     * Class<?> objectClass) {
-     *
-     *
-     * return null; }
-     */
-    public Object marshalJSONDocumentArray(JSON.Array<Value> jsonArray, Class<?> objectClass) throws JSONMarshalerException {
-        int size = jsonArray.size();
-        Class<?> componentClass = objectClass.getComponentType();
-        Object array = Array.newInstance(componentClass, size);
-        for(int i = 0; i < size; i++) {
-            Value value = jsonArray.get(i);
-            if(value.getValueType() == Value.TYPE.OBJECT) {
-                Array.set(array, i, marshalJSONDocumentObject((JSON.Object<CharSequence, Value>) value, componentClass));
-            } else if(value.getValueType() == Value.TYPE.ARRAY) {
-                Array.set(array, i, marshalJSONDocumentArray((JSON.Array<Value>) value, componentClass));
-            } else if(componentClass.equals(int.class)) {
-                Array.set(array, i, jsonArray.get(i).getNumber().intValue());
-            } else if(componentClass.equals(float.class)) {
-                Array.set(array, i, jsonArray.get(i).getNumber().floatValue());
-            } else if(componentClass.equals(double.class)) {
-                Array.set(array, i, jsonArray.get(i).getNumber().doubleValue());
-            } else if(componentClass.equals(byte.class)) {
-                Array.set(array, i, jsonArray.get(i).getNumber().byteValue());
-            } else if(componentClass.equals(boolean.class)) {
-                Array.set(array, i, jsonArray.get(i).getBoolean());
-            } else if(componentClass.equals(String.class)) {
-                Array.set(array, i, jsonArray.get(i).getString());
-            } else {
-                //
-            }
-        }
-        return array;
-    }
-
-    /*
-     * public boolean[]
-     * marshalJSONDocumentIntegerArrayPrimitive(JSON.Array<Value> jsonArray,
-     * Class<?> objectClass) { int size = jsonArray.size(); boolean[] array =
-     * (boolean[]) Array.newInstance(objectClass.getComponentType(), size); for
-     * (int i = 0; i < size; i++) { Array.set(array, i,
-     * jsonArray.get(i).getNumber().intValue()); } return array; }
-     *
-     * public Boolean[] marshalJSONDocumentIntegerArray(JSON.Array<Value>
-     * jsonArray, Class<?> objectClass) { int size = jsonArray.size(); Boolean[]
-     * array = (Boolean[]) Array.newInstance(objectClass.getComponentType(),
-     * size); for (int i = 0; i < size; i++) { Array.set(array, i,
-     * jsonArray.get(i).getNumber().intValue()); } return array; }
-     *
-     *
-     * public int[] marshalJSONDocumentIntegerArrayPrimitive(JSON.Array<Value>
-     * jsonArray, Class<?> objectClass) { int size = jsonArray.size(); int[]
-     * array = (int[]) Array.newInstance(objectClass.getComponentType(), size);
-     * for (int i = 0; i < size; i++) { Array.set(array, i,
-     * jsonArray.get(i).getNumber().intValue()); } return array; }
-     *
-     * public Integer[] marshalJSONDocumentIntegerArray(JSON.Array<Value>
-     * jsonArray, Class<?> objectClass) { int size = jsonArray.size(); Integer[]
-     * array = (Integer[]) Array.newInstance(objectClass.getComponentType(),
-     * size); for (int i = 0; i < size; i++) { Array.set(array, i,
-     * jsonArray.get(i).getNumber().intValue()); } return array; }
-     */
-    public static class MarshalerPropertyValue {
-
-        String name;
-
-        InspectorProperty property;
-
-        Value value;
-
-        public MarshalerPropertyValue() {
-            this.name = null;
-            this.property = null;
-            this.value = null;
-        }
-
-        public MarshalerPropertyValue(String name, InspectorProperty property, Value value) {
-            this.name = name;
-            this.property = property;
-            this.value = value;
-        }
-
-        public String getName() {
-            return name;
-        }
-
-        public void setName(String name) {
-            this.name = name;
-        }
-
-        public InspectorProperty getProperty() {
-            return property;
-        }
-
-        public void setProperty(InspectorProperty property) {
-            this.property = property;
-        }
-
-        public Value getValue() {
-            return value;
-        }
-
-        public void setValue(Value value) {
-            this.value = value;
-        }
-
-        @Override
-        public String toString() {
-            StringBuilder resultBuilder = new StringBuilder();
-            resultBuilder.append("MarshalerPropertyValue [Name:").append(name).append('|');
-            resultBuilder.append("Property:").append(property);
-            resultBuilder.append("->");
-            resultBuilder.append("Value:").append(value).append(']');
-            return resultBuilder.toString();
-        }
-    }
-}
+/*
+ * Copyright 2011 jmarsden.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package cc.plural.jsonij.marshal;
+
+import java.io.IOException;
+import java.io.InputStream;
+import cc.plural.jsonij.reflect.JavaType;
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import cc.plural.jsonij.JSON;
+import cc.plural.jsonij.Value;
+import cc.plural.jsonij.parser.ParserException;
+
+/**
+ *
+ * @author jmarsden
+ */
+public class JSONDocumentMarshaler {
+
+    public static String innerArrayAttribute;
+
+    public static String innerObjectAttribute;
+
+    static {
+        innerArrayAttribute = "_innerArray";
+        innerObjectAttribute = "_innerObject";
+    }
+
+    public Object marshalJSONDocument(JSON json, Class<?> objectClass) throws JSONMarshalerException {
+        Object resultObject = null;
+        Value jsonRoot = json.getRoot();
+        if(jsonRoot.type() == Value.TYPE.OBJECT) {
+            JSON.Object<CharSequence, Value> jsonObjectRoot = (JSON.Object<CharSequence, Value>) jsonRoot;
+            resultObject = marshalJSONDocumentObject(jsonObjectRoot, objectClass);
+        } else if(jsonRoot.type() == Value.TYPE.ARRAY) {
+            JSON.Array<Value> jsonArrayRoot = (JSON.Array<Value>) jsonRoot;
+            resultObject = marshalJSONDocumentArray(jsonArrayRoot, objectClass);
+        } else {
+            //throw new Exception();
+        }
+        return resultObject;
+    }
+
+    public Object marshalJSONDocument(Value value, Class<?> objectClass) throws JSONMarshalerException {
+        Object resultObject = null;
+        if(value.type() == Value.TYPE.OBJECT) {
+            JSON.Object<CharSequence, Value> jsonObjectRoot = (JSON.Object<CharSequence, Value>) value;
+            resultObject = marshalJSONDocumentObject(jsonObjectRoot, objectClass);
+        } else if(value.type() == Value.TYPE.ARRAY) {
+            JSON.Array<Value> jsonArrayRoot = (JSON.Array<Value>) value;
+            resultObject = marshalJSONDocumentArray(jsonArrayRoot, objectClass);
+        } else {
+            //throw new Exception();
+        }
+        return resultObject;
+    }
+
+    public Object marshalJSONDocumentObject(JSON.Object<CharSequence, Value> jsonObject, Class<?> objectClass) throws JSONMarshalerException {
+        Object resultObject = null;
+
+        Set<Entry<CharSequence, Value>> entrySet = jsonObject.entrySet();
+        Iterator<Entry<CharSequence, Value>> entrySetIterator = entrySet.iterator();
+        Entry<CharSequence, Value> entry = null;
+        Inspector inspector = new Inspector(objectClass);
+        inspector.inspect();
+
+        boolean hasCollector = inspector.hasCollector();
+        Map<CharSequence, Value> collectorReference = null;
+
+        List<MarshalerPropertyValue> objectPropertyValues = new ArrayList<MarshalerPropertyValue>();
+        List<MarshalerPropertyValue> collectorPropertyValues = null;
+
+        if(hasCollector) {
+            collectorPropertyValues = new ArrayList<MarshalerPropertyValue>();
+        }
+
+        while(entrySetIterator.hasNext()) {
+            entry = entrySetIterator.next();
+            if(entry.getKey().toString().equals(innerObjectAttribute) && inspector.hasInnerObject()) {
+                /**
+                 * todo: handle the inner object
+                 */
+            }
+            String propertyName = entry.getKey().toString();
+            if(inspector.hasProperty(propertyName)) {
+                MarshalerPropertyValue propertyValue = new MarshalerPropertyValue(propertyName, inspector.getProperty(propertyName), entry.getValue());
+                objectPropertyValues.add(propertyValue);
+            } else if(hasCollector) {
+                MarshalerPropertyValue propertyValue = new MarshalerPropertyValue(propertyName, inspector.getProperty(propertyName), entry.getValue());
+                collectorPropertyValues.add(propertyValue);
+            }
+        }
+
+        try {
+            resultObject = objectClass.newInstance();
+            if(hasCollector) {
+                InspectorProperty prop = inspector.getCollector();
+                if(prop.getAccessPropertyType() == InspectorProperty.TYPE.METHOD) {
+                    Method method = objectClass.getMethod(prop.getAccessName());
+                    collectorReference = (Map<CharSequence, Value>) method.invoke(resultObject);
+                } else if(prop.getAccessPropertyType() == InspectorProperty.TYPE.FIELD) {
+                    Field field = objectClass.getField(prop.getMutateName());
+                    collectorReference = (Map<CharSequence, Value>) field.get(resultObject);
+                }
+            }
+
+            for(MarshalerPropertyValue propertyValue : objectPropertyValues) {
+                if(propertyValue.getValue().isNull()) {
+                    // TODO: Handle Null
+                }
+                InspectorProperty property = propertyValue.getProperty();
+                if(property.getAccessPropertyType() == InspectorProperty.TYPE.METHOD) {
+                    Method method = objectClass.getMethod(property.getMutateName(), property.getMutateInputType());
+                    JavaType mutateType = JavaType.inspectObjectType(property.getMutateInputType());
+
+                    JSON.Array<Value> arrayJSON = null;
+
+                    switch(mutateType) {
+                        case BOOLEAN:
+                            method.invoke(resultObject, propertyValue.getValue().getBoolean());
+                            break;
+                        case BYTE:
+                            method.invoke(resultObject, propertyValue.getValue().getNumber().byteValue());
+                            break;
+                        case INTEGER:
+                            method.invoke(resultObject, propertyValue.getValue().getNumber().intValue());
+                            break;
+                        case SHORT:
+                            method.invoke(resultObject, propertyValue.getValue().getNumber().shortValue());
+                            break;
+                        case FLOAT:
+                            method.invoke(resultObject, propertyValue.getValue().getNumber().floatValue());
+                            break;
+                        case LONG:
+                            method.invoke(resultObject, propertyValue.getValue().getNumber().longValue());
+                            break;
+                        case DOUBLE:
+                            method.invoke(resultObject, propertyValue.getValue().getNumber().doubleValue());
+                            break;
+                        case STRING:
+                            method.invoke(resultObject, propertyValue.getValue().getString());
+                            break;
+                        case ENUM:
+                            method.invoke(resultObject, propertyValue.getValue().getString());
+                            break;
+                        case MAP:
+
+                            break;
+                        case LIST:
+
+                            break;
+                        case OBJECT:
+                            JSON.Object<CharSequence, Value> objectJSON = (JSON.Object<CharSequence, Value>) propertyValue.getValue();
+                            method.invoke(resultObject, marshalJSONDocumentObject(objectJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_BYTE:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_SHORT:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_INTEGER:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_FLOAT:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_DOUBLE:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_LONG:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_STRING:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_ENUM:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_LIST:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_MAP:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            method.invoke(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        default:
+
+                            break;
+                    }
+                } else if(property.getAccessPropertyType() == InspectorProperty.TYPE.FIELD) {
+                    Field field = objectClass.getField(propertyValue.getProperty().getMutateName());
+                    JavaType mutateType = JavaType.inspectObjectType(property.getMutateInputType());
+
+                    JSON.Array<Value> arrayJSON = null;
+
+                    switch(mutateType) {
+                        case BOOLEAN:
+                            field.set(resultObject, propertyValue.getValue().getBoolean());
+                            break;
+                        case BYTE:
+                            field.set(resultObject, propertyValue.getValue().getNumber().byteValue());
+                            break;
+                        case INTEGER:
+                            field.set(resultObject, propertyValue.getValue().getNumber().intValue());
+                            break;
+                        case SHORT:
+                            field.set(resultObject, propertyValue.getValue().getNumber().shortValue());
+                            break;
+                        case FLOAT:
+                            field.set(resultObject, propertyValue.getValue().getNumber().floatValue());
+                            break;
+                        case LONG:
+                            field.set(resultObject, propertyValue.getValue().getNumber().longValue());
+                            break;
+                        case DOUBLE:
+                            field.set(resultObject, propertyValue.getValue().getNumber().doubleValue());
+                            break;
+                        case STRING:
+                            field.set(resultObject, propertyValue.getValue().getString());
+                            break;
+                        case ENUM:
+
+                            break;
+                        case MAP:
+
+                            break;
+                        case LIST:
+
+                            break;
+                        case OBJECT:
+                            JSON.Object<CharSequence, Value> objectJSON = (JSON.Object<CharSequence, Value>) propertyValue.getValue();
+                            field.set(resultObject, marshalJSONDocumentObject(objectJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_BYTE:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_SHORT:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_INTEGER:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_FLOAT:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_DOUBLE:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_LONG:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_STRING:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_ENUM:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_LIST:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_MAP:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        case ARRAY_ARRAY:
+                            arrayJSON = (JSON.Array<Value>) propertyValue.getValue();
+                            field.set(resultObject, marshalJSONDocumentArray(arrayJSON, property.getMutateInputType()));
+                            break;
+                        default:
+                            break;
+                    }
+                }
+            }
+            if(hasCollector) {
+                for(MarshalerPropertyValue propertyValue : collectorPropertyValues) {
+                    collectorReference.put(propertyValue.getName(), propertyValue.getValue());
+                }
+            }
+        } catch(InstantiationException ex) {
+            Logger.getLogger(JSONDocumentMarshaler.class.getName()).log(Level.SEVERE, null, ex);
+        } catch(IllegalAccessException ex) {
+            Logger.getLogger(JSONDocumentMarshaler.class.getName()).log(Level.SEVERE, null, ex);
+        } catch(NoSuchFieldException ex) {
+            Logger.getLogger(JSONDocumentMarshaler.class.getName()).log(Level.SEVERE, null, ex);
+        } catch(NoSuchMethodException ex) {
+            Logger.getLogger(JSONDocumentMarshaler.class.getName()).log(Level.SEVERE, null, ex);
+        } catch(InvocationTargetException ex) {
+            Logger.getLogger(JSONDocumentMarshaler.class.getName()).log(Level.SEVERE, null, ex);
+        }
+        return resultObject;
+    }
+
+    public Object marshalJSONDocument(InputStream stream, Class<?> objectClass) throws JSONMarshalerException {
+        JSON json;
+        try {
+            json = JSON.parse(stream);
+
+        } catch(ParserException ex) {
+            throw new JSONMarshalerException("", ex);
+        } catch(IOException ex) {
+            throw new JSONMarshalerException("", ex);
+        }
+        return marshalJSONDocument(json, objectClass);
+    }
+
+    public Object marshalJSONDocument(String jsonString, Class<?> objectClass) throws JSONMarshalerException {
+        JSON json;
+        try {
+            json = JSON.parse(jsonString);
+
+        } catch(ParserException ex) {
+            throw new JSONMarshalerException("", ex);
+        } catch(IOException ex) {
+            throw new JSONMarshalerException("", ex);
+        }
+        return marshalJSONDocument(json, objectClass);
+    }
+
+    /*
+     * public Object marshalJSONDocumentArray(JSON.Array<Value> jsonArray,
+     * Class<?> objectClass) {
+     *
+     *
+     * return null; }
+     */
+    public Object marshalJSONDocumentArray(JSON.Array<Value> jsonArray, Class<?> objectClass) throws JSONMarshalerException {
+        int size = jsonArray.size();
+        Class<?> componentClass = objectClass.getComponentType();
+        Object array = Array.newInstance(componentClass, size);
+        for(int i = 0; i < size; i++) {
+            Value value = jsonArray.get(i);
+            if(value.getValueType() == Value.TYPE.OBJECT) {
+                Array.set(array, i, marshalJSONDocumentObject((JSON.Object<CharSequence, Value>) value, componentClass));
+            } else if(value.getValueType() == Value.TYPE.ARRAY) {
+                Array.set(array, i, marshalJSONDocumentArray((JSON.Array<Value>) value, componentClass));
+            } else if(componentClass.equals(int.class)) {
+                Array.set(array, i, jsonArray.get(i).getNumber().intValue());
+            } else if(componentClass.equals(float.class)) {
+                Array.set(array, i, jsonArray.get(i).getNumber().floatValue());
+            } else if(componentClass.equals(double.class)) {
+                Array.set(array, i, jsonArray.get(i).getNumber().doubleValue());
+            } else if(componentClass.equals(byte.class)) {
+                Array.set(array, i, jsonArray.get(i).getNumber().byteValue());
+            } else if(componentClass.equals(boolean.class)) {
+                Array.set(array, i, jsonArray.get(i).getBoolean());
+            } else if(componentClass.equals(String.class)) {
+                Array.set(array, i, jsonArray.get(i).getString());
+            } else {
+                //
+            }
+        }
+        return array;
+    }
+
+    /*
+     * public boolean[]
+     * marshalJSONDocumentIntegerArrayPrimitive(JSON.Array<Value> jsonArray,
+     * Class<?> objectClass) { int size = jsonArray.size(); boolean[] array =
+     * (boolean[]) Array.newInstance(objectClass.getComponentType(), size); for
+     * (int i = 0; i < size; i++) { Array.set(array, i,
+     * jsonArray.get(i).getNumber().intValue()); } return array; }
+     *
+     * public Boolean[] marshalJSONDocumentIntegerArray(JSON.Array<Value>
+     * jsonArray, Class<?> objectClass) { int size = jsonArray.size(); Boolean[]
+     * array = (Boolean[]) Array.newInstance(objectClass.getComponentType(),
+     * size); for (int i = 0; i < size; i++) { Array.set(array, i,
+     * jsonArray.get(i).getNumber().intValue()); } return array; }
+     *
+     *
+     * public int[] marshalJSONDocumentIntegerArrayPrimitive(JSON.Array<Value>
+     * jsonArray, Class<?> objectClass) { int size = jsonArray.size(); int[]
+     * array = (int[]) Array.newInstance(objectClass.getComponentType(), size);
+     * for (int i = 0; i < size; i++) { Array.set(array, i,
+     * jsonArray.get(i).getNumber().intValue()); } return array; }
+     *
+     * public Integer[] marshalJSONDocumentIntegerArray(JSON.Array<Value>
+     * jsonArray, Class<?> objectClass) { int size = jsonArray.size(); Integer[]
+     * array = (Integer[]) Array.newInstance(objectClass.getComponentType(),
+     * size); for (int i = 0; i < size; i++) { Array.set(array, i,
+     * jsonArray.get(i).getNumber().intValue()); } return array; }
+     */
+    public static class MarshalerPropertyValue {
+
+        String name;
+
+        InspectorProperty property;
+
+        Value value;
+
+        public MarshalerPropertyValue() {
+            this.name = null;
+            this.property = null;
+            this.value = null;
+        }
+
+        public MarshalerPropertyValue(String name, InspectorProperty property, Value value) {
+            this.name = name;
+            this.property = property;
+            this.value = value;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public void setName(String name) {
+            this.name = name;
+        }
+
+        public InspectorProperty getProperty() {
+            return property;
+        }
+
+        public void setProperty(InspectorProperty property) {
+            this.property = property;
+        }
+
+        public Value getValue() {
+            return value;
+        }
+
+        public void setValue(Value value) {
+            this.value = value;
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder resultBuilder = new StringBuilder();
+            resultBuilder.append("MarshalerPropertyValue [Name:").append(name).append('|');
+            resultBuilder.append("Property:").append(property);
+            resultBuilder.append("->");
+            resultBuilder.append("Value:").append(value).append(']');
+            return resultBuilder.toString();
+        }
+    }
+}

src/main/java/cc/plural/jsonij/marshal/JSONMarshaler.java

+/**
+ * Copyright (C) 2010-2011 J.W.Marsden
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+package cc.plural.jsonij;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import cc.plural.jsonij.marshal.JSONDocumentMarshaler;
+import cc.plural.jsonij.marshal.JSONMarshalerException;
+import cc.plural.jsonij.marshal.JavaMarshaler;
+import cc.plural.jsonij.parser.ParserException;
+
+/**
+ *
+ * @author openecho
+ */
+public class JSONMarshaler {
+
+    protected static final JavaMarshaler javaMarshaler;
+    protected static final JSONDocumentMarshaler jsonMarshaler;
+
+    static {
+        javaMarshaler = new JavaMarshaler();
+        jsonMarshaler = new JSONDocumentMarshaler();
+    }
+
+    public static JSON marshalObject(Object o) {
+        Value mashaledObject = javaMarshaler.marshalObject(o);
+        return new JSON(mashaledObject);
+    }
+
+    public static JSON marshalObject(boolean[] a) {
+        Value marshaledArray = javaMarshaler.marshalObject(a);
+        return new JSON(marshaledArray);
+    }
+
+    public static JSON marshalObject(Boolean[] a) {
+        Value marshaledArray = javaMarshaler.marshalObject(a);
+        return new JSON(marshaledArray);
+    }
+
+    public static JSON marshalObject(int[] a) {
+        Value marshaledArray = javaMarshaler.marshalObject(a);
+        return new JSON(marshaledArray);
+    }
+
+    public static JSON marshalObject(Integer[] a) {
+        Value marshaledArray = javaMarshaler.marshalObject(a);
+        return new JSON(marshaledArray);
+    }
+
+    public static JSON marshalObject(char[] a) {
+        Value marshaledArray = javaMarshaler.marshalObject(a);
+        return new JSON(marshaledArray);
+    }
+
+    public static JSON marshalObject(Character[] a) {
+        Value marshaledArray = javaMarshaler.marshalObject(a);
+        return new JSON(marshaledArray);
+    }
+
+    public static JSON marshalObject(double[] a) {
+        Value marshaledArray = javaMarshaler.marshalObject(a);
+        return new JSON(marshaledArray);
+    }
+
+    public static JSON marshalObject(Double[] a) {
+        Value marshaledArray = javaMarshaler.marshalObject(a);
+        return new JSON(marshaledArray);
+    }
+
+    public static JSON marshalObject(float[] a) {
+        Value marshaledArray = javaMarshaler.marshalObject(a);
+        return new JSON(marshaledArray);
+    }