blue.endless.jankson.impl.POJODeserializer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jankson Show documentation
Show all versions of jankson Show documentation
JSON5 / HJSON parser and preprocessor which preserves ordering and comments
/*
* MIT License
*
* Copyright (c) 2018-2019 Falkreon (Isaac Ellingson)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package blue.endless.jankson.impl;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import blue.endless.jankson.JsonArray;
import blue.endless.jankson.JsonElement;
import blue.endless.jankson.JsonGrammar;
import blue.endless.jankson.JsonNull;
import blue.endless.jankson.JsonObject;
import blue.endless.jankson.JsonPrimitive;
import blue.endless.jankson.annotation.Deserializer;
import blue.endless.jankson.annotation.SerializedName;
import blue.endless.jankson.api.DeserializationException;
import blue.endless.jankson.impl.serializer.InternalDeserializerFunction;
import blue.endless.jankson.impl.serializer.DeserializerFunctionPool;
import blue.endless.jankson.magic.TypeMagic;
public class POJODeserializer {
public static void unpackObject(Object target, JsonObject source) {
try {
unpackObject(target, source, false);
} catch (Throwable t) {
}
}
public static void unpackObject(Object target, JsonObject source, boolean failFast) throws DeserializationException {
//if (o.getClass().getTypeParameters().length>0) throw new DeserializationException("Can't safely deserialize generic types!");
//well, let's try anyway and see if we run into problems.
//Create a copy we can redact keys from
JsonObject work = source.clone();
//Fill public and private fields declared in the target object's immediate class
for(Field f : target.getClass().getDeclaredFields()) {
int modifiers = f.getModifiers();
if (Modifier.isStatic(modifiers) || Modifier.isTransient(modifiers)) continue;
unpackField(target, f, work, failFast);
}
//Attempt to fill public, accessible fields declared in the target object's superclass.
for(Field f : target.getClass().getFields()) {
int modifiers = f.getModifiers();
if (Modifier.isStatic(modifiers) || Modifier.isTransient(modifiers)) continue;
unpackField(target, f, work, failFast);
}
if (!work.isEmpty() && failFast) {
throw new DeserializationException("There was data that couldn't be applied to the destination object: "+work.toJson(JsonGrammar.STRICT));
}
}
public static void unpackField(Object parent, Field f, JsonObject source, boolean failFast) throws DeserializationException {
String fieldName = f.getName();
SerializedName nameAnnotation = f.getAnnotation(SerializedName.class);
if (nameAnnotation!=null) fieldName = nameAnnotation.value();
if (source.containsKey(fieldName)) {
JsonElement elem = source.get(fieldName);
source.remove(fieldName); //Prevent it from getting re-unpacked
if (elem==null || elem==JsonNull.INSTANCE) {
boolean accessible = f.isAccessible();
if (!accessible) f.setAccessible(true);
try {
f.set(parent, null);
if (!accessible) f.setAccessible(false);
} catch (IllegalArgumentException | IllegalAccessException ex) {
if (failFast) throw new DeserializationException("Couldn't set field \""+f.getName()+"\" of class \""+parent.getClass().getCanonicalName()+"\"", ex);
}
} else {
try {
unpackFieldData(parent, f, elem, source.getMarshaller());
} catch (Throwable t) {
if (failFast) throw new DeserializationException("There was a problem unpacking field "+f.getName()+" of class "+parent.getClass().getCanonicalName(), t);
}
}
}
}
/** NOT WORKING YET, HIGHLY EXPERIMENTAL */
@SuppressWarnings("unchecked")
@Nullable
public static Object unpack(Type t, JsonElement elem, blue.endless.jankson.api.Marshaller marshaller) {
Class> rawClass = TypeMagic.classForType(t);
if (rawClass.isPrimitive()) return null; //We can't unpack a primitive into an object of primitive type. Maybe in the future we can return a boxed type?
if (elem==null) return null;
/*
if (type instanceof Class) {
try {
return marshaller.marshall((Class>) type, elem);
} catch (ClassCastException t) {
return null;
}
}
if (type instanceof ParameterizedType) {
try {
Class> clazz = (Class>) TypeMagic.classForType(type);
if (List.class.isAssignableFrom(clazz)) {
Object result = TypeMagic.createAndCast(type);
try {
unpackList((List
© 2015 - 2024 Weber Informatics LLC | Privacy Policy