Commit e0e643ed by 郑娜伟

common 1.1.8

parent 3b40792f
......@@ -18,6 +18,7 @@ import com.sobot.network.http.db.SobotDownloadManager;
import com.sobot.pictureframe.SobotBitmapUtil;
import com.sobot.utils.SobotLogUtils;
import com.sobot.utils.SobotSDCardUtils;
import com.sobot.utils.SobotSharedPreferencesUtil;
import com.sobot.widget.image.photoview.SobotPhotoView;
import com.sobot.widget.loading.SobotLoadingLayout;
import com.sobot.widget.refresh.layout.api.RefreshLayout;
......@@ -89,6 +90,16 @@ SobotLogUtils.i("下载进度:"+progress);
map.put("groupId", "36b0f8eb2de948d99e89c8f0c3d92e68_5");
map.put("agentPhoneNum", "18600978969");
SobotSharedPreferencesUtil.getInstance(this).put("aa",map);
Map<String, String> map1=SobotSharedPreferencesUtil.getInstance(this).get("aa",Map.class);
SobotSharedPreferencesUtil.getInstance(this).clearAll();
Map<String, String> map2=SobotSharedPreferencesUtil.getInstance(this).get("aa",Map.class);
SobotSharedPreferencesUtil.getInstance(this).put("aa",map);
Map<String, String> map3=SobotSharedPreferencesUtil.getInstance(this).get("aa",Map.class);
SobotSharedPreferencesUtil.getInstance(this).remove("aa");
Map<String, String> map4=SobotSharedPreferencesUtil.getInstance(this).get("aa",Map.class);
SobotHttpUtils.doPostByJsonString(this, "https://sobot.com/comm/api/4/call/agentOnWork?access_token=c273b74c-3b37-48cf-937f-9c46940cc19d", map, null, new HttpBaseUtils.StringCallBack() {
@Override
public void onResponse(String result) {
......
......@@ -5,13 +5,6 @@ import android.support.multidex.MultiDex;
import com.sobot.common.ui.SobotMarkConfig;
import com.sobot.common.utils.SobotCommonApi;
import com.sobot.network.http.SobotOkHttpUtils;
import com.sobot.network.http.log.SobotNetLogUtils;
import com.sobot.utils.SobotLogUtils;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
/**
* @Description: java类作用描述
......
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
......
include ':sobot_pictureframe'
include ':sobot_network'
include ':sobot_utils'
include ':sobot_json'
include ':sobot_gson'
include ':sobot_common'
include ':sobot_widget'
include ':app'
......
......@@ -17,17 +17,17 @@ dependencies {
// api project(':sobot_utils')
// api project(':sobot_pictureframe')
// api project(':sobot_network')
// api project(':sobot_json')
// api project(':sobot_gson')
api 'com.sobot.library:utils:1.1.0'
api 'com.sobot.library:utils:1.1.1'
api 'com.sobot.library:picture:1.1'
api 'com.sobot.library:net:1.1.1'
api 'com.sobot.library:json:1.1'
api 'com.sobot.library:gson:1.1.1'
// api 'com.sobot.library:utils:1.1'
// api 'com.sobot.library:utils:1.1.1'
// api 'com.sobot.library:picture_x:1.1'
// api 'com.sobot.library:net:1.1.0'
// api 'com.sobot.library:json:1.1'
// api 'com.sobot.library:net:1.1.1'
// api 'com.sobot.library:gson:1.1.1'
}
......
......@@ -13,7 +13,7 @@ ext {
PUBLISH_GROUP_ID = "com.sobot.library" //项目包名
PUBLISH_ARTIFACT_ID = 'sobotcommon' //项目名
// PUBLISH_ARTIFACT_ID = 'sobotcommon_x' //项目名
PUBLISH_VERSION = '1.1.5' //版本号
PUBLISH_VERSION = '1.1.8' //版本号
}
......
......@@ -16,8 +16,6 @@
package com.sobot.gson;
import com.sobot.gson.GsonBuilder;
/**
* A strategy (or policy) definition that is used to decide whether or not a field or top-level
* class should be serialized or deserialized as part of the JSON output/input. For serialization,
......
......@@ -17,6 +17,7 @@
package com.sobot.gson;
import com.sobot.gson.internal.$Gson$Preconditions;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
......
......@@ -16,8 +16,6 @@
package com.sobot.gson;
import com.sobot.gson.FieldNamingStrategy;
import java.lang.reflect.Field;
import java.util.Locale;
......
......@@ -16,6 +16,15 @@
package com.sobot.gson;
import com.sobot.gson.internal.$Gson$Preconditions;
import com.sobot.gson.internal.Excluder;
import com.sobot.gson.internal.bind.DefaultDateTypeAdapter;
import com.sobot.gson.internal.bind.TreeTypeAdapter;
import com.sobot.gson.internal.bind.TypeAdapters;
import com.sobot.gson.internal.sql.SqlTypesSupport;
import com.sobot.gson.reflect.TypeToken;
import com.sobot.gson.stream.JsonReader;
import java.lang.reflect.Type;
import java.text.DateFormat;
import java.util.ArrayList;
......@@ -26,25 +35,6 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import com.sobot.gson.InstanceCreator;
import com.sobot.gson.JsonDeserializer;
import com.sobot.gson.JsonObject;
import com.sobot.gson.JsonSerializer;
import com.sobot.gson.LongSerializationPolicy;
import com.sobot.gson.ReflectionAccessFilter;
import com.sobot.gson.ToNumberPolicy;
import com.sobot.gson.ToNumberStrategy;
import com.sobot.gson.TypeAdapter;
import com.sobot.gson.TypeAdapterFactory;
import com.sobot.gson.internal.$Gson$Preconditions;
import com.sobot.gson.internal.Excluder;
import com.sobot.gson.internal.bind.DefaultDateTypeAdapter;
import com.sobot.gson.internal.bind.TreeTypeAdapter;
import com.sobot.gson.internal.bind.TypeAdapters;
import com.sobot.gson.internal.sql.SqlTypesSupport;
import com.sobot.gson.reflect.TypeToken;
import com.sobot.gson.stream.JsonReader;
import static com.sobot.gson.Gson.DEFAULT_COMPLEX_MAP_KEYS;
import static com.sobot.gson.Gson.DEFAULT_DATE_PATTERN;
import static com.sobot.gson.Gson.DEFAULT_ESCAPE_HTML;
......
......@@ -16,10 +16,6 @@
package com.sobot.gson;
import com.sobot.gson.JsonElement;
import com.sobot.gson.JsonNull;
import com.sobot.gson.JsonPrimitive;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
......
......@@ -16,10 +16,6 @@
package com.sobot.gson;
import com.sobot.gson.JsonDeserializer;
import com.sobot.gson.JsonElement;
import com.sobot.gson.JsonParseException;
import java.lang.reflect.Type;
/**
......
......@@ -16,10 +16,6 @@
package com.sobot.gson;
import com.sobot.gson.JsonElement;
import com.sobot.gson.JsonParseException;
import com.sobot.gson.TypeAdapter;
import java.lang.reflect.Type;
/**
......
......@@ -16,11 +16,9 @@
package com.sobot.gson;
import com.sobot.gson.JsonNull;
import com.sobot.gson.JsonObject;
import com.sobot.gson.JsonPrimitive;
import com.sobot.gson.internal.Streams;
import com.sobot.gson.stream.JsonWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.math.BigDecimal;
......
......@@ -15,8 +15,6 @@
*/
package com.sobot.gson;
import com.sobot.gson.JsonParseException;
/**
* This exception is raised when Gson was unable to read an input stream
* or write to one.
......
......@@ -16,7 +16,6 @@
package com.sobot.gson;
import com.sobot.gson.JsonPrimitive;
import com.sobot.gson.internal.LinkedTreeMap;
import java.util.Map;
......
......@@ -15,16 +15,15 @@
*/
package com.sobot.gson;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import com.sobot.gson.JsonSyntaxException;
import com.sobot.gson.internal.Streams;
import com.sobot.gson.stream.JsonReader;
import com.sobot.gson.stream.JsonToken;
import com.sobot.gson.stream.MalformedJsonException;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
/**
* A parser to parse Json into a parse tree of {@link JsonElement}s
*
......
......@@ -17,11 +17,11 @@
package com.sobot.gson;
import com.sobot.gson.internal.$Gson$Preconditions;
import com.sobot.gson.internal.LazilyParsedNumber;
import java.math.BigDecimal;
import java.math.BigInteger;
import com.sobot.gson.internal.LazilyParsedNumber;
/**
* A class representing a Json primitive value. A primitive value
* is either a String, a Java primitive, or a Java primitive
......
......@@ -16,8 +16,6 @@
package com.sobot.gson;
import com.sobot.gson.JsonSerializer;
import java.lang.reflect.Type;
/**
......
......@@ -16,8 +16,6 @@
package com.sobot.gson;
import com.sobot.gson.TypeAdapter;
import java.lang.reflect.Type;
/**
......
......@@ -15,6 +15,11 @@
*/
package com.sobot.gson;
import com.sobot.gson.internal.Streams;
import com.sobot.gson.stream.JsonReader;
import com.sobot.gson.stream.JsonToken;
import com.sobot.gson.stream.MalformedJsonException;
import java.io.EOFException;
import java.io.IOException;
import java.io.Reader;
......@@ -22,12 +27,6 @@ import java.io.StringReader;
import java.util.Iterator;
import java.util.NoSuchElementException;
import com.sobot.gson.JsonSyntaxException;
import com.sobot.gson.internal.Streams;
import com.sobot.gson.stream.JsonReader;
import com.sobot.gson.stream.JsonToken;
import com.sobot.gson.stream.MalformedJsonException;
/**
* A streaming parser that allows reading of multiple {@link JsonElement}s from the specified reader
* asynchronously. The JSON data is parsed in lenient mode, see also
......
package com.sobot.gson;
import java.lang.reflect.AccessibleObject;
import com.sobot.gson.TypeAdapter;
import com.sobot.gson.internal.ReflectionAccessFilterHelper;
import java.lang.reflect.AccessibleObject;
/**
* Filter for determining whether reflection based serialization and
* deserialization is allowed for a class.
......
......@@ -16,14 +16,13 @@
package com.sobot.gson;
import java.io.IOException;
import java.math.BigDecimal;
import com.sobot.gson.ToNumberStrategy;
import com.sobot.gson.internal.LazilyParsedNumber;
import com.sobot.gson.stream.JsonReader;
import com.sobot.gson.stream.MalformedJsonException;
import java.io.IOException;
import java.math.BigDecimal;
/**
* An enumeration that defines two standard number reading strategies and a couple of
* strategies to overcome some historical Gson limitations while deserializing numbers as
......
......@@ -16,10 +16,10 @@
package com.sobot.gson;
import java.io.IOException;
import com.sobot.gson.stream.JsonReader;
import java.io.IOException;
/**
* A strategy that is used to control how numbers should be deserialized for {@link Object} and {@link Number}
* when a concrete type of the deserialized number is unknown in advance. By default, Gson uses the following
......
......@@ -16,11 +16,12 @@
package com.sobot.gson;
import com.sobot.gson.internal.bind.JsonTreeWriter;
import com.sobot.gson.internal.bind.JsonTreeReader;
import com.sobot.gson.internal.bind.JsonTreeWriter;
import com.sobot.gson.stream.JsonReader;
import com.sobot.gson.stream.JsonToken;
import com.sobot.gson.stream.JsonWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
......
......@@ -20,6 +20,7 @@ import com.sobot.gson.JsonDeserializer;
import com.sobot.gson.JsonSerializer;
import com.sobot.gson.TypeAdapter;
import com.sobot.gson.TypeAdapterFactory;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
......
......@@ -20,9 +20,9 @@ import com.sobot.gson.InstanceCreator;
import com.sobot.gson.JsonIOException;
import com.sobot.gson.ReflectionAccessFilter;
import com.sobot.gson.ReflectionAccessFilter.FilterResult;
import com.sobot.gson.internal.ReflectionAccessFilterHelper;
import com.sobot.gson.internal.reflect.ReflectionHelper;
import com.sobot.gson.reflect.TypeToken;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
......
......@@ -27,6 +27,7 @@ import com.sobot.gson.annotations.Until;
import com.sobot.gson.reflect.TypeToken;
import com.sobot.gson.stream.JsonReader;
import com.sobot.gson.stream.JsonWriter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
......
......@@ -17,6 +17,7 @@
package com.sobot.gson.internal;
import com.sobot.gson.stream.JsonReader;
import java.io.IOException;
/**
......
package com.sobot.gson.internal;
import com.sobot.gson.ReflectionAccessFilter;
import com.sobot.gson.ReflectionAccessFilter.FilterResult;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;
import java.util.List;
import com.sobot.gson.ReflectionAccessFilter;
import com.sobot.gson.ReflectionAccessFilter.FilterResult;
/**
* Internal helper class for {@link ReflectionAccessFilter}.
*/
......
......@@ -25,6 +25,7 @@ import com.sobot.gson.internal.bind.TypeAdapters;
import com.sobot.gson.stream.JsonReader;
import com.sobot.gson.stream.JsonWriter;
import com.sobot.gson.stream.MalformedJsonException;
import java.io.EOFException;
import java.io.IOException;
import java.io.Writer;
......
......@@ -16,8 +16,6 @@
package com.sobot.gson.internal;
import com.sobot.gson.internal.ConstructorConstructor;
import java.io.ObjectInputStream;
import java.io.ObjectStreamClass;
import java.lang.reflect.Field;
......
......@@ -16,23 +16,22 @@
package com.sobot.gson.internal.bind;
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import com.sobot.gson.Gson;
import com.sobot.gson.TypeAdapter;
import com.sobot.gson.TypeAdapterFactory;
import com.sobot.gson.internal.$Gson$Types;
import com.sobot.gson.internal.bind.TypeAdapterRuntimeTypeWrapper;
import com.sobot.gson.reflect.TypeToken;
import com.sobot.gson.stream.JsonReader;
import com.sobot.gson.stream.JsonToken;
import com.sobot.gson.stream.JsonWriter;
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
/**
* Adapt an array of objects.
*/
......
......@@ -22,11 +22,11 @@ import com.sobot.gson.TypeAdapterFactory;
import com.sobot.gson.internal.$Gson$Types;
import com.sobot.gson.internal.ConstructorConstructor;
import com.sobot.gson.internal.ObjectConstructor;
import com.sobot.gson.internal.bind.TypeAdapterRuntimeTypeWrapper;
import com.sobot.gson.reflect.TypeToken;
import com.sobot.gson.stream.JsonReader;
import com.sobot.gson.stream.JsonToken;
import com.sobot.gson.stream.JsonWriter;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.Collection;
......
......@@ -16,16 +16,6 @@
package com.sobot.gson.internal.bind;
import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import com.sobot.gson.JsonSyntaxException;
import com.sobot.gson.TypeAdapter;
import com.sobot.gson.TypeAdapterFactory;
......@@ -37,6 +27,16 @@ import com.sobot.gson.stream.JsonReader;
import com.sobot.gson.stream.JsonToken;
import com.sobot.gson.stream.JsonWriter;
import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
/**
* This type adapter supports subclasses of date by defining a
* {@link DateType} and then using its {@code createAdapterFactory}
......
......@@ -23,11 +23,12 @@ import com.sobot.gson.JsonObject;
import com.sobot.gson.JsonPrimitive;
import com.sobot.gson.stream.JsonReader;
import com.sobot.gson.stream.JsonToken;
import java.io.IOException;
import java.io.Reader;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
import java.util.Arrays;
/**
* This reader walks the elements of a JsonElement as if it was coming from a
......
......@@ -22,6 +22,7 @@ import com.sobot.gson.JsonNull;
import com.sobot.gson.JsonObject;
import com.sobot.gson.JsonPrimitive;
import com.sobot.gson.stream.JsonWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
......
......@@ -27,11 +27,11 @@ import com.sobot.gson.internal.ConstructorConstructor;
import com.sobot.gson.internal.JsonReaderInternalAccess;
import com.sobot.gson.internal.ObjectConstructor;
import com.sobot.gson.internal.Streams;
import com.sobot.gson.internal.bind.TypeAdapterRuntimeTypeWrapper;
import com.sobot.gson.reflect.TypeToken;
import com.sobot.gson.stream.JsonReader;
import com.sobot.gson.stream.JsonToken;
import com.sobot.gson.stream.JsonWriter;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
......
......@@ -18,8 +18,8 @@ package com.sobot.gson.internal.bind;
import com.sobot.gson.Gson;
import com.sobot.gson.JsonSyntaxException;
import com.sobot.gson.ToNumberStrategy;
import com.sobot.gson.ToNumberPolicy;
import com.sobot.gson.ToNumberStrategy;
import com.sobot.gson.TypeAdapter;
import com.sobot.gson.TypeAdapterFactory;
import com.sobot.gson.reflect.TypeToken;
......
......@@ -17,8 +17,8 @@
package com.sobot.gson.internal.bind;
import com.sobot.gson.Gson;
import com.sobot.gson.ToNumberStrategy;
import com.sobot.gson.ToNumberPolicy;
import com.sobot.gson.ToNumberStrategy;
import com.sobot.gson.TypeAdapter;
import com.sobot.gson.TypeAdapterFactory;
import com.sobot.gson.internal.LinkedTreeMap;
......
......@@ -32,13 +32,12 @@ import com.sobot.gson.internal.Excluder;
import com.sobot.gson.internal.ObjectConstructor;
import com.sobot.gson.internal.Primitives;
import com.sobot.gson.internal.ReflectionAccessFilterHelper;
import com.sobot.gson.internal.bind.JsonAdapterAnnotationTypeAdapterFactory;
import com.sobot.gson.internal.bind.TypeAdapterRuntimeTypeWrapper;
import com.sobot.gson.internal.reflect.ReflectionHelper;
import com.sobot.gson.reflect.TypeToken;
import com.sobot.gson.stream.JsonReader;
import com.sobot.gson.stream.JsonToken;
import com.sobot.gson.stream.JsonWriter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
......
......@@ -30,6 +30,7 @@ import com.sobot.gson.internal.Streams;
import com.sobot.gson.reflect.TypeToken;
import com.sobot.gson.stream.JsonReader;
import com.sobot.gson.stream.JsonWriter;
import java.io.IOException;
import java.lang.reflect.Type;
......
......@@ -15,16 +15,16 @@
*/
package com.sobot.gson.internal.bind;
import java.io.IOException;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import com.sobot.gson.Gson;
import com.sobot.gson.TypeAdapter;
import com.sobot.gson.reflect.TypeToken;
import com.sobot.gson.stream.JsonReader;
import com.sobot.gson.stream.JsonWriter;
import java.io.IOException;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
final class TypeAdapterRuntimeTypeWrapper<T> extends TypeAdapter<T> {
private final Gson context;
private final TypeAdapter<T> delegate;
......
......@@ -16,6 +16,23 @@
package com.sobot.gson.internal.bind;
import com.sobot.gson.Gson;
import com.sobot.gson.JsonArray;
import com.sobot.gson.JsonElement;
import com.sobot.gson.JsonIOException;
import com.sobot.gson.JsonNull;
import com.sobot.gson.JsonObject;
import com.sobot.gson.JsonPrimitive;
import com.sobot.gson.JsonSyntaxException;
import com.sobot.gson.TypeAdapter;
import com.sobot.gson.TypeAdapterFactory;
import com.sobot.gson.annotations.SerializedName;
import com.sobot.gson.internal.LazilyParsedNumber;
import com.sobot.gson.reflect.TypeToken;
import com.sobot.gson.stream.JsonReader;
import com.sobot.gson.stream.JsonToken;
import com.sobot.gson.stream.JsonWriter;
import java.io.IOException;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
......@@ -42,24 +59,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicIntegerArray;
import com.sobot.gson.Gson;
import com.sobot.gson.JsonArray;
import com.sobot.gson.JsonElement;
import com.sobot.gson.JsonIOException;
import com.sobot.gson.JsonNull;
import com.sobot.gson.JsonObject;
import com.sobot.gson.JsonPrimitive;
import com.sobot.gson.JsonSyntaxException;
import com.sobot.gson.TypeAdapter;
import com.sobot.gson.TypeAdapterFactory;
import com.sobot.gson.annotations.SerializedName;
import com.sobot.gson.internal.LazilyParsedNumber;
import com.sobot.gson.internal.bind.JsonTreeReader;
import com.sobot.gson.reflect.TypeToken;
import com.sobot.gson.stream.JsonReader;
import com.sobot.gson.stream.JsonToken;
import com.sobot.gson.stream.JsonWriter;
/**
* Type adapters for basic types.
*/
......
......@@ -2,7 +2,11 @@ package com.sobot.gson.internal.bind.util;
import java.text.ParseException;
import java.text.ParsePosition;
import java.util.*;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
/**
* Utilities methods for manipulating dates in iso8601 format. This is much much faster and GC friendly than using SimpleDateFormat so
......
package com.sobot.gson.internal.reflect;
import com.sobot.gson.JsonIOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
......
......@@ -24,6 +24,7 @@ import com.sobot.gson.reflect.TypeToken;
import com.sobot.gson.stream.JsonReader;
import com.sobot.gson.stream.JsonToken;
import com.sobot.gson.stream.JsonWriter;
import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
......
......@@ -24,6 +24,7 @@ import com.sobot.gson.reflect.TypeToken;
import com.sobot.gson.stream.JsonReader;
import com.sobot.gson.stream.JsonToken;
import com.sobot.gson.stream.JsonWriter;
import java.io.IOException;
import java.sql.Time;
import java.text.DateFormat;
......
package com.sobot.gson.internal.sql;
import java.sql.Timestamp;
import java.util.Date;
import com.sobot.gson.TypeAdapterFactory;
import com.sobot.gson.internal.bind.DefaultDateTypeAdapter.DateType;
import java.sql.Timestamp;
import java.util.Date;
/**
* Encapsulates access to {@code java.sql} types, to allow Gson to
* work without the {@code java.sql} module being present.
......
......@@ -16,8 +16,9 @@
package com.sobot.gson.reflect;
import com.sobot.gson.internal.$Gson$Types;
import com.sobot.gson.internal.$Gson$Preconditions;
import com.sobot.gson.internal.$Gson$Types;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
......
......@@ -18,7 +18,6 @@ package com.sobot.gson.stream;
import com.sobot.gson.internal.JsonReaderInternalAccess;
import com.sobot.gson.internal.bind.JsonTreeReader;
import com.sobot.gson.stream.MalformedJsonException;
import java.io.Closeable;
import java.io.EOFException;
......
......@@ -16,9 +16,6 @@
package com.sobot.gson.stream;
import com.sobot.gson.stream.JsonReader;
import com.sobot.gson.stream.JsonWriter;
/**
* A structure, name or value type in a JSON-encoded string.
*
......
package com.sobot.gson;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("com.sobot.gson.test", appContext.getPackageName());
}
}
\ No newline at end of file
/*
* 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.sobot.fastjson;
import com.sobot.fastjson.parser.ParserConfig;
import com.sobot.fastjson.util.TypeUtils;
import java.io.Serializable;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.RandomAccess;
import static com.sobot.fastjson.util.TypeUtils.castToBigDecimal;
import static com.sobot.fastjson.util.TypeUtils.castToBigInteger;
import static com.sobot.fastjson.util.TypeUtils.castToBoolean;
import static com.sobot.fastjson.util.TypeUtils.castToByte;
import static com.sobot.fastjson.util.TypeUtils.castToDate;
import static com.sobot.fastjson.util.TypeUtils.castToDouble;
import static com.sobot.fastjson.util.TypeUtils.castToFloat;
import static com.sobot.fastjson.util.TypeUtils.castToInt;
import static com.sobot.fastjson.util.TypeUtils.castToLong;
import static com.sobot.fastjson.util.TypeUtils.castToShort;
import static com.sobot.fastjson.util.TypeUtils.castToString;
/**
* @author wenshao[szujobs@hotmail.com]
*/
@SuppressWarnings("serial")
public class JSONArray extends JSON implements List<Object>, Cloneable, RandomAccess, Serializable {
private final List<Object> list;
protected transient Object relatedArray;
protected transient Type componentType;
public JSONArray(){
this.list = new ArrayList<Object>(10);
}
public JSONArray(List<Object> list){
this.list = list;
}
public JSONArray(int initialCapacity){
this.list = new ArrayList<Object>(initialCapacity);
}
/**
* @since 1.1.16
* @return
*/
public Object getRelatedArray() {
return relatedArray;
}
public void setRelatedArray(Object relatedArray) {
this.relatedArray = relatedArray;
}
public Type getComponentType() {
return componentType;
}
public void setComponentType(Type componentType) {
this.componentType = componentType;
}
public int size() {
return list.size();
}
public boolean isEmpty() {
return list.isEmpty();
}
public boolean contains(Object o) {
return list.contains(o);
}
public Iterator<Object> iterator() {
return list.iterator();
}
public Object[] toArray() {
return list.toArray();
}
public <T> T[] toArray(T[] a) {
return list.toArray(a);
}
public boolean add(Object e) {
return list.add(e);
}
public boolean remove(Object o) {
return list.remove(o);
}
public boolean containsAll(Collection<?> c) {
return list.containsAll(c);
}
public boolean addAll(Collection<? extends Object> c) {
return list.addAll(c);
}
public boolean addAll(int index, Collection<? extends Object> c) {
return list.addAll(index, c);
}
public boolean removeAll(Collection<?> c) {
return list.removeAll(c);
}
public boolean retainAll(Collection<?> c) {
return list.retainAll(c);
}
public void clear() {
list.clear();
}
public Object set(int index, Object element) {
return list.set(index, element);
}
public void add(int index, Object element) {
list.add(index, element);
}
public Object remove(int index) {
return list.remove(index);
}
public int indexOf(Object o) {
return list.indexOf(o);
}
public int lastIndexOf(Object o) {
return list.lastIndexOf(o);
}
public ListIterator<Object> listIterator() {
return list.listIterator();
}
public ListIterator<Object> listIterator(int index) {
return list.listIterator(index);
}
public List<Object> subList(int fromIndex, int toIndex) {
return list.subList(fromIndex, toIndex);
}
public Object get(int index) {
return list.get(index);
}
public JSONObject getJSONObject(int index) {
Object value = list.get(index);
if (value instanceof JSONObject) {
return (JSONObject) value;
}
return (JSONObject) toJSON(value);
}
public JSONArray getJSONArray(int index) {
Object value = list.get(index);
if (value instanceof JSONArray) {
return (JSONArray) value;
}
return (JSONArray) toJSON(value);
}
public <T> T getObject(int index, Class<T> clazz) {
Object obj = list.get(index);
return TypeUtils.castToJavaBean(obj, clazz);
}
public Boolean getBoolean(int index) {
Object value = get(index);
if (value == null) {
return null;
}
return castToBoolean(value);
}
public boolean getBooleanValue(int index) {
Object value = get(index);
if (value == null) {
return false;
}
return castToBoolean(value).booleanValue();
}
public Byte getByte(int index) {
Object value = get(index);
return castToByte(value);
}
public byte getByteValue(int index) {
Object value = get(index);
if (value == null) {
return 0;
}
return castToByte(value).byteValue();
}
public Short getShort(int index) {
Object value = get(index);
return castToShort(value);
}
public short getShortValue(int index) {
Object value = get(index);
if (value == null) {
return 0;
}
return castToShort(value).shortValue();
}
public Integer getInteger(int index) {
Object value = get(index);
return castToInt(value);
}
public int getIntValue(int index) {
Object value = get(index);
if (value == null) {
return 0;
}
return castToInt(value).intValue();
}
public Long getLong(int index) {
Object value = get(index);
return castToLong(value);
}
public long getLongValue(int index) {
Object value = get(index);
if (value == null) {
return 0L;
}
return castToLong(value).longValue();
}
public Float getFloat(int index) {
Object value = get(index);
return castToFloat(value);
}
public float getFloatValue(int index) {
Object value = get(index);
if (value == null) {
return 0F;
}
return castToFloat(value).floatValue();
}
public Double getDouble(int index) {
Object value = get(index);
return castToDouble(value);
}
public double getDoubleValue(int index) {
Object value = get(index);
if (value == null) {
return 0D;
}
return castToDouble(value);
}
public BigDecimal getBigDecimal(int index) {
Object value = get(index);
return castToBigDecimal(value);
}
public BigInteger getBigInteger(int index) {
Object value = get(index);
return castToBigInteger(value);
}
public String getString(int index) {
Object value = get(index);
return castToString(value);
}
public java.util.Date getDate(int index) {
Object value = get(index);
return castToDate(value);
}
@Override
public Object clone() {
return new JSONArray(new ArrayList<Object>(list));
}
public boolean equals(Object obj) {
return this.list.equals(obj);
}
public int hashCode() {
return this.list.hashCode();
}
/**
* @since 1.1.71.android & 1.2.23
*/
public <T> List<T> toJavaList(Class<T> clazz) {
List<T> list = new ArrayList<T>(this.size());
ParserConfig config = ParserConfig.getGlobalInstance();
for (Object item : this) {
T classItem = TypeUtils.cast(item, clazz, config);
list.add(classItem);
}
return list;
}
}
/*
* 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.sobot.fastjson;
/**
* Beans that support customized output of JSON text shall implement this interface.
*
* @author wenshao[szujobs@hotmail.com]
*/
public interface JSONAware {
/**
* @return JSON text
*/
String toJSONString();
}
package com.sobot.fastjson;
import com.sobot.fastjson.parser.DefaultJSONParser;
import com.sobot.fastjson.parser.Feature;
import com.sobot.fastjson.parser.JSONLexer;
import com.sobot.fastjson.parser.JSONToken;
import com.sobot.fastjson.util.TypeUtils;
import java.io.Closeable;
import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.Type;
import java.util.Map;
import static com.sobot.fastjson.JSONStreamContext.ArrayValue;
import static com.sobot.fastjson.JSONStreamContext.PropertyKey;
import static com.sobot.fastjson.JSONStreamContext.PropertyValue;
import static com.sobot.fastjson.JSONStreamContext.StartArray;
import static com.sobot.fastjson.JSONStreamContext.StartObject;
public class JSONReader implements Closeable {
private final DefaultJSONParser parser;
private JSONStreamContext context;
private Reader reader;
public JSONReader(Reader reader){
this(new JSONLexer(readAll(reader)));
this.reader = reader;
}
static String readAll(Reader reader) {
StringBuilder buf = new StringBuilder();
try {
char[] chars = new char[2048];
for (;;) {
int len = reader.read(chars, 0, chars.length);
if (len < 0) {
break;
}
buf.append(chars, 0, len);
}
} catch(Exception ex) {
throw new JSONException("read string from reader error", ex);
}
return buf.toString();
}
public JSONReader(JSONLexer lexer){
this(new DefaultJSONParser(lexer));
}
public JSONReader(DefaultJSONParser parser){
this.parser = parser;
}
public void config(Feature feature, boolean state) {
this.parser.config(feature, state);
}
public void startObject() {
if (context == null) {
context = new JSONStreamContext(null, JSONStreamContext.StartObject);
} else {
startStructure();
context = new JSONStreamContext(context, JSONStreamContext.StartObject);
}
this.parser.accept(JSONToken.LBRACE);
}
public void endObject() {
this.parser.accept(JSONToken.RBRACE);
endStructure();
}
public void startArray() {
if (context == null) {
context = new JSONStreamContext(null, StartArray);
} else {
startStructure();
context = new JSONStreamContext(context, StartArray);
}
this.parser.accept(JSONToken.LBRACKET);
}
public void endArray() {
this.parser.accept(JSONToken.RBRACKET);
endStructure();
}
private void startStructure() {
final int state = context.state;
switch (state) {
case PropertyKey:
parser.accept(JSONToken.COLON);
break;
case PropertyValue:
case ArrayValue:
parser.accept(JSONToken.COMMA);
break;
case StartArray:
case StartObject:
break;
default:
throw new JSONException("illegal state : " + context.state);
}
}
private void endStructure() {
context = context.parent;
if (context == null) {
return;
}
final int state = context.state;
int newState = -1;
switch (state) {
case PropertyKey:
newState = PropertyValue;
break;
case StartArray:
newState = ArrayValue;
break;
case PropertyValue:
case StartObject:
newState = PropertyKey;
break;
default:
break;
}
if (newState != -1) {
context.state = newState;
}
}
public boolean hasNext() {
if (context == null) {
throw new JSONException("context is null");
}
final int token = parser.lexer.token();
final int state = context.state;
switch (state) {
case StartArray:
case ArrayValue:
return token != JSONToken.RBRACKET;
case StartObject:
case PropertyValue:
return token != JSONToken.RBRACE;
default:
throw new JSONException("illegal state : " + state);
}
}
public int peek() {
return parser.lexer.token();
}
public void close() {
parser.lexer.close();
if (reader != null) {
try {
reader.close();
} catch (IOException ex) {
throw new JSONException("closed reader error", ex);
}
}
}
public Integer readInteger() {
Object object;
if (context == null) {
object = parser.parse();
} else {
readBefore();
object = parser.parse();
readAfter();
}
return TypeUtils.castToInt(object);
}
public Long readLong() {
Object object;
if (context == null) {
object = parser.parse();
} else {
readBefore();
object = parser.parse();
readAfter();
}
return TypeUtils.castToLong(object);
}
public String readString() {
Object object;
if (context == null) {
object = parser.parse();
} else {
readBefore();
object = parser.parse();
readAfter();
}
return TypeUtils.castToString(object);
}
public <T> T readObject(TypeReference<T> typeRef) {
return readObject(typeRef.type);
}
public <T> T readObject(Type type) {
if (context == null) {
return parser.parseObject(type);
}
readBefore();
T object = parser.parseObject(type);
readAfter();
return object;
}
public <T> T readObject(Class<T> type) {
if (context == null) {
return parser.parseObject(type);
}
readBefore();
T object = parser.parseObject(type);
readAfter();
return object;
}
public void readObject(Object object) {
if (context == null) {
parser.parseObject(object);
return;
}
readBefore();
parser.parseObject(object);
readAfter();
}
public Object readObject() {
if (context == null) {
return parser.parse();
}
readBefore();
Object object = parser.parse();
readAfter();
return object;
}
@SuppressWarnings("rawtypes")
public Object readObject(Map object) {
if (context == null) {
return parser.parseObject(object);
}
readBefore();
Object value = parser.parseObject(object);
readAfter();
return value;
}
private void readBefore() {
int state = context.state;
// before
switch (state) {
case PropertyKey:
parser.accept(JSONToken.COLON);
break;
case PropertyValue:
case ArrayValue:
parser.accept(JSONToken.COMMA);
break;
case StartObject:
break;
case StartArray:
break;
default:
throw new JSONException("illegal state : " + state);
}
}
private void readAfter() {
int state = context.state;
int newStat = -1;
switch (state) {
case StartObject:
newStat = PropertyKey;
break;
case PropertyKey:
newStat = PropertyValue;
break;
case PropertyValue:
newStat = PropertyKey;
break;
case ArrayValue:
break;
case StartArray:
newStat = ArrayValue;
break;
default:
throw new JSONException("illegal state : " + state);
}
if (newStat != -1) {
context.state = newStat;
}
}
}
package com.sobot.fastjson;
class JSONStreamContext {
final static int StartObject = 1001;
final static int PropertyKey = 1002;
final static int PropertyValue = 1003;
final static int StartArray = 1004;
final static int ArrayValue = 1005;
protected final JSONStreamContext parent;
protected int state;
public JSONStreamContext(JSONStreamContext parent, int state){
this.parent = parent;
this.state = state;
}
}
package com.sobot.fastjson;
import com.sobot.fastjson.serializer.JSONSerializer;
import com.sobot.fastjson.serializer.SerializeWriter;
import com.sobot.fastjson.serializer.SerializerFeature;
import java.io.Closeable;
import java.io.Flushable;
import java.io.IOException;
import java.io.Writer;
import static com.sobot.fastjson.JSONStreamContext.ArrayValue;
import static com.sobot.fastjson.JSONStreamContext.PropertyKey;
import static com.sobot.fastjson.JSONStreamContext.PropertyValue;
import static com.sobot.fastjson.JSONStreamContext.StartArray;
import static com.sobot.fastjson.JSONStreamContext.StartObject;
public class JSONWriter implements Closeable, Flushable {
private SerializeWriter writer;
private JSONSerializer serializer;
private JSONStreamContext context;
public JSONWriter(Writer out){
writer = new SerializeWriter(out);
serializer = new JSONSerializer(writer);
}
public void config(SerializerFeature feature, boolean state) {
this.writer.config(feature, state);
}
public void startObject() {
if (context != null) {
beginStructure();
}
context = new JSONStreamContext(context, JSONStreamContext.StartObject);
writer.write('{');
}
public void endObject() {
writer.write('}');
endStructure();
}
public void writeKey(String key) {
writeObject(key);
}
public void writeValue(Object object) {
writeObject(object);
}
public void writeObject(String object) {
beforeWrite();
serializer.write(object);
afterWriter();
}
public void writeObject(Object object) {
beforeWrite();
serializer.write(object);
afterWriter();
}
public void startArray() {
if (context != null) {
beginStructure();
}
context = new JSONStreamContext(context, StartArray);
writer.write('[');
}
private void beginStructure() {
final int state = context.state;
switch (context.state) {
case PropertyKey:
writer.write(':');
break;
case ArrayValue:
writer.write(',');
break;
case StartObject:
break;
case StartArray:
break;
default:
throw new JSONException("illegal state : " + state);
}
}
public void endArray() {
writer.write(']');
endStructure();
}
private void endStructure() {
context = context.parent;
if (context == null) {
return;
}
int newState = -1;
switch (context.state) {
case PropertyKey:
newState = PropertyValue;
break;
case StartArray:
newState = ArrayValue;
break;
case ArrayValue:
break;
case StartObject:
newState = PropertyKey;
break;
default:
break;
}
if (newState != -1) {
context.state = newState;
}
}
private void beforeWrite() {
if (context == null) {
return;
}
switch (context.state) {
case StartObject:
case StartArray:
break;
case PropertyKey:
writer.write(':');
break;
case PropertyValue:
writer.write(',');
break;
case ArrayValue:
writer.write(',');
break;
default:
break;
}
}
private void afterWriter() {
if (context == null) {
return;
}
final int state = context.state;
int newState = -1;
switch (state) {
case PropertyKey:
newState = PropertyValue;
break;
case StartObject:
case PropertyValue:
newState = PropertyKey;
break;
case StartArray:
newState = ArrayValue;
break;
case ArrayValue:
break;
default:
break;
}
if (newState != -1) {
context.state = newState;
}
}
public void flush() throws IOException {
writer.flush();
}
public void close() throws IOException {
writer.close();
}
}
package com.sobot.fastjson;
/**
* @since 1.2.15, back port to 1.1.53.android
*/
public enum PropertyNamingStrategy {
CamelCase, //
PascalCase, //
SnakeCase, //
KebabCase;
public String translate(String propertyName) {
switch (this) {
case SnakeCase: {
StringBuilder buf = new StringBuilder();
for (int i = 0; i < propertyName.length(); ++i) {
char ch = propertyName.charAt(i);
if (ch >= 'A' && ch <= 'Z') {
char ch_ucase = (char) (ch + 32);
if (i > 0) {
buf.append('_');
}
buf.append(ch_ucase);
} else {
buf.append(ch);
}
}
return buf.toString();
}
case KebabCase: {
StringBuilder buf = new StringBuilder();
for (int i = 0; i < propertyName.length(); ++i) {
char ch = propertyName.charAt(i);
if (ch >= 'A' && ch <= 'Z') {
char ch_ucase = (char) (ch + 32);
if (i > 0) {
buf.append('-');
}
buf.append(ch_ucase);
} else {
buf.append(ch);
}
}
return buf.toString();
}
case PascalCase: {
char ch = propertyName.charAt(0);
if (ch >= 'a' && ch <= 'z') {
char[] chars = propertyName.toCharArray();
chars[0] -= 32;
return new String(chars);
}
return propertyName;
}
case CamelCase: {
char ch = propertyName.charAt(0);
if (ch >= 'A' && ch <= 'Z') {
char[] chars = propertyName.toCharArray();
chars[0] += 32;
return new String(chars);
}
return propertyName;
}
default:
return propertyName;
}
}
}
package com.sobot.fastjson;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
//json 工具类
public class SobotJsonUtils {
/**
* 返回Json字符串里面包含的一个对象
*
* @param jsonStr :{"city":"china","map1":[{"age":"28","name":"yys"}]}
* @param list_str :map1
* @param clazz :Map.class,或者其他对象
* @param <T> :Map
* @return :List<Map>
*/
public static final <T> List<T> jsonToChildList(String jsonStr, String list_str,
Class<T> clazz) {
JSONObject jsonobj = JSON.parseObject(jsonStr);
if (jsonobj == null) {
return null;
}
Object obj = jsonobj.get(list_str);
if (obj == null) {
return null;
}
if (obj instanceof JSONArray) {
JSONArray jsonarr = (JSONArray) obj;
List<T> list = new ArrayList<T>();
for (int i = 0; i < jsonarr.size(); i++) {
list.add(jsonarr.getObject(i, clazz));
}
return list;
}
return null;
}
/**
* 返回Json字符串里面包含的一个对象
*
* @param jsonStr :{"department":{"id":"1","name":"生产部"},"password":"admin","username":"admin"}
* @param obj_str :department
* @param clazz :Map.class,或者其他对象
* @param <T> :Map
* @return
*/
public static final <T> T jsonToChildObj(String jsonStr, String obj_str,
Class<T> clazz) {
JSONObject jsonobj = JSON.parseObject(jsonStr);
if (jsonobj == null) {
return null;
}
Object obj = jsonobj.get(obj_str);
if (obj == null) {
return null;
}
if (obj instanceof JSONObject) {
return jsonobj.getObject(obj_str, clazz);
} else {
Log.i("", obj.getClass() + "");
}
return null;
}
/**
* json 转换成对象
*
* @param jsonStr
* @param clazz
* @param <T>
* @return
*/
public static final <T> T jsonToObj(String jsonStr, Class<T> clazz) {
T t = null;
try {
t = JSON.parseObject(jsonStr, clazz);
} catch (Exception e) {
Log.e("json字符串转换失败!" + jsonStr, e.getMessage());
}
return t;
}
/**
* 对象转换成json字符串(带有格式化输出)
*
* @param object 要转换的对象
* @param prettyFormat 是否格式化json字符串,输出带有换行和缩进的字符串
* @return 返回一个json 字符串数组
*/
public static final String objToJson(Object object, boolean prettyFormat) {
return JSON.toJSONString(object, prettyFormat);
}
/**
* 对象转换成json字符串
*
* @param object 要转换的对象
* @return 返回一个json 字符串数组
*/
public static final String objToJson(Object object) {
return JSON.toJSONString(object);
}
/**
* json 字符串转换成原始的Object对象
*
* @param jsonStr
* @return
*/
public static final Object jsonToObj(String jsonStr) {
return JSON.parse(jsonStr);
}
/**
* json字符串转换成list
*
* @param jsonStr Json字符串
* @param clazz 要转换的class
* @param <T>返回的泛型类型
* @return 返回的<T>泛型类型
*/
public static <T> List<T> jsonToList(String jsonStr, Class<T> clazz) {
List<T> list = new ArrayList<T>();
try {
list = JSON.parseArray(jsonStr, clazz);
} catch (Exception e) {
Log.e("json字符串转List失败!" + jsonStr, e.toString());
}
return list;
}
/**
* json字符串转换成Map
*
* @param jsonStr Json字符串
* @return Map
*/
public static Map<String, Object> jsonToMap(String jsonStr) {
try {
return JSON.parseObject(jsonStr, Map.class);
} catch (Exception e) {
Log.e("json字符串转换失败!" + jsonStr, e.getMessage());
}
return null;
}
/**
* json 转换成list<map>
*
* @param jsonString
* @return
*/
public static List<Map<String, Object>> jsonToListkeyMap(String jsonString) {
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
try {
list = JSON.parseObject(jsonString,
new TypeReference<List<Map<String, Object>>>() {
});
} catch (Exception e) {
Log.e("json字符串转map失败", e.getMessage());
}
return list;
}
}
package com.sobot.fastjson;
import com.sobot.fastjson.util.ParameterizedTypeImpl;
import com.sobot.fastjson.util.TypeUtils;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* Represents a generic type {@code T}. Java doesn't yet provide a way to
* represent generic types, so this class does. Forces clients to create a
* subclass of this class which enables retrieval the type information even at
* runtime.
*
* <p>For example, to create a type literal for List&lt;String&gt;, you can
* create an empty anonymous inner class:
*
* <p>
* List&lt;String&gt; list = JSON.parseObject("...", new TypeReference&lt;List&lt;String&gt;&gt;() {});
*
*
* @author wenshao[szujobs@hotmail.com]
*/
public class TypeReference<T> {
static ConcurrentMap<Type, Type> classTypeCache
= new ConcurrentHashMap<Type, Type>(16, 0.75f, 1);
protected final Type type;
protected TypeReference(){
Type superClass = getClass().getGenericSuperclass();
Type oriType = ((ParameterizedType) superClass).getActualTypeArguments()[0];
if (oriType instanceof Class) {
type = oriType;
} else {
//修复在安卓环境中问题
Type cachedType = classTypeCache.get(oriType);
if (cachedType == null) {
classTypeCache.putIfAbsent(oriType, oriType);
cachedType = classTypeCache.get(oriType);
}
type = cachedType;
}
}
/**
* @since 1.2.9 & 1.1.58.android
* @param actualTypeArguments
*/
protected TypeReference(Type... actualTypeArguments){
Class<?> thisClass = this.getClass();
Type superClass = thisClass.getGenericSuperclass();
ParameterizedType argType = (ParameterizedType) ((ParameterizedType) superClass).getActualTypeArguments()[0];
Type rawType = argType.getRawType();
Type[] argTypes = argType.getActualTypeArguments();
int actualIndex = 0;
for (int i = 0; i < argTypes.length; ++i) {
if (argTypes[i] instanceof TypeVariable &&
actualIndex < actualTypeArguments.length) {
argTypes[i] = actualTypeArguments[actualIndex++];
}
// fix for openjdk and android env
if (argTypes[i] instanceof GenericArrayType) {
argTypes[i] = TypeUtils.checkPrimitiveArray(
(GenericArrayType) argTypes[i]);
}
// 如果有多层泛型且该泛型已经注明实现的情况下,判断该泛型下一层是否还有泛型
if(argTypes[i] instanceof ParameterizedType) {
argTypes[i] = handlerParameterizedType((ParameterizedType) argTypes[i], actualTypeArguments, actualIndex);
}
}
Type key = new ParameterizedTypeImpl(argTypes, thisClass, rawType);
Type cachedType = classTypeCache.get(key);
if (cachedType == null) {
classTypeCache.putIfAbsent(key, key);
cachedType = classTypeCache.get(key);
}
type = cachedType;
}
private Type handlerParameterizedType(ParameterizedType type, Type[] actualTypeArguments, int actualIndex) {
Class<?> thisClass = this.getClass();
Type rawType = type.getRawType();
Type[] argTypes = type.getActualTypeArguments();
for(int i = 0; i < argTypes.length; ++i) {
if (argTypes[i] instanceof TypeVariable && actualIndex < actualTypeArguments.length) {
argTypes[i] = actualTypeArguments[actualIndex++];
}
// fix for openjdk and android env
if (argTypes[i] instanceof GenericArrayType) {
argTypes[i] = TypeUtils.checkPrimitiveArray(
(GenericArrayType) argTypes[i]);
}
// 如果有多层泛型且该泛型已经注明实现的情况下,判断该泛型下一层是否还有泛型
if(argTypes[i] instanceof ParameterizedType) {
return handlerParameterizedType((ParameterizedType) argTypes[i], actualTypeArguments, actualIndex);
}
}
Type key = new ParameterizedTypeImpl(argTypes, thisClass, rawType);
return key;
}
public Type getType() {
return type;
}
}
package com.sobot.fastjson.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.CONSTRUCTOR, ElementType.METHOD })
public @interface JSONCreator {
}
/*
* 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.sobot.fastjson.annotation;
import com.sobot.fastjson.parser.Feature;
import com.sobot.fastjson.serializer.SerializerFeature;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author wenshao[szujobs@hotmail.com]
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER })
public @interface JSONField {
/**
* config encode/decode ordinal
* @since 1.1.42
* @return
*/
int ordinal() default 0;
String name() default "";
String format() default "";
boolean serialize() default true;
boolean deserialize() default true;
SerializerFeature[] serialzeFeatures() default {};
Feature[] parseFeatures() default {};
String[] alternateNames() default {};
}
package com.sobot.fastjson.annotation;
import com.sobot.fastjson.PropertyNamingStrategy;
import com.sobot.fastjson.parser.Feature;
import com.sobot.fastjson.serializer.SerializerFeature;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author wenshao[szujobs@hotmail.com]
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE })
public @interface JSONType {
boolean asm() default true;
String[] orders() default {};
String[] ignores() default {};
SerializerFeature[] serialzeFeatures() default {};
Feature[] parseFeatures() default {};
boolean alphabetic() default true;
Class<?> mappingTo() default Void.class;
/**
* @since 1.2.11 backport to 1.1.52.android
*/
String typeName() default "";
String typeKey() default "";
/**
* @since 1.2.11 backport to 1.1.52.android
*/
Class<?>[] seeAlso() default{};
/**
*
* @return
*/
PropertyNamingStrategy naming() default PropertyNamingStrategy.CamelCase;
}
package com.sobot.fastjson.parser;
import com.sobot.fastjson.parser.DefaultJSONParser.ResolveTask;
import com.sobot.fastjson.parser.deserializer.FieldDeserializer;
import com.sobot.fastjson.parser.deserializer.ObjectDeserializer;
import com.sobot.fastjson.serializer.DateCodec;
import com.sobot.fastjson.util.FieldInfo;
import com.sobot.fastjson.util.ParameterizedTypeImpl;
import com.sobot.fastjson.util.TypeUtils;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Map;
public class DefaultFieldDeserializer extends FieldDeserializer {
protected ObjectDeserializer fieldValueDeserilizer;
public DefaultFieldDeserializer(ParserConfig mapping, Class<?> clazz, FieldInfo fieldInfo){
super(clazz, fieldInfo, JSONToken.LITERAL_INT);
}
public ObjectDeserializer getFieldValueDeserilizer(ParserConfig config) {
if (fieldValueDeserilizer == null) {
fieldValueDeserilizer = config.getDeserializer(fieldInfo.fieldClass, fieldInfo.fieldType);
}
return fieldValueDeserilizer;
}
@Override
public void parseField(DefaultJSONParser parser, Object object, Type objectType, Map<String, Object> fieldValues) {
if (this.fieldValueDeserilizer == null) {
this.fieldValueDeserilizer = parser.config.getDeserializer(fieldInfo.fieldClass, fieldInfo.fieldType);
}
Type fieldType = fieldInfo.fieldType;
if (objectType instanceof ParameterizedType) {
ParseContext objContext = parser.contex;
if (objContext != null) {
objContext.type = objectType;
}
fieldType = FieldInfo.getFieldType(this.clazz, objectType, fieldType);
fieldValueDeserilizer = parser.config.getDeserializer(fieldType);
}
if (fieldType instanceof ParameterizedType
&& objectType instanceof ParameterizedType) {
ParameterizedType fieldParamType = (ParameterizedType) fieldType;
ParameterizedType objectParamType = (ParameterizedType) objectType;
Type[] args = fieldParamType.getActualTypeArguments();
Type rawType = objectParamType.getRawType();
if (rawType instanceof Class) {
Class<?> rawClass = (Class) rawType;
TypeVariable[] typeParameters = rawClass.getTypeParameters();
boolean changed = TypeUtils.getArgument(args, typeParameters, objectParamType.getActualTypeArguments());
if (changed) {
fieldType = new ParameterizedTypeImpl(args, fieldParamType.getOwnerType(), fieldParamType.getRawType());
}
}
}
String format = fieldInfo.format;
Object value;
if (format != null && fieldValueDeserilizer instanceof DateCodec) {
value = ((DateCodec) fieldValueDeserilizer).deserialze(parser, fieldType, fieldInfo.name, format);
} else {
value = fieldValueDeserilizer.deserialze(parser, fieldType, fieldInfo.name);
}
if (parser.resolveStatus == DefaultJSONParser.NeedToResolve) {
ResolveTask task = parser.getLastResolveTask();
task.fieldDeserializer = this;
task.ownerContext = parser.contex;
parser.resolveStatus = DefaultJSONParser.NONE;
} else {
if (object == null) {
fieldValues.put(fieldInfo.name, value);
} else {
if (value == null) {
Class<?> fieldClass = fieldInfo.fieldClass;
if (fieldClass == byte.class //
|| fieldClass == short.class //
|| fieldClass == float.class //
|| fieldClass == double.class) {
return;
}
}
setValue(object, value);
}
}
}
}
package com.sobot.fastjson.parser;
import com.sobot.fastjson.JSONException;
import com.sobot.fastjson.parser.deserializer.ObjectDeserializer;
import java.lang.reflect.Type;
import java.util.Arrays;
@SuppressWarnings("rawtypes")
public class EnumDeserializer implements ObjectDeserializer {
private final Class<?> enumClass;
protected final Enum[] enums;
protected final Enum[] ordinalEnums;
protected long[] enumNameHashCodes;
public EnumDeserializer(Class<?> enumClass){
this.enumClass = enumClass;
ordinalEnums = (Enum[]) enumClass.getEnumConstants();
long[] enumNameHashCodes = new long[ordinalEnums.length];
this.enumNameHashCodes = new long[ordinalEnums.length];
for (int i = 0; i < ordinalEnums.length; ++i) {
String name = ordinalEnums[i].name();
long hash = 0xcbf29ce484222325L;
for (int j = 0; j < name.length(); ++j) {
char ch = name.charAt(j);
hash ^= ch;
hash *= 0x100000001b3L;
}
enumNameHashCodes[i] = hash;
this.enumNameHashCodes[i] = hash;
}
Arrays.sort(this.enumNameHashCodes);
this.enums = new Enum[ordinalEnums.length];
for (int i = 0; i < this.enumNameHashCodes.length; ++i) {
for (int j = 0; j < enumNameHashCodes.length; ++j) {
if (this.enumNameHashCodes[i] == enumNameHashCodes[j]) {
this.enums[i] = ordinalEnums[j];
break;
}
}
}
}
@SuppressWarnings("unchecked")
public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
try {
Object value;
final JSONLexer lexer = parser.lexer;
final int token = lexer.token;
if (token == JSONToken.LITERAL_INT) {
int intValue = lexer.intValue();
lexer.nextToken(JSONToken.COMMA);
if (intValue < 0 || intValue > ordinalEnums.length) {
throw new JSONException("parse enum " + enumClass.getName() + " error, value : " + intValue);
}
return (T) ordinalEnums[intValue];
} else if (token == JSONToken.LITERAL_STRING) {
String name = lexer.stringVal();
lexer.nextToken(JSONToken.COMMA);
if (name.length() == 0) {
return (T) null;
}
long hash = 0xcbf29ce484222325L;
for (int j = 0; j < name.length(); ++j) {
char ch = name.charAt(j);
hash ^= ch;
hash *= 0x100000001b3L;
}
int enumIndex = Arrays.binarySearch(this.enumNameHashCodes, hash);
if (enumIndex < 0) {
return null;
}
return (T) enums[enumIndex];
} else if (token == JSONToken.NULL) {
value = null;
lexer.nextToken(JSONToken.COMMA);
return null;
} else {
value = parser.parse();
}
throw new JSONException("parse enum " + enumClass.getName() + " error, value : " + value);
} catch (JSONException e) {
throw e;
} catch (Exception e) {
throw new JSONException(e.getMessage(), e);
}
}
}
/*
* 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.sobot.fastjson.parser;
/**
* @author wenshao[szujobs@hotmail.com]
*/
public enum Feature {
/**
*
*/
AutoCloseSource,
/**
*
*/
AllowComment,
/**
*
*/
AllowUnQuotedFieldNames,
/**
*
*/
AllowSingleQuotes,
/**
*
*/
InternFieldNames,
/**
*
*/
AllowISO8601DateFormat,
/**
* {"a":1,,,"b":2}
*/
AllowArbitraryCommas,
/**
*
*/
UseBigDecimal,
/**
* @since 1.1.2
*/
IgnoreNotMatch,
/**
* @since 1.1.3
*/
SortFeidFastMatch,
/**
* @since 1.1.3
*/
DisableASM,
/**
* @since 1.1.7
*/
DisableCircularReferenceDetect,
/**
* @since 1.1.10
*/
InitStringFieldAsEmpty,
/**
* @since 1.1.35
*
*/
SupportArrayToBean,
/**
* @since 1.2.5, backport to 1.1.49.android
*/
OrderedField,
/**
* @since 1.2.5, backport to 1.1.49.android
*/
DisableSpecialKeyDetect,
/**
* @since 1.2.22, backport to 1.1.54.android
*/
SupportNonPublicField,
/**
* @since 1.2.41, backport to 1.1.66.android
*/
SupportAutoType
;
private Feature(){
mask = (1 << ordinal());
}
public final int mask;
}
This source diff could not be displayed because it is too large. You can view the blob instead.
/*
* 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.sobot.fastjson.parser;
/**
* @author wenshao[szujobs@hotmail.com]
*/
public class JSONToken {
//
public final static int ERROR = 1;
//
public final static int LITERAL_INT = 2;
//
public final static int LITERAL_FLOAT = 3;
//
public final static int LITERAL_STRING = 4;
//
public final static int LITERAL_ISO8601_DATE = 5;
public final static int TRUE = 6;
//
public final static int FALSE = 7;
//
public final static int NULL = 8;
//
public final static int NEW = 9;
//
public final static int LPAREN = 10; // ("("),
//
public final static int RPAREN = 11; // (")"),
//
public final static int LBRACE = 12; // ("{"),
//
public final static int RBRACE = 13; // ("}"),
//
public final static int LBRACKET = 14; // ("["),
//
public final static int RBRACKET = 15; // ("]"),
//
public final static int COMMA = 16; // (","),
//
public final static int COLON = 17; // (":"),
//
public final static int IDENTIFIER = 18;
//
// public final static int FIELD_NAME = 19;
public final static int EOF = 20;
public final static int SET = 21;
public final static int TREE_SET = 22;
public final static int UNDEFINED = 23; // undefined
public static String name(int value) {
switch (value) {
case ERROR:
return "error";
case LITERAL_INT:
return "int";
case LITERAL_FLOAT:
return "float";
case LITERAL_STRING:
return "string";
case LITERAL_ISO8601_DATE:
return "iso8601";
case TRUE:
return "true";
case FALSE:
return "false";
case NULL:
return "null";
case NEW:
return "new";
case LPAREN:
return "(";
case RPAREN:
return ")";
case LBRACE:
return "{";
case RBRACE:
return "}";
case LBRACKET:
return "[";
case RBRACKET:
return "]";
case COMMA:
return ",";
case COLON:
return ":";
case IDENTIFIER:
return "ident";
// case FIELD_NAME:
// return "fieldName";
case EOF:
return "EOF";
case SET:
return "Set";
case TREE_SET:
return "TreeSet";
case UNDEFINED:
return "undefined";
default:
return "Unknown";
}
}
}
package com.sobot.fastjson.parser;
import com.sobot.fastjson.parser.deserializer.ObjectDeserializer;
import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.List;
class JavaObjectDeserializer implements ObjectDeserializer {
public final static JavaObjectDeserializer instance = new JavaObjectDeserializer();
@SuppressWarnings("unchecked")
public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
if (type instanceof GenericArrayType) {
Type componentType = ((GenericArrayType) type).getGenericComponentType();
if (componentType instanceof TypeVariable) {
TypeVariable<?> componentVar = (TypeVariable<?>) componentType;
componentType = componentVar.getBounds()[0];
}
List<Object> list = new ArrayList<Object>();
parser.parseArray(componentType, list);
Class<?> componentClass;
if (componentType instanceof Class) {
componentClass = (Class<?>) componentType;
Object[] array = (Object[]) Array.newInstance(componentClass, list.size());
list.toArray(array);
return (T) array;
} else {
return (T) list.toArray();
}
}
return (T) parser.parse(fieldName);
}
}
package com.sobot.fastjson.parser;
import com.sobot.fastjson.JSONArray;
import com.sobot.fastjson.JSONException;
import com.sobot.fastjson.parser.deserializer.FieldDeserializer;
import com.sobot.fastjson.parser.deserializer.ObjectDeserializer;
import com.sobot.fastjson.util.FieldInfo;
import com.sobot.fastjson.util.ParameterizedTypeImpl;
import com.sobot.fastjson.util.TypeUtils;
import java.lang.reflect.Array;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
class ListTypeFieldDeserializer extends FieldDeserializer {
private final Type itemType;
private ObjectDeserializer deserializer;
private final boolean array;
public ListTypeFieldDeserializer(ParserConfig mapping, Class<?> clazz, FieldInfo fieldInfo){
super(clazz, fieldInfo, JSONToken.LBRACKET);
Type fieldType = fieldInfo.fieldType;
Class<?> fieldClass= fieldInfo.fieldClass;
if (fieldClass.isArray()) {
this.itemType = fieldClass.getComponentType();
array = true;
} else {
this.itemType = TypeUtils.getCollectionItemType(fieldType);
array = false;
}
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public void parseField(DefaultJSONParser parser, Object object, Type objectType, Map<String, Object> fieldValues) {
JSONLexer lexer = parser.lexer;
final int token = lexer.token();
if (token == JSONToken.NULL
|| (token == JSONToken.LITERAL_STRING && lexer.stringVal().length() == 0)) {
setValue(object, null);
parser.lexer.nextToken();
return;
}
JSONArray jsonArray = null;
List list;
if (array) {
list = jsonArray = new JSONArray();
jsonArray.setComponentType(itemType);
} else {
list = new ArrayList();
}
ParseContext context = parser.contex;
parser.setContext(context, object, fieldInfo.name);
parseArray(parser, objectType, list);
parser.setContext(context);
Object fieldValue;
if (array) {
Object[] arrayValue = (Object[]) Array.newInstance((Class<?>)itemType, list.size());
fieldValue = list.toArray(arrayValue);
jsonArray.setRelatedArray(fieldValue);
} else {
fieldValue = list;
}
if (object == null) {
fieldValues.put(fieldInfo.name, fieldValue);
} else {
setValue(object, fieldValue);
}
}
@SuppressWarnings({ "unchecked", "rawtypes" })
final void parseArray(DefaultJSONParser parser, Type objectType, Collection array) {
Type itemType = this.itemType;
ObjectDeserializer itemTypeDeser = this.deserializer;
if (objectType instanceof ParameterizedType) {
if (itemType instanceof TypeVariable) {
TypeVariable typeVar = (TypeVariable) itemType;
ParameterizedType paramType = (ParameterizedType) objectType;
Class<?> objectClass = null;
if (paramType.getRawType() instanceof Class) {
objectClass = (Class<?>) paramType.getRawType();
}
int paramIndex = -1;
if (objectClass != null) {
for (int i = 0, size = objectClass.getTypeParameters().length; i < size; ++i) {
TypeVariable item = objectClass.getTypeParameters()[i];
if (item.getName().equals(typeVar.getName())) {
paramIndex = i;
break;
}
}
}
if (paramIndex != -1) {
itemType = paramType.getActualTypeArguments()[paramIndex];
if (!itemType.equals(this.itemType)) {
itemTypeDeser = parser.config.getDeserializer(itemType);
}
}
} else if (itemType instanceof ParameterizedType) {
ParameterizedType parameterizedItemType = (ParameterizedType) itemType;
Type[] itemActualTypeArgs = parameterizedItemType.getActualTypeArguments();
if (itemActualTypeArgs.length == 1 && itemActualTypeArgs[0] instanceof TypeVariable) {
TypeVariable typeVar = (TypeVariable) itemActualTypeArgs[0];
ParameterizedType paramType = (ParameterizedType) objectType;
Class<?> objectClass = null;
if (paramType.getRawType() instanceof Class) {
objectClass = (Class<?>) paramType.getRawType();
}
int paramIndex = -1;
if (objectClass != null) {
for (int i = 0, size = objectClass.getTypeParameters().length; i < size; ++i) {
TypeVariable item = objectClass.getTypeParameters()[i];
if (item.getName().equals(typeVar.getName())) {
paramIndex = i;
break;
}
}
}
if (paramIndex != -1) {
itemActualTypeArgs[0] = paramType.getActualTypeArguments()[paramIndex];
itemType = new ParameterizedTypeImpl(itemActualTypeArgs, parameterizedItemType.getOwnerType(), parameterizedItemType.getRawType());
}
}
}
} else if (itemType instanceof TypeVariable && objectType instanceof Class) {
Class objectClass = (Class) objectType;
TypeVariable typeVar = (TypeVariable) itemType;
objectClass.getTypeParameters();
for (int i = 0, size = objectClass.getTypeParameters().length; i < size; ++i) {
TypeVariable item = objectClass.getTypeParameters()[i];
if (item.getName().equals(typeVar.getName())) {
Type[] bounds = item.getBounds();
if (bounds.length == 1) {
itemType = bounds[0];
}
break;
}
}
}
final JSONLexer lexer = parser.lexer;
if (itemTypeDeser == null) {
itemTypeDeser = deserializer = parser.config.getDeserializer(itemType);
}
if (lexer.token != JSONToken.LBRACKET) {
if (lexer.token == JSONToken.LBRACE) {
Object val = itemTypeDeser.deserialze(parser, itemType, 0);
array.add(val);
return;
} else {
String errorMessage = "exepct '[', but " + JSONToken.name(lexer.token);
if (objectType != null) {
errorMessage += ", type : " + objectType;
}
throw new JSONException(errorMessage);
}
}
int ch = lexer.ch;
if (ch == '[') {
int index = ++lexer.bp;
lexer.ch = (index >= lexer.len ? //
JSONLexer.EOI //
: lexer.text.charAt(index));
lexer.token = JSONToken.LBRACKET;
} else if (ch == '{') {
int index = ++lexer.bp;
lexer.ch = (index >= lexer.len ? //
JSONLexer.EOI //
: lexer.text.charAt(index));
lexer.token = JSONToken.LBRACE;
} else if (ch == '"') {
lexer.scanString();
} else if (ch == ']') {
int index = ++lexer.bp;
lexer.ch = (index >= lexer.len ? //
JSONLexer.EOI //
: lexer.text.charAt(index));
lexer.token = JSONToken.RBRACKET;
} else {
lexer.nextToken();
}
for (int i = 0;; ++i) {
while (lexer.token == JSONToken.COMMA) {
lexer.nextToken();
continue;
}
if (lexer.token == JSONToken.RBRACKET) {
break;
}
Object val = itemTypeDeser.deserialze(parser, itemType, i);
array.add(val);
if (parser.resolveStatus == DefaultJSONParser.NeedToResolve) {
parser.checkListResolve(array);
}
if (lexer.token == JSONToken.COMMA) {
ch = lexer.ch;
if (ch == '[') {
int index = ++lexer.bp;
lexer.ch = (index >= lexer.len ? //
JSONLexer.EOI //
: lexer.text.charAt(index));
lexer.token = JSONToken.LBRACKET;
} else if (ch == '{') {
int index = ++lexer.bp;
lexer.ch = (index >= lexer.len ? //
JSONLexer.EOI //
: lexer.text.charAt(index));
lexer.token = JSONToken.LBRACE;
} else if (ch == '"') {
lexer.scanString();
} else {
lexer.nextToken();
}
continue;
}
}
if (lexer.ch == ',') {
int index = ++lexer.bp;
lexer.ch = (index >= lexer.len ? //
JSONLexer.EOI //
: lexer.text.charAt(index));
lexer.token = JSONToken.COMMA;
} else {
lexer.nextToken();
}
}
}
package com.sobot.fastjson.parser;
import java.lang.reflect.Type;
public class ParseContext {
public Object object;
public final ParseContext parent;
public final Object fieldName;
public Type type;
private transient String path;
public ParseContext(ParseContext parent, Object object, Object fieldName){
this.parent = parent;
this.object = object;
this.fieldName = fieldName;
}
public String toString() {
if (path == null) {
if (parent == null) {
path = "$";
} else {
if (fieldName instanceof Integer) {
path = parent.toString() + "[" + fieldName + "]";
} else {
path = parent.toString() + "." + fieldName;
}
}
}
return path;
}
}
package com.sobot.fastjson.parser;
import com.sobot.fastjson.JSONArray;
import com.sobot.fastjson.parser.deserializer.FieldDeserializer;
import com.sobot.fastjson.util.TypeUtils;
import java.lang.reflect.Array;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@SuppressWarnings("rawtypes")
final class ResolveFieldDeserializer extends FieldDeserializer {
private final int index;
private final List list;
private final DefaultJSONParser parser;
private final Object key;
private final Map map;
private final Collection collection;
public ResolveFieldDeserializer(DefaultJSONParser parser, List list, int index){
super(null, null, 0);
this.parser = parser;
this.index = index;
this.list = list;
key = null;
map = null;
collection = null;
}
public ResolveFieldDeserializer(Map map, Object index){
super(null, null, 0);
this.parser = null;
this.index = -1;
this.list = null;
this.key = index;
this.map = map;
collection = null;
}
public ResolveFieldDeserializer(Collection collection){
super(null, null, 0);
this.parser = null;
this.index = -1;
this.list = null;
key = null;
map = null;
this.collection = collection;
}
@SuppressWarnings("unchecked")
public void setValue(Object object, Object value) {
if (map != null) {
map.put(key, value);
return;
}
if (collection != null) {
collection.add(value);
return;
}
list.set(index, value);
if (list instanceof JSONArray) {
JSONArray jsonArray = (JSONArray) list;
Object array = jsonArray.getRelatedArray();
if (array != null) {
int arrayLength = Array.getLength(array);
if (arrayLength > index) {
Object item;
if (jsonArray.getComponentType() != null) {
item = TypeUtils.cast(value, jsonArray.getComponentType(), parser.config);
} else {
item = value;
}
Array.set(array, index, item);
}
}
}
}
public void parseField(DefaultJSONParser parser, Object object, Type objectType, Map<String, Object> fieldValues) {
}
}
/*
* 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.sobot.fastjson.parser;
import com.sobot.fastjson.JSON;
/**
* @author wenshao[szujobs@hotmail.com]
*/
public class SymbolTable {
private final Entry[] symbols;
private final int indexMask;
public SymbolTable(int tableSize){
this.indexMask = tableSize - 1;
this.symbols = new Entry[tableSize];
this.addSymbol("$ref", 0, 4, "$ref".hashCode());
this.addSymbol(JSON.DEFAULT_TYPE_KEY, 0, JSON.DEFAULT_TYPE_KEY.length(), JSON.DEFAULT_TYPE_KEY.hashCode());
}
/**
* Adds the specified symbol to the symbol table and returns a reference to the unique symbol. If the symbol already
* exists, the previous symbol reference is returned instead, in order guarantee that symbol references remain
* unique.
*
* @param buffer The buffer containing the new symbol.
* @param offset The offset into the buffer of the new symbol.
* @param len The length of the new symbol in the buffer.
*/
public String addSymbol(char[] buffer, int offset, int len, int hash) {
final int bucket = hash & indexMask;
Entry entry = symbols[bucket];
if (entry != null) {
boolean eq = true;
if (hash == entry.hashCode //
&& len == entry.chars.length) {
for (int i = 0; i < len; i++) {
if (buffer[offset + i] != entry.chars[i]) {
eq = false;
break;
}
}
} else {
eq = false;
}
if (eq) {
return entry.value;
} else {
return new String(buffer, offset, len);
}
}
String strVal = new String(buffer, offset, len).intern();
entry = new Entry(strVal, hash);
symbols[bucket] = entry;
return strVal;
}
public String addSymbol(String buffer, int offset, int len, int hash) {
final int bucket = hash & indexMask;
Entry entry = symbols[bucket];
if (entry != null) {
if (hash == entry.hashCode //
&& len == entry.chars.length //
&& buffer.regionMatches(offset, entry.value, 0, len)) {
return entry.value;
}
return subString(buffer, offset, len);
}
String symbol = len == buffer.length() ? //
buffer //
: subString(buffer, offset, len);
symbol = symbol.intern();
symbols[bucket] = new Entry(symbol, hash);
return symbol;
}
private static String subString(String src, int offset, int len) {
char[] chars = new char[len];
src.getChars(offset, offset + len, chars, 0);
return new String(chars);
}
static class Entry {
final String value;
final char[] chars;
final int hashCode;
Entry(String value, int hashCode) {
this.value = value;
this.chars = value.toCharArray();
this.hashCode = hashCode;
}
}
}
package com.sobot.fastjson.parser;
import com.sobot.fastjson.JSON;
import com.sobot.fastjson.JSONException;
import com.sobot.fastjson.parser.deserializer.FieldDeserializer;
import com.sobot.fastjson.parser.deserializer.ObjectDeserializer;
import com.sobot.fastjson.util.TypeUtils;
import java.lang.reflect.Constructor;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
public class ThrowableDeserializer extends JavaBeanDeserializer {
public ThrowableDeserializer(ParserConfig mapping, Class<?> clazz){
super(mapping, clazz, clazz);
}
@SuppressWarnings("unchecked")
public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
JSONLexer lexer = parser.lexer;
if (lexer.token == JSONToken.NULL) {
lexer.nextToken();
return null;
}
if (parser.resolveStatus == DefaultJSONParser.TypeNameRedirect) {
parser.resolveStatus = DefaultJSONParser.NONE;
} else {
if (lexer.token != JSONToken.LBRACE) {
throw new JSONException("syntax error");
}
}
Throwable cause = null;
Class<?> exClass = null;
if (type != null && type instanceof Class) {
Class<?> clazz = (Class<?>) type;
if (Throwable.class.isAssignableFrom(clazz)) {
exClass = clazz;
}
}
String message = null;
StackTraceElement[] stackTrace = null;
Map<String, Object> otherValues = null;
for (;;) {
// lexer.scanSymbol
String key = lexer.scanSymbol(parser.symbolTable);
if (key == null) {
if (lexer.token == JSONToken.RBRACE) {
lexer.nextToken(JSONToken.COMMA);
break;
}
if (lexer.token == JSONToken.COMMA) {
continue;
}
}
lexer.nextTokenWithChar(':');
if (JSON.DEFAULT_TYPE_KEY.equals(key)) {
if (lexer.token == JSONToken.LITERAL_STRING) {
String exClassName = lexer.stringVal();
exClass = TypeUtils.loadClass(exClassName, parser.config.defaultClassLoader, false);
} else {
throw new JSONException("syntax error");
}
lexer.nextToken(JSONToken.COMMA);
} else if ("message".equals(key)) {
if (lexer.token == JSONToken.NULL) {
message = null;
} else if (lexer.token == JSONToken.LITERAL_STRING) {
message = lexer.stringVal();
} else {
throw new JSONException("syntax error");
}
lexer.nextToken();
} else if ("cause".equals(key)) {
cause = deserialze(parser, null, "cause");
} else if ("stackTrace".equals(key)) {
stackTrace = parser.parseObject(StackTraceElement[].class);
} else {
if (otherValues == null) {
otherValues = new HashMap<String, Object>();
}
otherValues.put(key, parser.parse());
}
if (lexer.token == JSONToken.RBRACE) {
lexer.nextToken(JSONToken.COMMA);
break;
}
}
Throwable ex = null;
if (exClass == null) {
ex = new Exception(message, cause);
} else {
try {
Constructor<?> defaultConstructor = null;
Constructor<?> messageConstructor = null;
Constructor<?> causeConstructor = null;
for (Constructor<?> constructor : exClass.getConstructors()) {
if (constructor.getParameterTypes().length == 0) {
defaultConstructor = constructor;
continue;
}
if (constructor.getParameterTypes().length == 1 && constructor.getParameterTypes()[0] == String.class) {
messageConstructor = constructor;
continue;
}
if (constructor.getParameterTypes().length == 2 && constructor.getParameterTypes()[0] == String.class
&& constructor.getParameterTypes()[1] == Throwable.class) {
causeConstructor = constructor;
continue;
}
}
if (causeConstructor != null) {
ex = (Throwable) causeConstructor.newInstance(message, cause);
} else if (messageConstructor != null) {
ex = (Throwable) messageConstructor.newInstance(message);
} else if (defaultConstructor != null) {
ex = (Throwable) defaultConstructor.newInstance();
}
if (ex == null) {
ex = new Exception(message, cause);
}
} catch (Exception e) {
throw new JSONException("create instance error", e);
}
}
if (stackTrace != null) {
ex.setStackTrace(stackTrace);
}
if (otherValues != null) {
JavaBeanDeserializer exBeanDeser = null;
if (exClass != null) {
if (exClass == clazz) {
exBeanDeser = this;
} else {
ObjectDeserializer exDeser = parser.config.getDeserializer(exClass);
if (exDeser instanceof JavaBeanDeserializer) {
exBeanDeser = (JavaBeanDeserializer) exDeser;
}
}
}
if (exBeanDeser != null) {
for (Map.Entry<String, Object> entry : otherValues.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
FieldDeserializer fieldDeserializer = exBeanDeser.getFieldDeserializer(key);
if (fieldDeserializer != null) {
fieldDeserializer.setValue(ex, value);
}
}
}
}
return (T) ex;
}
}
package com.sobot.fastjson.parser.deserializer;
/**
*
* @author wenshao[szujobs@hotmail.com]
* @since 1.2.9 back port to 1.1.49.android
*/
public interface ExtraProcessable {
void processExtra(String key, Object value);
}
package com.sobot.fastjson.parser.deserializer;
/**
*
* @author wenshao[szujobs@hotmail.com]
* @since 1.1.34
*/
public interface ExtraProcessor extends ParseProcess {
void processExtra(Object object, String key, Object value);
}
package com.sobot.fastjson.parser.deserializer;
import java.lang.reflect.Type;
/**
* @author wenshao[szujobs@hotmail.com]
* @since 1.1.34
*/
public interface ExtraTypeProvider extends ParseProcess {
Type getExtraType(Object object, String key);
}
package com.sobot.fastjson.parser.deserializer;
import com.sobot.fastjson.JSONException;
import com.sobot.fastjson.parser.DefaultJSONParser;
import com.sobot.fastjson.util.FieldInfo;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
public abstract class FieldDeserializer {
public final FieldInfo fieldInfo;
public final Class<?> clazz;
protected Enum[] enums;
protected long[] enumNameHashCodes;
public FieldDeserializer(Class<?> clazz, FieldInfo fieldInfo, int fastMatchToken){
this.clazz = clazz;
this.fieldInfo = fieldInfo;
if (fieldInfo == null) {
return;
}
Class fieldClass = fieldInfo.fieldClass;
if (fieldClass.isEnum()) {
Enum[] enums = (Enum[]) fieldClass.getEnumConstants();
long[] enumNameHashCodes = new long[enums.length];
this.enumNameHashCodes = new long[enums.length];
for (int i = 0; i < enums.length; ++i) {
String name = enums[i].name();
long hash = 0xcbf29ce484222325L;
for (int j = 0; j < name.length(); ++j) {
char ch = name.charAt(j);
hash ^= ch;
hash *= 0x100000001b3L;
}
enumNameHashCodes[i] = hash;
this.enumNameHashCodes[i] = hash;
}
Arrays.sort(this.enumNameHashCodes);
this.enums = new Enum[enums.length];
for (int i = 0; i < this.enumNameHashCodes.length; ++i) {
for (int j = 0; j < enumNameHashCodes.length; ++j) {
if (this.enumNameHashCodes[i] == enumNameHashCodes[j]) {
this.enums[i] = enums[j];
break;
}
}
}
}
}
public Enum getEnumByHashCode(long hashCode) {
if (enums == null) {
return null;
}
int enumIndex = Arrays.binarySearch(this.enumNameHashCodes, hashCode);
if (enumIndex < 0) {
return null;
}
return enums[enumIndex];
}
public abstract void parseField(DefaultJSONParser parser, Object object, Type objectType,
Map<String, Object> fieldValues);
public void setValue(Object object, int value) throws IllegalAccessException {
fieldInfo.field.setInt(object, value);
}
public void setValue(Object object, long value) throws IllegalAccessException {
fieldInfo.field.setLong(object, value);
}
public void setValue(Object object, float value) throws IllegalAccessException {
fieldInfo.field.setFloat(object, value);
}
public void setValue(Object object, double value) throws IllegalAccessException {
fieldInfo.field.setDouble(object, value);
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public void setValue(Object object, Object value) {
if (value == null) {
Class<?> fieldClass = fieldInfo.fieldClass;
if (fieldClass.isPrimitive()) {
return;
}
}
final Field field = fieldInfo.field;
final Method method = fieldInfo.method;
try {
if (fieldInfo.fieldAccess) {
if (fieldInfo.getOnly) {
if (Map.class.isAssignableFrom(fieldInfo.fieldClass)) {
Map map = (Map) field.get(object);
if (map != null) {
map.putAll((Map) value);
}
} else {
Collection collection = (Collection) field.get(object);
if (collection != null) {
collection.addAll((Collection) value);
}
}
} else {
field.set(object, value);
}
} else {
if (fieldInfo.getOnly) {
if (Map.class.isAssignableFrom(fieldInfo.fieldClass)) {
Map map = (Map) method.invoke(object);
if (map != null) {
map.putAll((Map) value);
}
} else {
Collection collection = (Collection) method.invoke(object);
if (collection != null) {
collection.addAll((Collection) value);
}
}
} else {
method.invoke(object, value);
}
}
} catch (Exception e) {
throw new JSONException("set property error, " + fieldInfo.name, e);
}
}
}
package com.sobot.fastjson.parser.deserializer;
import java.lang.reflect.Type;
public interface FieldTypeResolver extends ParseProcess {
Type resolve(Object object, String fieldName);
}
package com.sobot.fastjson.parser.deserializer;
import com.sobot.fastjson.parser.DefaultJSONParser;
import java.lang.reflect.Type;
public interface ObjectDeserializer {
<T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName);
}
package com.sobot.fastjson.parser.deserializer;
public interface ParseProcess {
}
package com.sobot.fastjson.serializer;
/**
* @since 1.1.35
*/
public abstract class AfterFilter implements SerializeFilter {
private static final ThreadLocal<JSONSerializer> serializerLocal = new ThreadLocal<JSONSerializer>();
private static final ThreadLocal<Character> seperatorLocal = new ThreadLocal<Character>();
private final static Character COMMA = Character.valueOf(',');
final char writeAfter(JSONSerializer serializer, Object object, char seperator) {
serializerLocal.set(serializer);
seperatorLocal.set(seperator);
writeAfter(object);
serializerLocal.set(null);
return seperatorLocal.get();
}
protected final void writeKeyValue(String key, Object value) {
JSONSerializer serializer = serializerLocal.get();
char seperator = seperatorLocal.get();
serializer.writeKeyValue(seperator, key, value);
if (seperator != ',') {
seperatorLocal.set(COMMA);
}
}
public abstract void writeAfter(Object object);
}
/*
* 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.sobot.fastjson.serializer;
import com.sobot.fastjson.JSON;
import com.sobot.fastjson.JSONArray;
import com.sobot.fastjson.parser.DefaultJSONParser;
import com.sobot.fastjson.parser.JSONLexer;
import com.sobot.fastjson.parser.JSONToken;
import com.sobot.fastjson.parser.deserializer.ObjectDeserializer;
import com.sobot.fastjson.util.TypeUtils;
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.Type;
/**
* @author wenshao[szujobs@hotmail.com]
*/
public final class ArrayCodec implements ObjectSerializer, ObjectDeserializer {
public static final ArrayCodec instance = new ArrayCodec();
private ArrayCodec(){
}
public final void write(JSONSerializer serializer, //
Object object, //
Object fieldName, //
Type fieldType //
) throws IOException {
SerializeWriter out = serializer.out;
Object[] array = (Object[]) object;
if (object == null) {
if ((out.features & SerializerFeature.WriteNullListAsEmpty.mask) != 0) {
out.write("[]");
} else {
out.writeNull();
}
return;
}
int size = array.length;
int end = size - 1;
if (end == -1) {
out.append("[]");
return;
}
SerialContext context = serializer.context;
serializer.setContext(context, object, fieldName, 0);
try {
Class<?> preClazz = null;
ObjectSerializer preWriter = null;
out.write('[');
if ((out.features & SerializerFeature.PrettyFormat.mask) != 0) {
serializer.incrementIndent();
serializer.println();
for (int i = 0; i < size; ++i) {
if (i != 0) {
out.write(',');
serializer.println();
}
serializer.write(array[i]);
}
serializer.decrementIdent();
serializer.println();
out.write(']');
return;
}
for (int i = 0; i < end; ++i) {
Object item = array[i];
if (item == null) {
out.append("null,");
} else {
if (serializer.references != null && serializer.references.containsKey(item)) {
serializer.writeReference(item);
} else {
Class<?> clazz = item.getClass();
if (clazz == preClazz) {
preWriter.write(serializer, item, null, null);
} else {
preClazz = clazz;
preWriter = serializer.config.get(clazz);
preWriter.write(serializer, item, null, null);
}
}
out.write(',');
}
}
Object item = array[end];
if (item == null) {
out.append("null]");
} else {
if (serializer.references != null && serializer.references.containsKey(item)) {
serializer.writeReference(item);
} else {
serializer.writeWithFieldName(item, end);
}
out.write(']');
}
} finally {
serializer.context = context;
}
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
final JSONLexer lexer = parser.lexer;
int token = lexer.token();
if (token == JSONToken.NULL) {
lexer.nextToken(JSONToken.COMMA);
return null;
}
if (type == char[].class) {
if (token == JSONToken.LITERAL_STRING) {
String val = lexer.stringVal();
lexer.nextToken(JSONToken.COMMA);
return (T) val.toCharArray();
}
if (token == JSONToken.LITERAL_INT) {
Number val = lexer.integerValue();
lexer.nextToken(JSONToken.COMMA);
return (T) val.toString().toCharArray();
}
Object value = parser.parse();
return (T) JSON.toJSONString(value).toCharArray();
}
if (token == JSONToken.LITERAL_STRING) {
byte[] bytes = lexer.bytesValue();
lexer.nextToken(JSONToken.COMMA);
return (T) bytes;
}
Class clazz = (Class) type;
Class componentClass = clazz.getComponentType();
JSONArray array = new JSONArray();
parser.parseArray(componentClass, array, fieldName);
return (T) toObjectArray(parser, componentClass, array);
}
@SuppressWarnings("unchecked")
private <T> T toObjectArray(DefaultJSONParser parser, Class<?> componentType, JSONArray array) {
if (array == null) {
return null;
}
int size = array.size();
Object objArray = Array.newInstance(componentType, size);
for (int i = 0; i < size; ++i) {
Object value = array.get(i);
if (value == array) {
Array.set(objArray, i, objArray);
continue;
}
Object element;
if (componentType.isArray()) {
if (componentType.isInstance(value)) {
element = value;
} else {
element = toObjectArray(parser, componentType, (JSONArray) value);
}
} else {
element = TypeUtils.cast(value, componentType, parser.config);
}
Array.set(objArray, i, element);
}
array.setRelatedArray(objArray);
array.setComponentType(componentType);
return (T) objArray;
}
}
/*
* 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.sobot.fastjson.serializer;
import java.io.IOException;
import java.lang.reflect.Type;
/**
* @author wenshao[szujobs@hotmail.com]
*/
final class ArraySerializer implements ObjectSerializer {
private final Class<?> componentType;
private final ObjectSerializer compObjectSerializer;
ArraySerializer(Class<?> componentType, ObjectSerializer compObjectSerializer){
this.componentType = componentType;
this.compObjectSerializer = compObjectSerializer;
}
public final void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType)
throws IOException {
SerializeWriter out = serializer.out;
if (object == null) {
if ((out.features & SerializerFeature.WriteNullListAsEmpty.mask) != 0) {
out.write("[]");
} else {
out.writeNull();
}
return;
}
if (object instanceof boolean[]) {
boolean[] array = (boolean[]) object;
out.write('[');
for (int i = 0; i < array.length; ++i) {
if (i != 0) {
out.write(',');
}
out.write(array[i]);
}
out.write(']');
return;
}
if (object instanceof byte[]) {
byte[] array = (byte[]) object;
out.writeByteArray(array);
return;
}
if (object instanceof char[]) {
char[] chars = (char[]) object;
out.writeString(new String(chars));
return;
}
if (object instanceof double[]) {
double[] array = (double[]) object;
int size = array.length;
int end = size - 1;
if (end == -1) {
out.append("[]");
return;
}
out.write('[');
for (int i = 0; i < end; ++i) {
double item = array[i];
if (Double.isNaN(item)) {
out.writeNull();
} else {
out.append(Double.toString(item));
}
out.write(',');
}
double item = array[end];
if (Double.isNaN(item)) {
out.writeNull();
} else {
out.append(Double.toString(item));
}
out.write(']');
return;
}
if (object instanceof float[]) {
float[] array = (float[]) object;
int size = array.length;
int end = size - 1;
if (end == -1) {
out.append("[]");
return;
}
out.write('[');
for (int i = 0; i < end; ++i) {
float item = array[i];
if (Float.isNaN(item)) {
out.writeNull();
} else {
out.append(Float.toString(item));
}
out.write(',');
}
float item = array[end];
if (Float.isNaN(item)) {
out.writeNull();
} else {
out.append(Float.toString(item));
}
out.write(']');
return;
}
if (object instanceof int[]) {
int[] array = (int[]) object;
out.write('[');
for (int i = 0; i < array.length; ++i) {
if (i != 0) {
out.write(',');
}
out.writeInt(array[i]);
}
out.write(']');
return;
}
if (object instanceof long[]) {
long[] array = (long[]) object;
out.write('[');
for (int i = 0; i < array.length; ++i) {
if (i != 0) {
out.write(',');
}
out.writeLong(array[i]);
}
out.write(']');
return;
}
if (object instanceof short[]) {
short[] array = (short[]) object;
out.write('[');
for (int i = 0; i < array.length; ++i) {
if (i != 0) {
out.write(',');
}
out.writeInt(array[i]);
}
out.write(']');
return;
}
Object[] array = (Object[]) object;
int size = array.length;
SerialContext context = serializer.context;
serializer.setContext(context, object, fieldName, 0);
try {
out.write('[');
for (int i = 0; i < size; ++i) {
if (i != 0) {
out.write(',');
}
Object item = array[i];
if (item == null) {
if (out.isEnabled(SerializerFeature.WriteNullStringAsEmpty) && object instanceof String[]) {
out.writeString("");
} else {
out.append("null");
}
} else if (item.getClass() == componentType) {
compObjectSerializer.write(serializer, item, i, null);
} else {
ObjectSerializer itemSerializer = serializer.config.get(item.getClass());
itemSerializer.write(serializer, item, i, null);
}
}
out.write(']');
} finally {
serializer.context = context;
}
}
}
package com.sobot.fastjson.serializer;
public abstract class BeforeFilter implements SerializeFilter {
private static final ThreadLocal<JSONSerializer> serializerLocal = new ThreadLocal<JSONSerializer>();
private static final ThreadLocal<Character> seperatorLocal = new ThreadLocal<Character>();
private final static Character COMMA = Character.valueOf(',');
final char writeBefore(JSONSerializer serializer, Object object, char seperator) {
serializerLocal.set(serializer);
seperatorLocal.set(seperator);
writeBefore(object);
serializerLocal.set(null);
return seperatorLocal.get();
}
protected final void writeKeyValue(String key, Object value) {
JSONSerializer serializer = serializerLocal.get();
char seperator = seperatorLocal.get();
serializer.writeKeyValue(seperator, key, value);
if (seperator != ',') {
seperatorLocal.set(COMMA);
}
}
public abstract void writeBefore(Object object);
}
/*
* 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.sobot.fastjson.serializer;
import com.sobot.fastjson.parser.DefaultJSONParser;
import com.sobot.fastjson.parser.JSONLexer;
import com.sobot.fastjson.parser.JSONToken;
import com.sobot.fastjson.parser.deserializer.ObjectDeserializer;
import com.sobot.fastjson.util.TypeUtils;
import java.io.IOException;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
/**
* @author wenshao[szujobs@hotmail.com]
*/
public class BigDecimalCodec implements ObjectSerializer, ObjectDeserializer {
public final static BigDecimalCodec instance = new BigDecimalCodec();
private BigDecimalCodec() {
}
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType) throws IOException {
SerializeWriter out = serializer.out;
if (object == null) {
if ((out.features & SerializerFeature.WriteNullNumberAsZero.mask) != 0) {
out.write('0');
} else {
out.writeNull();
}
return;
}
if (object instanceof BigInteger) {
BigInteger val = (BigInteger) object;
out.write(val.toString());
return;
}
BigDecimal val = (BigDecimal) object;
out.write(val.toString());
if ((out.features & SerializerFeature.WriteClassName.mask) != 0 && fieldType != BigDecimal.class && val.scale() == 0) {
out.write('.');
}
}
@SuppressWarnings("unchecked")
public <T> T deserialze(DefaultJSONParser parser, Type clazz, Object fieldName) {
final JSONLexer lexer = parser.lexer;
int token = lexer.token();
if (token == JSONToken.LITERAL_INT) {
if (clazz == BigInteger.class) {
String val = lexer.numberString();
lexer.nextToken(JSONToken.COMMA);
return (T) new BigInteger(val, 10);
} else {
BigDecimal decimal = lexer.decimalValue();
lexer.nextToken(JSONToken.COMMA);
return (T) decimal;
}
}
if (token == JSONToken.LITERAL_FLOAT) {
BigDecimal val = lexer.decimalValue();
lexer.nextToken(JSONToken.COMMA);
if (clazz == BigInteger.class) {
int scale = val.scale();
if (scale < -100 || scale > 100) {
throw new NumberFormatException();
}
return (T) val.toBigInteger();
} else {
return (T) val;
}
}
Object value = parser.parse();
if (value == null) {
return null;
}
if (clazz == BigInteger.class) {
return (T) TypeUtils.castToBigInteger(value);
}
return (T) TypeUtils.castToBigDecimal(value);
}
}
/*
* 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.sobot.fastjson.serializer;
import com.sobot.fastjson.parser.DefaultJSONParser;
import com.sobot.fastjson.parser.JSONLexer;
import com.sobot.fastjson.parser.JSONToken;
import com.sobot.fastjson.parser.deserializer.ObjectDeserializer;
import com.sobot.fastjson.util.TypeUtils;
import java.io.IOException;
import java.lang.reflect.Type;
/**
* @author wenshao[szujobs@hotmail.com]
*/
public final class BooleanCodec implements ObjectSerializer, ObjectDeserializer {
public final static BooleanCodec instance = new BooleanCodec();
private BooleanCodec() {
}
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType) throws IOException {
SerializeWriter out = serializer.out;
Boolean value = (Boolean) object;
if (value == null) {
if ((out.features & SerializerFeature.WriteNullBooleanAsFalse.mask) != 0) {
out.write("false");
} else {
out.writeNull();
}
return;
}
if (value.booleanValue()) {
out.write("true");
} else {
out.write("false");
}
}
@SuppressWarnings("unchecked")
public <T> T deserialze(DefaultJSONParser parser, Type clazz, Object fieldName) {
final JSONLexer lexer = parser.lexer;
Boolean boolObj;
int token = lexer.token();
if (token == JSONToken.TRUE) {
lexer.nextToken(JSONToken.COMMA);
boolObj = Boolean.TRUE;
} else if (token == JSONToken.FALSE) {
lexer.nextToken(JSONToken.COMMA);
boolObj = Boolean.FALSE;
} else if (token == JSONToken.LITERAL_INT) {
int intValue = lexer.intValue();
lexer.nextToken(JSONToken.COMMA);
if (intValue == 1) {
boolObj = Boolean.TRUE;
} else {
boolObj = Boolean.FALSE;
}
} else {
Object value = parser.parse();
if (value == null) {
return null;
}
boolObj = TypeUtils.castToBoolean(value);
}
return (T) boolObj;
}
}
/*
* 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.sobot.fastjson.serializer;
import com.sobot.fastjson.JSONArray;
import com.sobot.fastjson.JSONException;
import com.sobot.fastjson.parser.DefaultJSONParser;
import com.sobot.fastjson.parser.JSONToken;
import com.sobot.fastjson.parser.deserializer.ObjectDeserializer;
import com.sobot.fastjson.util.TypeUtils;
import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.AbstractCollection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.TreeSet;
/**
* @author wenshao[szujobs@hotmail.com]
*/
public class CollectionCodec implements ObjectSerializer, ObjectDeserializer {
public final static CollectionCodec instance = new CollectionCodec();
private CollectionCodec() {
}
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType) throws IOException {
SerializeWriter out = serializer.out;
if (object == null) {
if ((out.features & SerializerFeature.WriteNullListAsEmpty.mask) != 0) {
out.write("[]");
} else {
out.writeNull();
}
return;
}
Type elementType = null;
if ((out.features & SerializerFeature.WriteClassName.mask) != 0) {
elementType = TypeUtils.getCollectionItemType(fieldType);
}
Collection<?> collection = (Collection<?>) object;
SerialContext context = serializer.context;
serializer.setContext(context, object, fieldName, 0);
if ((out.features & SerializerFeature.WriteClassName.mask) != 0) {
if (HashSet.class == collection.getClass()) {
out.append("Set");
} else if (TreeSet.class == collection.getClass()) {
out.append("TreeSet");
}
}
try {
int i = 0;
out.write('[');
for (Object item : collection) {
if (i++ != 0) {
out.write(',');
}
if (item == null) {
out.writeNull();
continue;
}
Class<?> clazz = item.getClass();
if (clazz == Integer.class) {
out.writeInt(((Integer) item).intValue());
continue;
}
if (clazz == Long.class) {
out.writeLong(((Long) item).longValue());
if ((out.features & SerializerFeature.WriteClassName.mask) != 0) {
out.write('L');
}
continue;
}
ObjectSerializer itemSerializer = serializer.config.get(clazz);
itemSerializer.write(serializer, item, i - 1, elementType);
}
out.write(']');
} finally {
serializer.context = context;
}
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
if (parser.lexer.token() == JSONToken.NULL) {
parser.lexer.nextToken(JSONToken.COMMA);
return null;
}
if (type == JSONArray.class) {
JSONArray array = new JSONArray();
parser.parseArray(array);
return (T) array;
}
Class<?> rawClass; //= getRawClass(type);
for (Type t = type;;) {
if (t instanceof Class<?>) {
rawClass = (Class<?>) t;
break;
} else if (t instanceof ParameterizedType) {
t = ((ParameterizedType) t).getRawType();
} else {
throw new JSONException("TODO");
}
}
Collection list;
if (rawClass == AbstractCollection.class //
|| rawClass == Collection.class) {
list = new ArrayList();
} else if (rawClass.isAssignableFrom(HashSet.class)) {
list = new HashSet();
} else if (rawClass.isAssignableFrom(LinkedHashSet.class)) {
list = new LinkedHashSet();
} else if (rawClass.isAssignableFrom(TreeSet.class)) {
list = new TreeSet();
} else if (rawClass.isAssignableFrom(ArrayList.class)) {
list = new ArrayList();
} else if (rawClass.isAssignableFrom(EnumSet.class)) {
Type itemType;
if (type instanceof ParameterizedType) {
itemType = ((ParameterizedType) type).getActualTypeArguments()[0];
} else {
itemType = Object.class;
}
list = EnumSet.noneOf((Class<Enum>)itemType);
} else {
try {
list = (Collection) rawClass.newInstance();
} catch (Exception e) {
throw new JSONException("create instane error, class " + rawClass.getName());
}
}
Type itemType = TypeUtils.getCollectionItemType(type);
parser.parseArray(itemType, list, fieldName);
return (T) list;
}
}
/*
* 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.sobot.fastjson.serializer;
import java.io.IOException;
import java.lang.reflect.Type;
/**
* @author wenshao[szujobs@hotmail.com]
*/
class EnumSerializer implements ObjectSerializer {
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType) throws IOException {
SerializeWriter out = serializer.out;
if ((out.features & SerializerFeature.WriteEnumUsingToString.mask) != 0) {
Enum<?> e = (Enum<?>) object;
String name = e.toString();
boolean userSingleQuote = (out.features & SerializerFeature.UseSingleQuotes.mask) != 0;
if (userSingleQuote) {
out.writeStringWithSingleQuote(name);
} else {
out.writeStringWithDoubleQuote(name, (char) 0, false);
}
} else {
Enum<?> e = (Enum<?>) object;
out.writeInt(e.ordinal());
}
}
}
/*
* 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.sobot.fastjson.serializer;
import com.sobot.fastjson.JSONException;
import com.sobot.fastjson.annotation.JSONField;
import com.sobot.fastjson.util.FieldInfo;
import java.io.IOException;
import java.lang.reflect.Member;
import java.util.Collection;
/**
* @author wenshao[szujobs@hotmail.com]
*/
public final class FieldSerializer implements Comparable<FieldSerializer> {
public final FieldInfo fieldInfo;
protected final boolean writeNull;
protected final int features;
protected final String format;
protected char[] name_chars;
private RuntimeSerializerInfo runtimeInfo;
public FieldSerializer(FieldInfo fieldInfo){
this.fieldInfo = fieldInfo;
boolean writeNull = false;
JSONField annotation = fieldInfo.getAnnotation();
String format = null;
if (annotation != null) {
for (SerializerFeature feature : annotation.serialzeFeatures()) {
if (feature == SerializerFeature.WriteMapNullValue) {
writeNull = true;
}
}
format = annotation.format();
format = format.trim();
if (format.length() == 0) {
format = null;
}
features = SerializerFeature.of(annotation.serialzeFeatures());
} else {
features = 0;
}
this.writeNull = writeNull;
this.format = format;
String name = fieldInfo.name;
int nameLen = name.length();
name_chars = new char[nameLen + 3];
name.getChars(0, name.length(), name_chars, 1);
name_chars[0] = '"';
name_chars[nameLen + 1] = '"';
name_chars[nameLen + 2] = ':';
}
public void writePrefix(JSONSerializer serializer) throws IOException {
SerializeWriter out = serializer.out;
final int featurs = out.features;
if ((featurs & SerializerFeature.QuoteFieldNames.mask) != 0) {
if ((featurs & SerializerFeature.UseSingleQuotes.mask) != 0) {
out.writeFieldName(fieldInfo.name, true);
} else {
out.write(name_chars, 0, name_chars.length);
}
} else {
out.writeFieldName(fieldInfo.name, true);
}
}
public Object getPropertyValue(Object object) throws Exception {
try {
return fieldInfo.get(object);
} catch (Exception ex) {
Member member = fieldInfo.method != null ? //
fieldInfo.method //
: fieldInfo.field;
String qualifiedName = member.getDeclaringClass().getName() + "." + member.getName();
throw new JSONException("get property error。 " + qualifiedName, ex);
}
}
public void writeValue(JSONSerializer serializer, Object propertyValue) throws Exception {
if (format != null) {
serializer.writeWithFormat(propertyValue, format);
return;
}
if (runtimeInfo == null) {
Class<?> runtimeFieldClass;
if (propertyValue == null) {
runtimeFieldClass = this.fieldInfo.fieldClass;
} else {
runtimeFieldClass = propertyValue.getClass();
}
ObjectSerializer fieldSerializer = serializer.config.get(runtimeFieldClass);
runtimeInfo = new RuntimeSerializerInfo(fieldSerializer, runtimeFieldClass);
}
final RuntimeSerializerInfo runtimeInfo = this.runtimeInfo;
if (propertyValue == null) {
if ((features & SerializerFeature.WriteNullNumberAsZero.mask) != 0 //
&& Number.class.isAssignableFrom(runtimeInfo.runtimeFieldClass)) {
serializer.out.write('0');
return;
} else if ((features & SerializerFeature.WriteNullBooleanAsFalse.mask) != 0 //
&& Boolean.class == runtimeInfo.runtimeFieldClass) {
serializer.out.write("false");
return;
} else if ((features & SerializerFeature.WriteNullListAsEmpty.mask) != 0 //
&& Collection.class.isAssignableFrom(runtimeInfo.runtimeFieldClass)) {
serializer.out.write("[]");
return;
}
runtimeInfo.fieldSerializer.write(serializer, null, fieldInfo.name, runtimeInfo.runtimeFieldClass);
return;
}
Class<?> valueClass = propertyValue.getClass();
if (valueClass == runtimeInfo.runtimeFieldClass) {
runtimeInfo.fieldSerializer.write(serializer, propertyValue, fieldInfo.name, fieldInfo.fieldType);
return;
}
ObjectSerializer valueSerializer = serializer.config.get(valueClass);
valueSerializer.write(serializer, propertyValue, fieldInfo.name, fieldInfo.fieldType);
}
static class RuntimeSerializerInfo {
ObjectSerializer fieldSerializer;
Class<?> runtimeFieldClass;
public RuntimeSerializerInfo(ObjectSerializer fieldSerializer, Class<?> runtimeFieldClass){
this.fieldSerializer = fieldSerializer;
this.runtimeFieldClass = runtimeFieldClass;
}
}
public int compareTo(FieldSerializer o) {
return this.fieldInfo.compareTo(o.fieldInfo);
}
}
/*
* 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.sobot.fastjson.serializer;
import com.sobot.fastjson.JSONException;
import com.sobot.fastjson.parser.DefaultJSONParser;
import com.sobot.fastjson.parser.JSONLexer;
import com.sobot.fastjson.parser.JSONToken;
import com.sobot.fastjson.parser.deserializer.ObjectDeserializer;
import com.sobot.fastjson.util.TypeUtils;
import java.io.IOException;
import java.lang.reflect.Type;
import java.math.BigDecimal;
/**
* @author wenshao[szujobs@hotmail.com]
*/
public final class IntegerCodec implements ObjectSerializer, ObjectDeserializer {
public static IntegerCodec instance = new IntegerCodec();
private IntegerCodec() {
}
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType) throws IOException {
SerializeWriter out = serializer.out;
Number value = (Number) object;
if (value == null) {
if ((out.features & SerializerFeature.WriteNullNumberAsZero.mask) != 0) {
out.write('0');
} else {
out.writeNull();
}
return;
}
if (object instanceof Long) {
out.writeLong(value.longValue());
} else {
out.writeInt(value.intValue());
}
if ((out.features & SerializerFeature.WriteClassName.mask) != 0) {
Class<?> clazz = value.getClass();
if (clazz == Byte.class) {
out.write('B');
} else if (clazz == Short.class) {
out.write('S');
} else if (clazz == Long.class) {
long longValue = value.longValue();
if (longValue <= Integer.MAX_VALUE && longValue >= Integer.MIN_VALUE) {
if (fieldType != Long.class) {
out.write('L');
}
}
}
}
}
@SuppressWarnings("unchecked")
public <T> T deserialze(DefaultJSONParser parser, Type clazz, Object fieldName) {
final JSONLexer lexer = parser.lexer;
int token = lexer.token();
if (token == JSONToken.NULL) {
lexer.nextToken(JSONToken.COMMA);
return null;
}
Number intObj;
if (token == JSONToken.LITERAL_INT) {
if (clazz == long.class || clazz == Long.class) {
long longValue = lexer.longValue();
intObj = Long.valueOf(longValue);
} else {
try {
int val = lexer.intValue();
intObj = Integer.valueOf(val);
} catch (NumberFormatException ex) {
throw new JSONException("int value overflow, field : " + fieldName, ex);
}
}
lexer.nextToken(JSONToken.COMMA);
} else if (token == JSONToken.LITERAL_FLOAT) {
BigDecimal decimalValue = lexer.decimalValue();
lexer.nextToken(JSONToken.COMMA);
if (clazz == long.class || clazz == Long.class) {
intObj = Long.valueOf(decimalValue.longValueExact());
} else {
intObj = Integer.valueOf(decimalValue.intValueExact());
}
} else {
Object value = parser.parse();
try {
if (clazz == long.class || clazz == Long.class) {
intObj = TypeUtils.castToLong(value);
} else {
intObj = TypeUtils.castToInt(value);
}
} catch (Exception ex) {
throw new JSONException("cast error, field : " + fieldName + ", value " + value, ex);
}
}
return (T) intObj;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment