/* * 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 final static String VERSION = "1.1.27"; 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'T'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()); } }