com.alibaba.fastjson.JSON Maven / Gradle / Ivy
The newest version!
/*
* Copyright 1999-2017 Alibaba Group.
*
* 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 com.alibaba.fastjson;
import java.io.*;
import java.lang.reflect.Array;
import java.lang.reflect.Type;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.zip.GZIPInputStream;
import com.alibaba.fastjson.annotation.JSONType;
import com.alibaba.fastjson.parser.*;
import com.alibaba.fastjson.parser.deserializer.ExtraProcessor;
import com.alibaba.fastjson.parser.deserializer.ExtraTypeProvider;
import com.alibaba.fastjson.parser.deserializer.FieldTypeResolver;
import com.alibaba.fastjson.parser.deserializer.ParseProcess;
import com.alibaba.fastjson.serializer.*;
import com.alibaba.fastjson.util.IOUtils;
import com.alibaba.fastjson.util.TypeUtils;
/**
* This is the main class for using Fastjson. You usually call these two methods {@link #toJSONString(Object)} and {@link #parseObject(String, Class)}.
*
* Here is an example of how fastjson is used for a simple Class:
*
*
* Model model = new Model();
* String json = JSON.toJSONString(model); // serializes model to Json
* Model model2 = JSON.parseObject(json, Model.class); // deserializes json into model2
*
*
* If the object that your are serializing/deserializing is a {@code ParameterizedType}
* (i.e. contains at least one type parameter and may be an array) then you must use the
* {@link #toJSONString(Object)} or {@link #parseObject(String, Type, Feature[])} method. Here is an
* example for serializing and deserialing a {@code ParameterizedType}:
*
*
* String json = "[{},...]";
* Type listType = new TypeReference<List<Model>>() {}.getType();
* List<Model> modelList = JSON.parseObject(json, listType);
*
*
* @see com.alibaba.fastjson.TypeReference
*
* @author wenshao[[email protected]]
*/
public abstract class JSON implements JSONStreamAware, JSONAware {
public static TimeZone defaultTimeZone = TimeZone.getDefault();
public static Locale defaultLocale = Locale.getDefault();
public static String DEFAULT_TYPE_KEY = "@type";
static final SerializeFilter[] emptyFilters = new SerializeFilter[0];
public static String DEFFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
public static int DEFAULT_PARSER_FEATURE;
public static int DEFAULT_GENERATE_FEATURE;
private static final ConcurrentHashMap mixInsMapper = new ConcurrentHashMap(16);
static {
int features = 0;
features |= Feature.AutoCloseSource.getMask();
features |= Feature.InternFieldNames.getMask();
features |= Feature.UseBigDecimal.getMask();
features |= Feature.AllowUnQuotedFieldNames.getMask();
features |= Feature.AllowSingleQuotes.getMask();
features |= Feature.AllowArbitraryCommas.getMask();
features |= Feature.SortFeidFastMatch.getMask();
features |= Feature.IgnoreNotMatch.getMask();
DEFAULT_PARSER_FEATURE = features;
}
static {
int features = 0;
features |= SerializerFeature.QuoteFieldNames.getMask();
features |= SerializerFeature.SkipTransientField.getMask();
features |= SerializerFeature.WriteEnumUsingName.getMask();
features |= SerializerFeature.SortField.getMask();
DEFAULT_GENERATE_FEATURE = features;
config(IOUtils.DEFAULT_PROPERTIES);
}
private static void config(Properties properties) {
{
String featuresProperty = properties.getProperty("fastjson.serializerFeatures.MapSortField");
int mask = SerializerFeature.MapSortField.getMask();
if ("true".equals(featuresProperty)) {
DEFAULT_GENERATE_FEATURE |= mask;
} else if ("false".equals(featuresProperty)) {
DEFAULT_GENERATE_FEATURE &= ~mask;
}
}
{
if ("true".equals(properties.getProperty("parser.features.NonStringKeyAsString"))) {
DEFAULT_PARSER_FEATURE |= Feature.NonStringKeyAsString.getMask();
}
}
{
if ("true".equals(properties.getProperty("parser.features.ErrorOnEnumNotMatch"))
|| "true".equals(properties.getProperty("fastjson.parser.features.ErrorOnEnumNotMatch")))
{
DEFAULT_PARSER_FEATURE |= Feature.ErrorOnEnumNotMatch.getMask();
}
}
{
if ("false".equals(properties.getProperty("fastjson.asmEnable"))) {
ParserConfig.global.setAsmEnable(false);
SerializeConfig.globalInstance.setAsmEnable(false);
}
}
}
/**
* config default type key
* @since 1.2.14
*/
public static void setDefaultTypeKey(String typeKey) {
DEFAULT_TYPE_KEY = typeKey;
ParserConfig.global.symbolTable.addSymbol(typeKey,
0,
typeKey.length(),
typeKey.hashCode(), true);
}
public static Object parse(String text) {
return parse(text, DEFAULT_PARSER_FEATURE);
}
/**
*
* @since 1.2.38
*/
public static Object parse(String text, ParserConfig config) {
return parse(text, config, DEFAULT_PARSER_FEATURE);
}
/**
*
* @since 1.2.68
*/
public static Object parse(String text, ParserConfig config, Feature... features) {
int featureValues = DEFAULT_PARSER_FEATURE;
for (Feature feature : features) {
featureValues = Feature.config(featureValues, feature, true);
}
return parse(text, config, featureValues);
}
/**
*
* @since 1.2.38
*/
public static Object parse(String text, ParserConfig config, int features) {
if (text == null) {
return null;
}
DefaultJSONParser parser = new DefaultJSONParser(text, config, features);
Object value = parser.parse();
parser.handleResovleTask(value);
parser.close();
return value;
}
public static Object parse(String text, int features) {
return parse(text, ParserConfig.getGlobalInstance(), features);
}
public static Object parse(byte[] input, Feature... features) {
char[] chars = allocateChars(input.length);
int len = IOUtils.decodeUTF8(input, 0, input.length, chars);
if (len < 0) {
return null;
}
return parse(new String(chars, 0, len), features);
}
public static Object parse(byte[] input, int off, int len, CharsetDecoder charsetDecoder, Feature... features) {
if (input == null || input.length == 0) {
return null;
}
int featureValues = DEFAULT_PARSER_FEATURE;
for (Feature feature : features) {
featureValues = Feature.config(featureValues, feature, true);
}
return parse(input, off, len, charsetDecoder, featureValues);
}
public static Object parse(byte[] input, int off, int len, CharsetDecoder charsetDecoder, int features) {
charsetDecoder.reset();
int scaleLength = (int) (len * (double) charsetDecoder.maxCharsPerByte());
char[] chars = allocateChars(scaleLength);
ByteBuffer byteBuf = ByteBuffer.wrap(input, off, len);
CharBuffer charBuf = CharBuffer.wrap(chars);
IOUtils.decode(charsetDecoder, byteBuf, charBuf);
int position = charBuf.position();
DefaultJSONParser parser = new DefaultJSONParser(chars, position, ParserConfig.getGlobalInstance(), features);
Object value = parser.parse();
parser.handleResovleTask(value);
parser.close();
return value;
}
public static Object parse(String text, Feature... features) {
int featureValues = DEFAULT_PARSER_FEATURE;
for (Feature feature : features) {
featureValues = Feature.config(featureValues, feature, true);
}
return parse(text, featureValues);
}
public static JSONObject parseObject(String text, Feature... features) {
return (JSONObject) parse(text, features);
}
public static JSONObject parseObject(String text) {
Object obj = parse(text);
if (obj instanceof JSONObject) {
return (JSONObject) obj;
}
try {
return (JSONObject) JSON.toJSON(obj);
} catch (RuntimeException e) {
throw new JSONException("can not cast to JSONObject.", e);
}
}
/**
*
* String jsonStr = "[{\"id\":1001,\"name\":\"Jobs\"}]";
* List<Model> models = JSON.parseObject(jsonStr, new TypeReference<List<Model>>() {});
*
* @param text json string
* @param type type refernce
* @param features parser features
* @return an object of type T from the string
*/
@SuppressWarnings("unchecked")
public static T parseObject(String text, TypeReference type, Feature... features) {
return (T) parseObject(text, type.type, ParserConfig.global, DEFAULT_PARSER_FEATURE, features);
}
/**
*
* This method deserializes the specified Json into an object of the specified class. It is not
* suitable to use if the specified class is a generic type since it will not have the generic
* type information because of the Type Erasure feature of Java. Therefore, this method should not
* be used if the desired type is a generic type. Note that this method works fine if the any of
* the fields of the specified object are generics, just the object itself should not be a
* generic type. For the cases when the object is of generic type, invoke
* {@link #parseObject(String, Type, Feature[])}. If you have the Json in a {@link InputStream} instead of
* a String, use {@link #parseObject(InputStream, Type, Feature[])} instead.
*
* @param json the string from which the object is to be deserialized
* @param clazz the class of T
* @param features parser features
* @return an object of type T from the string
* classOfT
*/
@SuppressWarnings("unchecked")
public static T parseObject(String json, Class clazz, Feature... features) {
return (T) parseObject(json, (Type) clazz, ParserConfig.global, null, DEFAULT_PARSER_FEATURE, features);
}
@SuppressWarnings("unchecked")
public static T parseObject(String text, Class clazz, ParseProcess processor, Feature... features) {
return (T) parseObject(text, (Type) clazz, ParserConfig.global, processor, DEFAULT_PARSER_FEATURE,
features);
}
/**
* This method deserializes the specified Json into an object of the specified type. This method
* is useful if the specified object is a generic type. For non-generic objects, use
* {@link #parseObject(String, Class, Feature[])} instead. If you have the Json in a {@link InputStream} instead of
* a String, use {@link #parseObject(InputStream, Type, Feature[])} instead.
*
* @param the type of the desired object
* @param json the string from which the object is to be deserialized
* @param type The specific genericized type of src. You can obtain this type by using the
* {@link com.alibaba.fastjson.TypeReference} class. For example, to get the type for
* {@code Collection}, you should use:
*
* Type type = new TypeReference<Collection<Foo>>(){}.getType();
*
* @return an object of type T from the string
*/
@SuppressWarnings("unchecked")
public static T parseObject(String json, Type type, Feature... features) {
return (T) parseObject(json, type, ParserConfig.global, DEFAULT_PARSER_FEATURE, features);
}
@SuppressWarnings("unchecked")
public static T parseObject(String input, Type clazz, ParseProcess processor, Feature... features) {
return (T) parseObject(input, clazz, ParserConfig.global, processor, DEFAULT_PARSER_FEATURE, features);
}
@SuppressWarnings("unchecked")
public static T parseObject(String input, Type clazz, int featureValues, Feature... features) {
if (input == null) {
return null;
}
for (Feature feature : features) {
featureValues = Feature.config(featureValues, feature, true);
}
DefaultJSONParser parser = new DefaultJSONParser(input, ParserConfig.getGlobalInstance(), featureValues);
T value = (T) parser.parseObject(clazz);
parser.handleResovleTask(value);
parser.close();
return (T) value;
}
/**
* @since 1.2.11
*/
public static T parseObject(String input, Type clazz, ParserConfig config, Feature... features) {
return parseObject(input, clazz, config, null, DEFAULT_PARSER_FEATURE, features);
}
public static T parseObject(String input, Type clazz, ParserConfig config, int featureValues,
Feature... features) {
return parseObject(input, clazz, config, null, featureValues, features);
}
@SuppressWarnings("unchecked")
public static T parseObject(String input, Type clazz, ParserConfig config, ParseProcess processor,
int featureValues, Feature... features) {
if (input == null || input.length() == 0) {
return null;
}
if (features != null) {
for (Feature feature : features) {
featureValues |= feature.mask;
}
}
DefaultJSONParser parser = new DefaultJSONParser(input, config, featureValues);
if (processor != null) {
if (processor instanceof ExtraTypeProvider) {
parser.getExtraTypeProviders().add((ExtraTypeProvider) processor);
}
if (processor instanceof ExtraProcessor) {
parser.getExtraProcessors().add((ExtraProcessor) processor);
}
if (processor instanceof FieldTypeResolver) {
parser.setFieldTypeResolver((FieldTypeResolver) processor);
}
}
T value = (T) parser.parseObject(clazz, null);
parser.handleResovleTask(value);
parser.close();
return (T) value;
}
@SuppressWarnings("unchecked")
public static T parseObject(byte[] bytes, Type clazz, Feature... features) {
return (T) parseObject(bytes, 0, bytes.length, IOUtils.UTF8, clazz, features);
}
/**
* @since 1.2.11
*/
@SuppressWarnings("unchecked")
public static T parseObject(byte[] bytes, int offset, int len, Charset charset, Type clazz, Feature... features) {
return (T) parseObject(bytes, offset, len, charset, clazz, ParserConfig.global, null, DEFAULT_PARSER_FEATURE, features);
}
/**
* @since 1.2.55
*/
@SuppressWarnings("unchecked")
public static T parseObject(byte[] bytes,
Charset charset,
Type clazz,
ParserConfig config,
ParseProcess processor,
int featureValues,
Feature... features) {
return (T) parseObject(bytes, 0, bytes.length, charset, clazz, config, processor, featureValues, features);
}
/**
* @since 1.2.55
*/
@SuppressWarnings("unchecked")
public static T parseObject(byte[] bytes, int offset, int len,
Charset charset,
Type clazz,
ParserConfig config,
ParseProcess processor,
int featureValues,
Feature... features) {
if (charset == null) {
charset = IOUtils.UTF8;
}
String strVal = null;
if (charset == IOUtils.UTF8) {
char[] chars = allocateChars(bytes.length);
int chars_len = IOUtils.decodeUTF8(bytes, offset, len, chars);
if (chars_len < 0) {
InputStreamReader gzipReader = null;
try {
gzipReader = new InputStreamReader(
new GZIPInputStream(
new ByteArrayInputStream(bytes, offset, len)), "UTF-8");
strVal = IOUtils.readAll(gzipReader);
} catch (Exception ex) {
return null;
} finally {
IOUtils.close(gzipReader);
}
}
if (strVal == null && chars_len < 0) {
return null;
}
if (strVal == null) {
strVal = new String(chars, 0, chars_len);
}
} else {
if (len < 0) {
return null;
}
strVal = new String(bytes, offset, len, charset);
}
return (T) parseObject(strVal, clazz, config, processor, featureValues, features);
}
@SuppressWarnings("unchecked")
public static T parseObject(byte[] input, //
int off, //
int len, //
CharsetDecoder charsetDecoder, //
Type clazz, //
Feature... features) {
charsetDecoder.reset();
int scaleLength = (int) (len * (double) charsetDecoder.maxCharsPerByte());
char[] chars = allocateChars(scaleLength);
ByteBuffer byteBuf = ByteBuffer.wrap(input, off, len);
CharBuffer charByte = CharBuffer.wrap(chars);
IOUtils.decode(charsetDecoder, byteBuf, charByte);
int position = charByte.position();
return (T) parseObject(chars, position, clazz, features);
}
@SuppressWarnings("unchecked")
public static T parseObject(char[] input, int length, Type clazz, Feature... features) {
if (input == null || input.length == 0) {
return null;
}
int featureValues = DEFAULT_PARSER_FEATURE;
for (Feature feature : features) {
featureValues = Feature.config(featureValues, feature, true);
}
DefaultJSONParser parser = new DefaultJSONParser(input, length, ParserConfig.getGlobalInstance(), featureValues);
T value = (T) parser.parseObject(clazz);
parser.handleResovleTask(value);
parser.close();
return (T) value;
}
/**
* @since 1.2.11
*/
@SuppressWarnings("unchecked")
public static T parseObject(InputStream is, //
Type type, //
Feature... features) throws IOException {
return (T) parseObject(is, IOUtils.UTF8, type, features);
}
/**
* @since 1.2.11
*/
@SuppressWarnings("unchecked")
public static T parseObject(InputStream is, //
Charset charset, //
Type type, //
Feature... features) throws IOException {
return (T) parseObject(is, charset, type, ParserConfig.global, features);
}
/**
* @since 1.2.55
*/
@SuppressWarnings("unchecked")
public static T parseObject(InputStream is, //
Charset charset, //
Type type, //
ParserConfig config, //
Feature... features) throws IOException {
return (T) parseObject(is, charset, type, config, null, DEFAULT_PARSER_FEATURE, features);
}
/**
* @since 1.2.55
*/
@SuppressWarnings("unchecked")
public static T parseObject(InputStream is, //
Charset charset, //
Type type, //
ParserConfig config, //
ParseProcess processor, //
int featureValues, //
Feature... features) throws IOException {
if (charset == null) {
charset = IOUtils.UTF8;
}
byte[] bytes = allocateBytes(1024 * 64);
int offset = 0;
for (;;) {
int readCount = is.read(bytes, offset, bytes.length - offset);
if (readCount == -1) {
break;
}
offset += readCount;
if (offset == bytes.length) {
byte[] newBytes = new byte[bytes.length * 3 / 2];
System.arraycopy(bytes, 0, newBytes, 0, bytes.length);
bytes = newBytes;
}
}
return (T) parseObject(bytes, 0, offset, charset, type, config, processor, featureValues, features);
}
public static T parseObject(String text, Class clazz) {
return parseObject(text, clazz, new Feature[0]);
}
public static JSONArray parseArray(String text) {
return parseArray(text, ParserConfig.global);
}
public static JSONArray parseArray(String text, ParserConfig parserConfig) {
if (text == null) {
return null;
}
DefaultJSONParser parser = new DefaultJSONParser(text, parserConfig);
JSONArray array;
JSONLexer lexer = parser.lexer;
if (lexer.token() == JSONToken.NULL) {
lexer.nextToken();
array = null;
} else if (lexer.token() == JSONToken.EOF && lexer.isBlankInput()) {
array = null;
} else {
array = new JSONArray();
parser.parseArray(array);
parser.handleResovleTask(array);
}
parser.close();
return array;
}
public static List parseArray(String text, Class clazz) {
return parseArray(text, clazz, ParserConfig.global);
}
public static List parseArray(String text, Class clazz, ParserConfig config) {
if (text == null) {
return null;
}
List list;
DefaultJSONParser parser = new DefaultJSONParser(text, config);
JSONLexer lexer = parser.lexer;
int token = lexer.token();
if (token == JSONToken.NULL) {
lexer.nextToken();
list = null;
} else if (token == JSONToken.EOF && lexer.isBlankInput()) {
list = null;
} else {
list = new ArrayList();
parser.parseArray(clazz, list);
parser.handleResovleTask(list);
}
parser.close();
return list;
}
public static List