JSONFactory.java
package com.alibaba.fastjson2;
import com.alibaba.fastjson2.reader.ObjectReader;
import com.alibaba.fastjson2.reader.ObjectReaderCreator;
import com.alibaba.fastjson2.reader.ObjectReaderProvider;
import com.alibaba.fastjson2.util.Fnv;
import com.alibaba.fastjson2.util.IOUtils;
import com.alibaba.fastjson2.util.JDKUtils;
import com.alibaba.fastjson2.writer.ObjectWriterCreator;
import com.alibaba.fastjson2.writer.ObjectWriterProvider;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.*;
import java.util.function.Function;
import java.util.function.Supplier;
import static com.alibaba.fastjson2.util.JDKUtils.JVM_VERSION;
public final class JSONFactory {
static volatile Throwable initErrorLast;
public static final String CREATOR;
public static final String PROPERTY_DENY_PROPERTY = "fastjson2.parser.deny";
public static final String PROPERTY_AUTO_TYPE_ACCEPT = "fastjson2.autoTypeAccept";
public static final String PROPERTY_AUTO_TYPE_HANDLER = "fastjson2.autoTypeHandler";
public static final String PROPERTY_AUTO_TYPE_BEFORE_HANDLER = "fastjson2.autoTypeBeforeHandler";
public static final boolean MIXED_HASH_ALGORITHM;
protected static boolean useJacksonAnnotation;
public static String getProperty(String key) {
return DEFAULT_PROPERTIES.getProperty(key);
}
static long defaultReaderFeatures;
static long defaultWriterFeatures;
static Supplier<Map> defaultObjectSupplier;
static Supplier<List> defaultArraySupplier;
static final NameCacheEntry[] NAME_CACHE = new NameCacheEntry[8192];
static final NameCacheEntry2[] NAME_CACHE2 = new NameCacheEntry2[8192];
static final Function<JSONWriter.Context, JSONWriter> INCUBATOR_VECTOR_WRITER_CREATOR_UTF8;
static final Function<JSONWriter.Context, JSONWriter> INCUBATOR_VECTOR_WRITER_CREATOR_UTF16;
static final JSONReaderUTF8Creator INCUBATOR_VECTOR_READER_CREATOR_ASCII;
static final JSONReaderUTF8Creator INCUBATOR_VECTOR_READER_CREATOR_UTF8;
static final JSONReaderUTF16Creator INCUBATOR_VECTOR_READER_CREATOR_UTF16;
interface JSONReaderUTF8Creator {
JSONReader create(JSONReader.Context ctx, String str, byte[] bytes, int offset, int length);
}
interface JSONReaderUTF16Creator {
JSONReader create(JSONReader.Context ctx, String str, char[] chars, int offset, int length);
}
static final class NameCacheEntry {
final String name;
final long value;
public NameCacheEntry(String name, long value) {
this.name = name;
this.value = value;
}
}
static final class NameCacheEntry2 {
final String name;
final long value0;
final long value1;
public NameCacheEntry2(String name, long value0, long value1) {
this.name = name;
this.value0 = value0;
this.value1 = value1;
}
}
static final BigDecimal LOW = BigDecimal.valueOf(-9007199254740991L);
static final BigDecimal HIGH = BigDecimal.valueOf(9007199254740991L);
static final BigInteger LOW_BIGINT = BigInteger.valueOf(-9007199254740991L);
static final BigInteger HIGH_BIGINT = BigInteger.valueOf(9007199254740991L);
static final char[] CA = new char[]{
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', '+', '/'
};
static final int[] DIGITS2 = new int[]{
+0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0,
+0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0,
+0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0,
+0, +1, +2, +3, +4, +5, +6, +7, +8, +9, +0, +0, +0, +0, +0, +0,
+0, 10, 11, 12, 13, 14, 15, +0, +0, +0, +0, +0, +0, +0, +0, +0,
+0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0, +0,
+0, 10, 11, 12, 13, 14, 15
};
static final long INFLATED = Long.MIN_VALUE;
static final double[] SMALL_10_POW = {
1.0e0,
1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5,
1.0e6, 1.0e7, 1.0e8, 1.0e9, 1.0e10,
1.0e11, 1.0e12, 1.0e13, 1.0e14, 1.0e15
};
static final float[] FLOAT_10_POW = {
1.0e0f, 1.0e1f, 1.0e2f, 1.0e3f, 1.0e4f, 1.0e5f,
1.0e6f, 1.0e7f, 1.0e8f, 1.0e9f, 1.0e10f
};
static final double[] DOUBLE_10_POW = {
1.0e0, 1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5,
1.0e6, 1.0e7, 1.0e8, 1.0e9, 1.0e10, 1.0e11,
1.0e12, 1.0e13, 1.0e14, 1.0e15, 1.0e16, 1.0e17,
1.0e18, 1.0e19, 1.0e20, 1.0e21, 1.0e22
};
static final Double DOUBLE_ZERO = Double.valueOf(0);
static {
Properties properties = new Properties();
InputStream inputStream = AccessController.doPrivileged((PrivilegedAction<InputStream>) () -> {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
final String resourceFile = "fastjson2.properties";
if (cl != null) {
return cl.getResourceAsStream(resourceFile);
} else {
return ClassLoader.getSystemResourceAsStream(resourceFile);
}
});
if (inputStream != null) {
try {
properties.load(inputStream);
} catch (java.io.IOException ignored) {
} finally {
IOUtils.close(inputStream);
}
}
DEFAULT_PROPERTIES = properties;
{
String property = System.getProperty("fastjson2.creator");
if (property != null) {
property = property.trim();
}
if (property == null || property.isEmpty()) {
property = properties.getProperty("fastjson2.creator");
if (property != null) {
property = property.trim();
}
}
CREATOR = property == null ? "asm" : property;
}
{
String property = System.getProperty("fastjson2.hash-algorithm");
if (property != null) {
property = property.trim();
}
if (property == null || property.isEmpty()) {
property = properties.getProperty("fastjson2.hash-algorithm");
if (property != null) {
property = property.trim();
}
}
if ("mixed".equals(property)) {
MIXED_HASH_ALGORITHM = true;
} else {
MIXED_HASH_ALGORITHM = JVM_VERSION > 8;
}
}
{
String property = System.getProperty("fastjson2.useJacksonAnnotation");
if (property != null) {
property = property.trim();
}
if (property == null || property.isEmpty()) {
property = properties.getProperty("fastjson2.useJacksonAnnotation");
if (property != null) {
property = property.trim();
}
}
useJacksonAnnotation = !"false".equals(property);
}
Function<JSONWriter.Context, JSONWriter> incubatorVectorCreatorUTF8 = null;
Function<JSONWriter.Context, JSONWriter> incubatorVectorCreatorUTF16 = null;
JSONReaderUTF8Creator readerCreatorASCII = null;
JSONReaderUTF8Creator readerCreatorUTF8 = null;
JSONReaderUTF16Creator readerCreatorUTF16 = null;
if (JDKUtils.VECTOR_SUPPORT) {
try {
Class<?> factoryClass = Class.forName("com.alibaba.fastjson2.JSONWriterUTF8Vector$Factory");
incubatorVectorCreatorUTF8 = (Function<JSONWriter.Context, JSONWriter>) factoryClass.newInstance();
} catch (Throwable ignored) {
// skip
initErrorLast = ignored;
}
try {
Class<?> factoryClass = Class.forName("com.alibaba.fastjson2.JSONWriterUTF16Vector$Factory");
incubatorVectorCreatorUTF16 = (Function<JSONWriter.Context, JSONWriter>) factoryClass.newInstance();
} catch (Throwable ignored) {
// skip
initErrorLast = ignored;
}
try {
Class<?> factoryClass = Class.forName("com.alibaba.fastjson2.JSONReaderASCIIVector$Factory");
readerCreatorASCII = (JSONReaderUTF8Creator) factoryClass.newInstance();
} catch (Throwable ignored) {
// skip
initErrorLast = ignored;
}
try {
Class<?> factoryClass = Class.forName("com.alibaba.fastjson2.JSONReaderUTF8Vector$Factory");
readerCreatorUTF8 = (JSONReaderUTF8Creator) factoryClass.newInstance();
} catch (Throwable ignored) {
// skip
initErrorLast = ignored;
}
try {
Class<?> factoryClass = Class.forName("com.alibaba.fastjson2.JSONReaderUTF16Vector$Factory");
readerCreatorUTF16 = (JSONReaderUTF16Creator) factoryClass.newInstance();
} catch (Throwable ignored) {
// skip
initErrorLast = ignored;
}
}
INCUBATOR_VECTOR_WRITER_CREATOR_UTF8 = incubatorVectorCreatorUTF8;
INCUBATOR_VECTOR_WRITER_CREATOR_UTF16 = incubatorVectorCreatorUTF16;
INCUBATOR_VECTOR_READER_CREATOR_ASCII = readerCreatorASCII;
INCUBATOR_VECTOR_READER_CREATOR_UTF8 = readerCreatorUTF8;
INCUBATOR_VECTOR_READER_CREATOR_UTF16 = readerCreatorUTF16;
}
public static boolean isUseJacksonAnnotation() {
return useJacksonAnnotation;
}
public static void setUseJacksonAnnotation(boolean useJacksonAnnotation) {
JSONFactory.useJacksonAnnotation = useJacksonAnnotation;
}
static final int CACHE_SIZE = 4;
private static final int CACHE_THRESHOLD = 1024 * 1024;
private static final byte[][] BYTE_ARRAY_CACHE = new byte[CACHE_SIZE][];
private static final char[][] CHAR_ARRAY_CACHE = new char[CACHE_SIZE][];
static char[] allocateCharArray(int cacheIndex) {
char[] chars;
synchronized (CHAR_ARRAY_CACHE) {
chars = CHAR_ARRAY_CACHE[cacheIndex];
if (chars != null) {
CHAR_ARRAY_CACHE[cacheIndex] = null;
}
}
if (chars == null) {
chars = new char[8192];
}
return chars;
}
static void releaseCharArray(int cacheIndex, char[] chars) {
if (chars == null || chars.length > CACHE_THRESHOLD) {
return;
}
synchronized (CHAR_ARRAY_CACHE) {
CHAR_ARRAY_CACHE[cacheIndex] = chars;
}
}
static byte[] allocateByteArray(int cacheIndex) {
byte[] bytes;
synchronized (BYTE_ARRAY_CACHE) {
bytes = BYTE_ARRAY_CACHE[cacheIndex];
if (bytes != null) {
BYTE_ARRAY_CACHE[cacheIndex] = null;
}
}
if (bytes == null) {
bytes = new byte[8192];
}
return bytes;
}
static void releaseByteArray(int cacheIndex, byte[] chars) {
if (chars == null || chars.length > CACHE_THRESHOLD) {
return;
}
synchronized (BYTE_ARRAY_CACHE) {
BYTE_ARRAY_CACHE[cacheIndex] = chars;
}
}
static final class SymbolTableImpl
implements SymbolTable {
private final String[] names;
private final long hashCode64;
private final short[] mapping;
private final long[] hashCodes;
private final long[] hashCodesOrigin;
SymbolTableImpl(String... input) {
Set<String> set = new TreeSet<>();
for (String name : input) {
set.add(name);
}
names = new String[set.size()];
Iterator<String> it = set.iterator();
for (int i = 0; i < names.length; i++) {
if (it.hasNext()) {
names[i] = it.next();
}
}
long[] hashCodes = new long[names.length];
for (int i = 0; i < names.length; i++) {
long hashCode = Fnv.hashCode64(names[i]);
hashCodes[i] = hashCode;
}
this.hashCodesOrigin = hashCodes;
this.hashCodes = Arrays.copyOf(hashCodes, hashCodes.length);
Arrays.sort(this.hashCodes);
mapping = new short[this.hashCodes.length];
for (int i = 0; i < hashCodes.length; i++) {
long hashCode = hashCodes[i];
int index = Arrays.binarySearch(this.hashCodes, hashCode);
mapping[index] = (short) i;
}
long hashCode64 = Fnv.MAGIC_HASH_CODE;
for (long hashCode : hashCodes) {
hashCode64 ^= hashCode;
hashCode64 *= Fnv.MAGIC_PRIME;
}
this.hashCode64 = hashCode64;
}
@Override
public int size() {
return names.length;
}
@Override
public long hashCode64() {
return hashCode64;
}
@Override
public String getNameByHashCode(long hashCode) {
int m = Arrays.binarySearch(hashCodes, hashCode);
if (m < 0) {
return null;
}
int index = this.mapping[m];
return names[index];
}
@Override
public int getOrdinalByHashCode(long hashCode) {
int m = Arrays.binarySearch(hashCodes, hashCode);
if (m < 0) {
return -1;
}
return this.mapping[m] + 1;
}
@Override
public int getOrdinal(String name) {
long hashCode = Fnv.hashCode64(name);
int m = Arrays.binarySearch(hashCodes, hashCode);
if (m < 0) {
return -1;
}
return this.mapping[m] + 1;
}
@Override
public String getName(int ordinal) {
return names[ordinal - 1];
}
@Override
public long getHashCode(int ordinal) {
return hashCodesOrigin[ordinal - 1];
}
}
static final Properties DEFAULT_PROPERTIES;
static ObjectWriterProvider defaultObjectWriterProvider = new ObjectWriterProvider();
static ObjectReaderProvider defaultObjectReaderProvider = new ObjectReaderProvider();
static final JSONPathCompiler defaultJSONPathCompiler;
static {
JSONPathCompilerReflect compiler = null;
switch (JSONFactory.CREATOR) {
case "reflect":
case "lambda":
compiler = JSONPathCompilerReflect.INSTANCE;
break;
default:
try {
if (!JDKUtils.ANDROID && !JDKUtils.GRAAL) {
compiler = JSONPathCompilerReflectASM.INSTANCE;
}
} catch (Throwable ignored) {
// ignored
}
if (compiler == null) {
compiler = JSONPathCompilerReflect.INSTANCE;
}
break;
}
defaultJSONPathCompiler = compiler;
}
static final ThreadLocal<ObjectReaderCreator> readerCreatorLocal = new ThreadLocal<>();
static final ThreadLocal<ObjectReaderProvider> readerProviderLocal = new ThreadLocal<>();
static final ThreadLocal<ObjectWriterCreator> writerCreatorLocal = new ThreadLocal<>();
static final ThreadLocal<JSONPathCompiler> jsonPathCompilerLocal = new ThreadLocal<>();
static final ObjectReader<JSONArray> ARRAY_READER = JSONFactory.getDefaultObjectReaderProvider().getObjectReader(JSONArray.class);
static final ObjectReader<JSONObject> OBJECT_READER = JSONFactory.getDefaultObjectReaderProvider().getObjectReader(JSONObject.class);
/**
* @param objectSupplier
* @since 2.0.15
*/
public static void setDefaultObjectSupplier(Supplier<Map> objectSupplier) {
defaultObjectSupplier = objectSupplier;
}
/**
* @param arraySupplier
* @since 2.0.15
*/
public static void setDefaultArraySupplier(Supplier<List> arraySupplier) {
defaultArraySupplier = arraySupplier;
}
public static Supplier<Map> getDefaultObjectSupplier() {
return defaultObjectSupplier;
}
public static Supplier<List> getDefaultArraySupplier() {
return defaultArraySupplier;
}
public static JSONWriter.Context createWriteContext() {
return new JSONWriter.Context(defaultObjectWriterProvider);
}
public static JSONWriter.Context createWriteContext(ObjectWriterProvider provider, JSONWriter.Feature... features) {
JSONWriter.Context context = new JSONWriter.Context(provider);
context.config(features);
return context;
}
public static JSONWriter.Context createWriteContext(JSONWriter.Feature... features) {
return new JSONWriter.Context(defaultObjectWriterProvider, features);
}
public static JSONReader.Context createReadContext() {
ObjectReaderProvider provider = JSONFactory.getDefaultObjectReaderProvider();
return new JSONReader.Context(provider);
}
public static JSONReader.Context createReadContext(long features) {
ObjectReaderProvider provider = JSONFactory.getDefaultObjectReaderProvider();
return new JSONReader.Context(provider, features);
}
public static JSONReader.Context createReadContext(JSONReader.Feature... features) {
JSONReader.Context context = new JSONReader.Context(
JSONFactory.getDefaultObjectReaderProvider()
);
context.config(features);
return context;
}
public static JSONReader.Context createReadContext(ObjectReaderProvider provider, JSONReader.Feature... features) {
if (provider == null) {
provider = getDefaultObjectReaderProvider();
}
JSONReader.Context context = new JSONReader.Context(provider);
context.config(features);
return context;
}
public static JSONReader.Context createReadContext(SymbolTable symbolTable) {
ObjectReaderProvider provider = JSONFactory.getDefaultObjectReaderProvider();
return new JSONReader.Context(provider, symbolTable);
}
public static JSONReader.Context createReadContext(SymbolTable symbolTable, JSONReader.Feature... features) {
ObjectReaderProvider provider = JSONFactory.getDefaultObjectReaderProvider();
JSONReader.Context context = new JSONReader.Context(provider, symbolTable);
context.config(features);
return context;
}
public static JSONReader.Context createReadContext(Supplier<Map> objectSupplier, JSONReader.Feature... features) {
ObjectReaderProvider provider = JSONFactory.getDefaultObjectReaderProvider();
JSONReader.Context context = new JSONReader.Context(provider);
context.setObjectSupplier(objectSupplier);
context.config(features);
return context;
}
public static JSONReader.Context createReadContext(
Supplier<Map> objectSupplier,
Supplier<List> arraySupplier,
JSONReader.Feature... features) {
ObjectReaderProvider provider = JSONFactory.getDefaultObjectReaderProvider();
JSONReader.Context context = new JSONReader.Context(provider);
context.setObjectSupplier(objectSupplier);
context.setArraySupplier(arraySupplier);
context.config(features);
return context;
}
public static ObjectWriterProvider getDefaultObjectWriterProvider() {
return defaultObjectWriterProvider;
}
public static ObjectReaderProvider getDefaultObjectReaderProvider() {
ObjectReaderProvider providerLocal = readerProviderLocal.get();
if (providerLocal != null) {
return providerLocal;
}
return defaultObjectReaderProvider;
}
public static JSONPathCompiler getDefaultJSONPathCompiler() {
JSONPathCompiler compilerLocal = jsonPathCompilerLocal.get();
if (compilerLocal != null) {
return compilerLocal;
}
return defaultJSONPathCompiler;
}
public static void setContextReaderCreator(ObjectReaderCreator creator) {
readerCreatorLocal.set(creator);
}
public static void setContextObjectReaderProvider(ObjectReaderProvider creator) {
readerProviderLocal.set(creator);
}
public static ObjectReaderCreator getContextReaderCreator() {
return readerCreatorLocal.get();
}
public static void setContextJSONPathCompiler(JSONPathCompiler compiler) {
jsonPathCompilerLocal.set(compiler);
}
public static void setContextWriterCreator(ObjectWriterCreator creator) {
writerCreatorLocal.set(creator);
}
public static ObjectWriterCreator getContextWriterCreator() {
return writerCreatorLocal.get();
}
public interface JSONPathCompiler {
JSONPath compile(Class objectClass, JSONPath path);
}
}