Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
Uber-fast, ultra-lightweight Java classpath scanner. Scans the classpath by parsing the classfile binary format directly rather than by using reflection.
See https://github.com/lukehutch/fast-classpath-scanner
/*
* This file is part of FastClasspathScanner.
*
* Author: Luke Hutchison
*
* Hosted at: https://github.com/lukehutch/fast-classpath-scanner
*
* --
*
* The MIT License (MIT)
*
* Copyright (c) 2018 Luke Hutchison
*
* 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 io.github.lukehutch.fastclasspathscanner.json;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import io.github.lukehutch.fastclasspathscanner.json.JSONUtils.ParameterizedTypeImpl;
/**
* Fast, lightweight Java object to JSON serializer, and JSON to Java object deserializer. Handles cycles in the
* object graph by inserting reference ids.
*/
public class JSONDeserializer {
/**
* Deserialize a JSON basic value (String, Integer, Long, or Double), conforming it to the expected type
* (Character, Short, etc.).
*/
private static Object jsonBasicValueToObject(final Object jsonVal, final Type expectedType,
final boolean convertStringToNumber) {
if (jsonVal == null) {
return null;
} else if (jsonVal instanceof JSONArray || jsonVal instanceof JSONObject) {
throw new RuntimeException("Expected a basic value type");
}
if (expectedType instanceof ParameterizedType) {
// TODO: add support for Class reference values, which may be parameterized
throw new IllegalArgumentException("Got illegal ParameterizedType: " + expectedType);
} else if (!(expectedType instanceof Class>)) {
throw new IllegalArgumentException("Got illegal basic value type: " + expectedType);
}
final Class> rawType = (Class>) expectedType;
if (rawType == String.class) {
if (!(jsonVal instanceof CharSequence)) {
throw new IllegalArgumentException("Expected string; got " + jsonVal.getClass().getName());
}
return jsonVal.toString();
} else if (rawType == CharSequence.class) {
if (!(jsonVal instanceof CharSequence)) {
throw new IllegalArgumentException("Expected CharSequence; got " + jsonVal.getClass().getName());
}
return jsonVal;
} else if (rawType == Integer.class || rawType == Integer.TYPE) {
if (convertStringToNumber && jsonVal instanceof CharSequence) {
return Integer.parseInt(jsonVal.toString());
}
if (!(jsonVal instanceof Integer)) {
throw new IllegalArgumentException("Expected integer; got " + jsonVal.getClass().getName());
}
return jsonVal;
} else if (rawType == Long.class || rawType == Long.TYPE) {
final boolean isLong = jsonVal instanceof Long;
final boolean isInteger = jsonVal instanceof Integer;
if (convertStringToNumber && jsonVal instanceof CharSequence) {
return isLong ? Long.parseLong(jsonVal.toString()) : Integer.parseInt(jsonVal.toString());
}
if (!(isLong || isInteger)) {
throw new IllegalArgumentException("Expected long; got " + jsonVal.getClass().getName());
}
if (isLong) {
return jsonVal;
} else {
return Long.valueOf(((Integer) jsonVal).intValue());
}
} else if (rawType == Short.class || rawType == Short.TYPE) {
if (convertStringToNumber && jsonVal instanceof CharSequence) {
return Short.parseShort(jsonVal.toString());
}
if (!(jsonVal instanceof Integer)) {
throw new IllegalArgumentException("Expected short; got " + jsonVal.getClass().getName());
}
final int intValue = ((Integer) jsonVal).intValue();
if (intValue < Short.MIN_VALUE || intValue > Short.MAX_VALUE) {
throw new IllegalArgumentException("Expected short; got out-of-range value " + intValue);
}
return Short.valueOf((short) intValue);
} else if (rawType == Float.class || rawType == Float.TYPE) {
if (convertStringToNumber && jsonVal instanceof CharSequence) {
return Float.parseFloat(jsonVal.toString());
}
if (!(jsonVal instanceof Double)) {
throw new IllegalArgumentException("Expected float; got " + jsonVal.getClass().getName());
}
final double doubleValue = ((Double) jsonVal).doubleValue();
if (doubleValue < Float.MIN_VALUE || doubleValue > Float.MAX_VALUE) {
throw new IllegalArgumentException("Expected float; got out-of-range value " + doubleValue);
}
return Float.valueOf((float) doubleValue);
} else if (rawType == Double.class || rawType == Double.TYPE) {
if (convertStringToNumber && jsonVal instanceof CharSequence) {
return Double.parseDouble(jsonVal.toString());
}
if (!(jsonVal instanceof Double)) {
throw new IllegalArgumentException("Expected double; got " + jsonVal.getClass().getName());
}
return jsonVal;
} else if (rawType == Byte.class || rawType == Byte.TYPE) {
if (convertStringToNumber && jsonVal instanceof CharSequence) {
return Byte.parseByte(jsonVal.toString());
}
if (!(jsonVal instanceof Integer)) {
throw new IllegalArgumentException("Expected byte; got " + jsonVal.getClass().getName());
}
final int intValue = ((Integer) jsonVal).intValue();
if (intValue < Byte.MIN_VALUE || intValue > Byte.MAX_VALUE) {
throw new IllegalArgumentException("Expected byte; got out-of-range value " + intValue);
}
return Byte.valueOf((byte) intValue);
} else if (rawType == Character.class || rawType == Character.TYPE) {
if (!(jsonVal instanceof CharSequence)) {
throw new IllegalArgumentException("Expected character; got " + jsonVal.getClass().getName());
}
final CharSequence charSequence = (CharSequence) jsonVal;
if (charSequence.length() != 1) {
throw new IllegalArgumentException("Expected single character; got string");
}
return Character.valueOf(charSequence.charAt(0));
} else if (rawType == Boolean.class || rawType == Boolean.TYPE) {
if (convertStringToNumber && jsonVal instanceof CharSequence) {
return Boolean.parseBoolean(jsonVal.toString());
}
if (!(jsonVal instanceof Boolean)) {
throw new IllegalArgumentException("Expected boolean; got " + jsonVal.getClass().getName());
}
return jsonVal;
} else if (Enum.class.isAssignableFrom(rawType)) {
if (!(jsonVal instanceof CharSequence)) {
throw new IllegalArgumentException(
"Expected string for enum value; got " + jsonVal.getClass().getName());
}
@SuppressWarnings({ "rawtypes", "unchecked" })
final Enum enumValue = Enum.valueOf((Class) rawType, jsonVal.toString());
return enumValue;
} else if (JSONUtils.getRawType(expectedType).isAssignableFrom(jsonVal.getClass())) {
return jsonVal;
} else {
throw new IllegalArgumentException("Got type " + jsonVal.getClass() + "; expected " + expectedType);
}
}
/**
* Used to hold object instantiations temporarily before their fields can be populated, so that object
* references can be resolved in the same order during deserialization as they were created during
* serialization.
*/
private static class ObjectInstantiation {
/** The JSONObject or JSONArray to recurse into. */
Object jsonVal;
/** The Java object instance to populate from the JSONObject or JSONArray. */
Object objectInstance;
/** The resolved type of the object instance. */
Type type;
public ObjectInstantiation(final Object objectInstance, final Type type, final Object jsonVal) {
this.jsonVal = jsonVal;
this.objectInstance = objectInstance;
this.type = type;
}
}
private static void populateObjectFromJsonObject(final Object objectInstance, final Type objectResolvedType,
final Object jsonVal, final ClassFieldCache classFieldCache,
final Map idToObjectInstance, final List collectionElementAdders) {
// Leave objectInstance empty (or leave fields null) if jsonVal is null
if (jsonVal == null) {
return;
}
// Check jsonVal is JSONObject or JSONArray
final boolean isJsonObject = jsonVal instanceof JSONObject;
final boolean isJsonArray = jsonVal instanceof JSONArray;
if (!(isJsonArray || isJsonObject)) {
throw new IllegalArgumentException(
"Expected JSONObject or JSONArray, got " + jsonVal.getClass().getSimpleName());
}
final JSONObject jsonObject = isJsonObject ? (JSONObject) jsonVal : null;
final JSONArray jsonArray = isJsonArray ? (JSONArray) jsonVal : null;
// Check concrete type of object instance
final Class> rawType = objectInstance.getClass();
final boolean isMap = Map.class.isAssignableFrom(rawType);
@SuppressWarnings("unchecked")
final Map