/*
* Copyright 1999-2101 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.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.Type;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharsetDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import com.alibaba.fastjson.parser.DefaultJSONParser;
import com.alibaba.fastjson.parser.DefaultJSONParser.ResolveTask;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.parser.JSONLexer;
import com.alibaba.fastjson.parser.JSONToken;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.parser.deserializer.FieldDeserializer;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.NameFilter;
import com.alibaba.fastjson.serializer.PropertyPreFilter;
import com.alibaba.fastjson.serializer.PropertyFilter;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializeFilter;
import com.alibaba.fastjson.serializer.SerializeWriter;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.serializer.ValueFilter;
import com.alibaba.fastjson.util.FieldInfo;
import com.alibaba.fastjson.util.IOUtils;
import com.alibaba.fastjson.util.ThreadLocalCache;
import com.alibaba.fastjson.util.TypeUtils;
/**
* @author wenshao<szujobs@hotmail.com>
*/
public abstract class JSON implements JSONStreamAware, JSONAware {
public static int DEFAULT_PARSER_FEATURE;
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;
}
public static String DEFFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
public static int DEFAULT_GENERATE_FEATURE;
static {
int features = 0;
features |= com.alibaba.fastjson.serializer.SerializerFeature.QuoteFieldNames.getMask();
features |= com.alibaba.fastjson.serializer.SerializerFeature.SkipTransientField.getMask();
features |= com.alibaba.fastjson.serializer.SerializerFeature.WriteEnumUsingToString.getMask();
features |= com.alibaba.fastjson.serializer.SerializerFeature.SortField.getMask();
features |= com.alibaba.fastjson.serializer.SerializerFeature.WriteTabAsSpecial.getMask();
// features |= com.alibaba.fastjson.serializer.SerializerFeature.WriteSlashAsSpecial.getMask();
DEFAULT_GENERATE_FEATURE = features;
}
public static final Object parse(String text) {
return parse(text, DEFAULT_PARSER_FEATURE);
}
public static final Object parse(String text, int features) {
if (text == null) {
return null;
}
DefaultJSONParser parser = new DefaultJSONParser(text, ParserConfig.getGlobalInstance(), features);
Object value = parser.parse();
handleResovleTask(parser, value);
parser.close();
return value;
}
public static final Object parse(byte[] input, Feature... features) {
return parse(input, 0, input.length, ThreadLocalCache.getUTF8Decoder(), features);
}
public static final 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 featrue : features) {
featureValues = Feature.config(featureValues, featrue, true);
}
return parse(input, off, len, charsetDecoder, featureValues);
}
public static final Object parse(byte[] input, int off, int len, CharsetDecoder charsetDecoder, int features) {
charsetDecoder.reset();
int scaleLength = (int) (len * (double) charsetDecoder.maxCharsPerByte());
char[] chars = ThreadLocalCache.getChars(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();
handleResovleTask(parser, value);
parser.close();
return value;
}
public static final Object parse(String text, Feature... features) {
int featureValues = DEFAULT_PARSER_FEATURE;
for (Feature featrue : features) {
featureValues = Feature.config(featureValues, featrue, true);
}
return parse(text, featureValues);
}
public static final JSONObject parseObject(String text, Feature... features) {
return (JSONObject) parse(text, features);
}
public static final JSONObject parseObject(String text) {
Object obj = parse(text);
if (obj instanceof JSONObject) {
return (JSONObject) obj;
}
return (JSONObject) JSON.toJSON(obj);
}
@SuppressWarnings("unchecked")
public static final <T> T parseObject(String text, TypeReference<T> type, Feature... features) {
return (T) parseObject(text, type.getType(), ParserConfig.getGlobalInstance(), DEFAULT_PARSER_FEATURE, features);
}
@SuppressWarnings("unchecked")
public static final <T> T parseObject(String text, Class<T> clazz, Feature... features) {
return (T) parseObject(text, (Type) clazz, ParserConfig.getGlobalInstance(), DEFAULT_PARSER_FEATURE, features);
}
@SuppressWarnings("unchecked")
public static final <T> T parseObject(String input, Type clazz, Feature... features) {
return (T) parseObject(input, clazz, ParserConfig.getGlobalInstance(), DEFAULT_PARSER_FEATURE, features);
}
@SuppressWarnings("unchecked")
public static final <T> T parseObject(String input, Type clazz, int featureValues, Feature... features) {
if (input == null) {
return null;
}
for (Feature featrue : features) {
featureValues = Feature.config(featureValues, featrue, true);
}
DefaultJSONParser parser = new DefaultJSONParser(input, ParserConfig.getGlobalInstance(), featureValues);
T value = (T) parser.parseObject(clazz);
handleResovleTask(parser, value);
parser.close();
return (T) value;
}
@SuppressWarnings("unchecked")
public static final <T> T parseObject(String input, Type clazz, ParserConfig config, int featureValues,
Feature... features) {
if (input == null) {
return null;
}
for (Feature featrue : features) {
featureValues = Feature.config(featureValues, featrue, true);
}
DefaultJSONParser parser = new DefaultJSONParser(input, config, featureValues);
T value = (T) parser.parseObject(clazz);
handleResovleTask(parser, value);
parser.close();
return (T) value;
}
public static <T> int handleResovleTask(DefaultJSONParser parser, T value) {
if (parser.isEnabled(Feature.DisableCircularReferenceDetect)) {
return 0;
}
int size = parser.getResolveTaskList().size();
for (int i = 0; i < size; ++i) {
ResolveTask task = parser.getResolveTaskList().get(i);
FieldDeserializer fieldDeser = task.getFieldDeserializer();
Object object = null;
if (task.getOwnerContext() != null) {
object = task.getOwnerContext().getObject();
}
String ref = task.getReferenceValue();
Object refValue;
if (ref.startsWith("$")) {
refValue = parser.getObject(ref);
} else {
refValue = task.getContext().getObject();
}
fieldDeser.setValue(object, refValue);
}
return size;
}
@SuppressWarnings("unchecked")
public static final <T> T parseObject(byte[] input, Type clazz, Feature... features) {
return (T) parseObject(input, 0, input.length, ThreadLocalCache.getUTF8Decoder(), clazz, features);
}
@SuppressWarnings("unchecked")
public static final <T> 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 = ThreadLocalCache.getChars(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 final <T> 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 featrue : features) {
featureValues = Feature.config(featureValues, featrue, true);
}
DefaultJSONParser parser = new DefaultJSONParser(input, length, ParserConfig.getGlobalInstance(), featureValues);
T value = (T) parser.parseObject(clazz);
handleResovleTask(parser, value);
parser.close();
return (T) value;
}
public static final <T> T parseObject(String text, Class<T> clazz) {
return parseObject(text, clazz, new Feature[0]);
}
public static final JSONArray parseArray(String text) {
if (text == null) {
return null;
}
DefaultJSONParser parser = new DefaultJSONParser(text, ParserConfig.getGlobalInstance());
JSONArray array;
JSONLexer lexer = parser.getLexer();
if (lexer.token() == JSONToken.NULL) {
lexer.nextToken();
array = null;
} else if (lexer.token() == JSONToken.EOF) {
array = null;
} else {
array = new JSONArray();
parser.parseArray(array);
handleResovleTask(parser, array);
}
parser.close();
return array;
}
public static final <T> List<T> parseArray(String text, Class<T> clazz) {
if (text == null) {
return null;
}
List<T> list;
DefaultJSONParser parser = new DefaultJSONParser(text, ParserConfig.getGlobalInstance());
JSONLexer lexer = parser.getLexer();
if (lexer.token() == JSONToken.NULL) {
lexer.nextToken();
list = null;
} else {
list = new ArrayList<T>();
parser.parseArray(clazz, list);
handleResovleTask(parser, list);
}
parser.close();
return list;
}
public static final List<Object> parseArray(String text, Type[] types) {
if (text == null) {
return null;
}
List<Object> list;
DefaultJSONParser parser = new DefaultJSONParser(text, ParserConfig.getGlobalInstance());
Object[] objectArray = parser.parseArray(types);
if (objectArray == null) {
list = null;
} else {
list = Arrays.asList(objectArray);
}
handleResovleTask(parser, list);
parser.close();
return list;
}
// ======================
public static final String toJSONString(Object object) {
return toJSONString(object, new SerializerFeature[0]);
}
public static final String toJSONString(Object object, SerializerFeature... features) {
SerializeWriter out = new SerializeWriter();
try {
JSONSerializer serializer = new JSONSerializer(out);
for (com.alibaba.fastjson.serializer.SerializerFeature feature : features) {
serializer.config(feature, true);
}
serializer.write(object);
return out.toString();
} finally {
out.close();
}
}
/**
* @since 1.1.14
*/
public static final String toJSONStringWithDateFormat(Object object, String dateFormat,
SerializerFeature... features) {
SerializeWriter out = new SerializeWriter();
try {
JSONSerializer serializer = new JSONSerializer(out);
for (com.alibaba.fastjson.serializer.SerializerFeature feature : features) {
serializer.config(feature, true);
}
serializer.config(SerializerFeature.WriteDateUseDateFormat, true);
if (dateFormat != null) {
serializer.setDateFormat(dateFormat);
}
serializer.write(object);
return out.toString();
} finally {
out.close();
}
}
public static final String toJSONString(Object object, SerializeFilter filter, SerializerFeature... features) {
SerializeWriter out = new SerializeWriter();
try {
JSONSerializer serializer = new JSONSerializer(out);
for (com.alibaba.fastjson.serializer.SerializerFeature feature : features) {
serializer.config(feature, true);
}
serializer.config(SerializerFeature.WriteDateUseDateFormat, true);
if (filter != null) {
if (filter instanceof PropertyPreFilter) {
serializer.getPropertyPreFilters().add((PropertyPreFilter) filter);
}
if (filter instanceof NameFilter) {
serializer.getNameFilters().add((NameFilter) filter);
}
if (filter instanceof ValueFilter) {
serializer.getValueFilters().add((ValueFilter) filter);
}
if (filter instanceof PropertyFilter) {
serializer.getPropertyFilters().add((PropertyFilter) filter);
}
}
serializer.write(object);
return out.toString();
} finally {
out.close();
}
}
public static final byte[] toJSONBytes(Object object, SerializerFeature... features) {
SerializeWriter out = new SerializeWriter();
try {
JSONSerializer serializer = new JSONSerializer(out);
for (com.alibaba.fastjson.serializer.SerializerFeature feature : features) {
serializer.config(feature, true);
}
serializer.write(object);
return out.toBytes("UTF-8");
} finally {
out.close();
}
}
public static final String toJSONString(Object object, SerializeConfig config, SerializerFeature... features) {
SerializeWriter out = new SerializeWriter();
try {
JSONSerializer serializer = new JSONSerializer(out, config);
for (com.alibaba.fastjson.serializer.SerializerFeature feature : features) {
serializer.config(feature, true);
}
serializer.write(object);
return out.toString();
} finally {
out.close();
}
}
public static final String toJSONStringZ(Object object, SerializeConfig mapping, SerializerFeature... features) {
SerializeWriter out = new SerializeWriter(features);
try {
JSONSerializer serializer = new JSONSerializer(out, mapping);
serializer.write(object);
return out.toString();
} finally {
out.close();
}
}
public static final byte[] toJSONBytes(Object object, SerializeConfig config, SerializerFeature... features) {
SerializeWriter out = new SerializeWriter();
try {
JSONSerializer serializer = new JSONSerializer(out, config);
for (com.alibaba.fastjson.serializer.SerializerFeature feature : features) {
serializer.config(feature, true);
}
serializer.write(object);
return out.toBytes("UTF-8");
} finally {
out.close();
}
}
public static final String toJSONString(Object object, boolean prettyFormat) {
if (!prettyFormat) {
return toJSONString(object);
}
return toJSONString(object, SerializerFeature.PrettyFormat);
}
// ======================================
@Override
public String toString() {
return toJSONString();
}
public String toJSONString() {
SerializeWriter out = new SerializeWriter();
try {
new JSONSerializer(out).write(this);
return out.toString();
} finally {
out.close();
}
}
public void writeJSONString(Appendable appendable) {
SerializeWriter out = new SerializeWriter();
try {
new JSONSerializer(out).write(this);
appendable.append(out.toString());
} catch (IOException e) {
throw new JSONException(e.getMessage(), e);
} finally {
out.close();
}
}
// ///////
public static final Object toJSON(Object javaObject) {
return toJSON(javaObject, ParserConfig.getGlobalInstance());
}
@SuppressWarnings("unchecked")
public static final Object toJSON(Object javaObject, ParserConfig mapping) {
if (javaObject == null) {
return null;
}
if (javaObject instanceof JSON) {
return (JSON) javaObject;
}
if (javaObject instanceof Map) {
Map<Object, Object> map = (Map<Object, Object>) javaObject;
JSONObject json = new JSONObject(map.size());
for (Map.Entry<Object, Object> entry : map.entrySet()) {
Object key = entry.getKey();
String jsonKey = TypeUtils.castToString(key);
Object jsonValue = toJSON(entry.getValue());
json.put(jsonKey, jsonValue);
}
return json;
}
if (javaObject instanceof Collection) {
Collection<Object> collection = (Collection<Object>) javaObject;
JSONArray array = new JSONArray(collection.size());
for (Object item : collection) {
Object jsonValue = toJSON(item);
array.add(jsonValue);
}
return array;
}
Class<?> clazz = javaObject.getClass();
if (clazz.isEnum()) {
return ((Enum<?>) javaObject).name();
}
if (clazz.isArray()) {
int len = Array.getLength(javaObject);
JSONArray array = new JSONArray(len);
for (int i = 0; i < len; ++i) {
Object item = Array.get(javaObject, i);
Object jsonValue = toJSON(item);
array.add(jsonValue);
}
return array;
}
if (mapping.isPrimitive(clazz)) {
return javaObject;
}
try {
List<FieldInfo> getters = TypeUtils.computeGetters(clazz, null);
JSONObject json = new JSONObject(getters.size());
for (FieldInfo field : getters) {
Object value = field.get(javaObject);
Object jsonValue = toJSON(value);
json.put(field.getName(), jsonValue);
}
return json;
} catch (Exception e) {
throw new JSONException("toJSON error", e);
}
}
public static final <T> T toJavaObject(JSON json, Class<T> clazz) {
return TypeUtils.cast(json, clazz, ParserConfig.getGlobalInstance());
}
public final static String VERSION = "1.1.28";
}