Merge branch 'master' into master

This commit is contained in:
inder123 2018-05-09 13:11:43 -07:00 committed by GitHub
commit 3547420885
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 641 additions and 138 deletions

4
.gitignore vendored
View File

@ -13,4 +13,8 @@ release.properties
*.iws
classes
.gradle
local.properties
build
.DS_Store

View File

@ -1,6 +1,17 @@
Change Log
==========
## Version 2.8.4
_2018-05-01_ [GitHub Diff](https://github.com/google/gson/compare/gson-parent-2.8.3...gson-parent-2.8.4)
* Added a new FieldNamingPolicy, `LOWER_CASE_WITH_DOTS` that mapps JSON name `someFieldName` to `some.field.name`
* Fixed issue https://github.com/google/gson/issues/1305 by removing compile/runtime dependency on `sun.misc.Unsafe`
## Version 2.8.3
_2018-04-27_ [GitHub Diff](https://github.com/google/gson/compare/gson-parent-2.8.2...gson-parent-2.8.3)
* Added a new API, `GsonBuilder.newBuilder()` that clones the current builder
* Preserving DateFormatter behavior on JDK 9
* Numerous other bugfixes
## Version 2.8.2
_2017-09-19_ [GitHub Diff](https://github.com/google/gson/compare/gson-parent-2.8.1...gson-parent-2.8.2)
* Introduced a new API, `JsonElement.deepCopy()`

View File

@ -20,7 +20,7 @@ There are a few open-source projects that can convert Java objects to JSON. Howe
* To use Gson in Android
```gradle
dependencies {
implementation 'com.google.code.gson:gson:2.8.2'
implementation 'com.google.code.gson:gson:2.8.4'
}
```
@ -30,7 +30,7 @@ dependencies {
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.2</version>
<version>2.8.4</version>
</dependency>
```

View File

@ -1,51 +1,19 @@
#Gson Release Process
# Gson Release Process
The following is a step-by-step procedure for releasing a new version of Google-Gson.
1. Go through all open bugs and identify which will be fixed in this release. Mark all others with an appropriate release tag. Identify duplicates, and close the bugs that will never be fixed. Fix all bugs for the release, and mark them fixed.
1. (obsolete step) Edit [`pom.xml`](pom.xml) and update the versions listed for Export-Package to the target version. Also add any new Java packages that have been introduced in Gson.
1. Ensure all changelists are code-reviewed and have +1
1. (obsolete step) Ensure that your `~/.m2/settings.xml` is configured properly (see steps below)
1. `cd gson` to the parent directory; ensure there are no open files and all changes are committed.
1. Run `mvn release:clean`
1. Do a dry run: `mvn release:prepare -DdryRun=true`
1. Start the release: `mvn release:prepare`
* Answer questions: usually the defaults are fine.
* This will do a full build, change version from `-SNAPSHOT` to the released version, commit and create the tags. It will then change the version to `-SNAPSHOT` for the next release.
1. Ensure you have defined `sonatype-nexus-staging` in your Maven `settings.xml` and run:
```bash
mvn -s /home/<username>/.m2/settings.xml release:perform
```
1. [Log in to Nexus repository manager](https://oss.sonatype.org/index.html#welcome) at Sonatype and close the staging repository for Gson. If you run into an error regarding missing signatures, you need to manually upload the artifacts using `mvn gpg:sign-and-deploy-file` for Gson binary, source and Javadoc jars.
```bash
cp -r ~/.m2/repository/com/google/code/gson/gson/1.7.2 /tmp
cd /tmp/1.7.2
mvn gpg:sign-and-deploy-file \
-Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ \
-DrepositoryId=sonatype-nexus-staging \
-DpomFile=gson-1.7.2.pom \
-Dfile=gson-1.7.2-javadoc.jar \
-Dclassifier=javadoc
mvn gpg:sign-and-deploy-file \
-Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ \
-DrepositoryId=sonatype-nexus-staging \
-DpomFile=gson-1.7.2.pom \
-Dfile=gson-1.7.2-sources.jar \
-Dclassifier=sources
mvn gpg:sign-and-deploy-file \
-Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ \
-DrepositoryId=sonatype-nexus-staging \
-DpomFile=gson-1.7.2.pom \
-Dfile=gson-1.7.2.jar
```
1. Close the Gson repository. Download and sanity check all downloads. Do not skip this step! Once you release the staging repository, there is no going back. It will get synced with Maven central and you will not be able to update or delete anything. Your only recourse will be to release a new version of Gson and hope that no one uses the old one.
* Answer questions: usually the defaults are fine.
* This will do a full build, change version from `-SNAPSHOT` to the released version, commit and create the tags. It will then change the version to `-SNAPSHOT` for the next release.
1. Complete the release: `mvn release:perform`
1. [Log in to Nexus repository manager](https://oss.sonatype.org/index.html#welcome) at Sonatype and close the staging repository for Gson.
1. Download and sanity check all downloads. Do not skip this step! Once you release the staging repository, there is no going back. It will get synced with Maven central and you will not be able to update or delete anything. Your only recourse will be to release a new version of Gson and hope that no one uses the old one.
1. Release the staging repository for Gson. Gson will now get synced to Maven central with-in the next hour. For issues consult [Sonatype Guide](https://docs.sonatype.org/display/Repository/Sonatype+OSS+Maven+Repository+Usage+Guide#SonatypeOSSMavenRepositoryUsageGuide-8.ReleaseIt).
1. Update the version in the [Using Gson with Maven2 page](https://github.com/google/gson/blob/master/UserGuide.md#TOC-Gson-With-Maven)
@ -58,16 +26,16 @@ The following is a step-by-step procedure for releasing a new version of Google-
This section was borrowed heavily from [Doclava release process](http://code.google.com/p/doclava/wiki/ProcessRelease).
1. Install/Configure GPG following this [guide](http://www.sonatype.com/people/2010/01/how-to-generate-pgp-signatures-with-maven/).
2. [Create encrypted passwords](http://maven.apache.org/guides/mini/guide-encryption.html).
3. Create `~/.m2/settings.xml` similar to as described in [Doclava release process](https://code.google.com/p/doclava/wiki/ProcessRelease).
4. Now for deploying a snapshot repository, use `mvn deploy`.
1. [Create encrypted passwords](http://maven.apache.org/guides/mini/guide-encryption.html).
1. Create `~/.m2/settings.xml` similar to as described in [Doclava release process](https://code.google.com/p/doclava/wiki/ProcessRelease).
1. Now for deploying a snapshot repository, use `mvn deploy`.
## Getting Maven Publishing Privileges
Based on [Gson group thread](https://groups.google.com/d/topic/google-gson/DHWJHVFpIBg/discussion):
1. [Sign up for a Sonatype account](https://docs.sonatype.org/display/Repository/Sonatype+OSS+Maven+Repository+Usage+Guide) following instructions under (2) on that page
2. Ask one of the existing members of the repository to create a JIRA ticket (Step 3 of above document) to add you to the publisher list.
1. Ask one of the existing members of the repository to create a JIRA ticket (Step 3 of above document) to add you to the publisher list.
## Running Benchmarks or Tests on Android

View File

@ -74,7 +74,7 @@ The Gson instance does not maintain any state while invoking Json operations. So
## <a name="TOC-Gson-With-Gradle"></a>Using Gson with Gradle/Android
```
dependencies {
compile 'com.google.code.gson:gson:2.8.2'
compile 'com.google.code.gson:gson:2.8.4'
}
```
## <a name="TOC-Gson-With-Maven"></a>Using Gson with Maven
@ -86,7 +86,7 @@ To use Gson with Maven2/3, you can use the Gson version available in Maven Centr
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.2</version>
<version>2.8.4</version>
<scope>compile</scope>
</dependency>
</dependencies>

12
build.gradle Normal file
View File

@ -0,0 +1,12 @@
buildscript {
repositories {
mavenCentral()
}
}
allprojects {
repositories {
mavenCentral()
}
}

0
examples/android-proguard-example/AndroidManifest.xml Executable file → Normal file
View File

BIN
gradle/wrapper/gradle-wrapper.jar vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,6 @@
#Fri Apr 27 17:41:01 PDT 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip

172
gradlew vendored Executable file
View File

@ -0,0 +1,172 @@
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

84
gradlew.bat vendored Executable file
View File

@ -0,0 +1,84 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

13
gson/build.gradle Normal file
View File

@ -0,0 +1,13 @@
apply plugin: 'java'
apply plugin: 'maven'
group = 'com.google.code.gson'
version = '2.8.4-SNAPSHOT'
sourceCompatibility = 1.6
targetCompatibility = 1.6
sourceSets.main.java.exclude("**/module-info.java")
dependencies {
testCompile "junit:junit:4.12"
}

View File

@ -4,7 +4,7 @@
<parent>
<groupId>com.google.code.gson</groupId>
<artifactId>gson-parent</artifactId>
<version>2.8.3-SNAPSHOT</version>
<version>2.8.5-SNAPSHOT</version>
</parent>
<artifactId>gson</artifactId>

View File

@ -27,12 +27,12 @@ import java.util.Date;
import java.util.List;
import java.util.Locale;
import com.google.gson.internal.JavaVersion;
import com.google.gson.internal.PreJava9DateFormatProvider;
import com.google.gson.internal.bind.util.ISO8601Utils;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import com.google.gson.util.VersionUtils;
/**
* This type adapter supports three subclasses of date: Date, Timestamp, and
@ -59,7 +59,7 @@ final class DefaultDateTypeAdapter extends TypeAdapter<Date> {
if (!Locale.getDefault().equals(Locale.US)) {
dateFormats.add(DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT));
}
if (VersionUtils.isJava9OrLater()) {
if (JavaVersion.isJava9OrLater()) {
dateFormats.add(PreJava9DateFormatProvider.getUSDateTimeFormat(DateFormat.DEFAULT, DateFormat.DEFAULT));
}
}
@ -78,7 +78,7 @@ final class DefaultDateTypeAdapter extends TypeAdapter<Date> {
if (!Locale.getDefault().equals(Locale.US)) {
dateFormats.add(DateFormat.getDateInstance(style));
}
if (VersionUtils.isJava9OrLater()) {
if (JavaVersion.isJava9OrLater()) {
dateFormats.add(PreJava9DateFormatProvider.getUSDateFormat(style));
}
}
@ -93,7 +93,7 @@ final class DefaultDateTypeAdapter extends TypeAdapter<Date> {
if (!Locale.getDefault().equals(Locale.US)) {
dateFormats.add(DateFormat.getDateTimeInstance(dateStyle, timeStyle));
}
if (VersionUtils.isJava9OrLater()) {
if (JavaVersion.isJava9OrLater()) {
dateFormats.add(PreJava9DateFormatProvider.getUSDateTimeFormat(dateStyle, timeStyle));
}
}

View File

@ -114,6 +114,29 @@ public enum FieldNamingPolicy implements FieldNamingStrategy {
@Override public String translateName(Field f) {
return separateCamelCase(f.getName(), "-").toLowerCase(Locale.ENGLISH);
}
},
/**
* Using this naming policy with Gson will modify the Java Field name from its camel cased
* form to a lower case field name where each word is separated by a dot (.).
*
* <p>Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":</p>
* <ul>
* <li>someFieldName ---> some.field.name</li>
* <li>_someFieldName ---> _some.field.name</li>
* <li>aStringField ---> a.string.field</li>
* <li>aURL ---> a.u.r.l</li>
* </ul>
* Using dots in JavaScript is not recommended since dot is also used for a member sign in
* expressions. This requires that a field named with dots is always accessed as a quoted
* property like {@code myobject['my.field']}. Accessing it as an object field
* {@code myobject.my.field} will result in an unintended javascript expression.
* @since 2.8
*/
LOWER_CASE_WITH_DOTS() {
@Override public String translateName(Field f) {
return separateCamelCase(f.getName(), ".").toLowerCase(Locale.ENGLISH);
}
};
/**

0
gson/src/main/java/com/google/gson/JsonNull.java Executable file → Normal file
View File

0
gson/src/main/java/com/google/gson/JsonParser.java Executable file → Normal file
View File

View File

@ -0,0 +1,90 @@
/*
* Copyright (C) 2017 The Gson authors
*
* 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.google.gson.internal;
/**
* Utility to check the major Java version of the current JVM.
*/
public final class JavaVersion {
// Oracle defines naming conventions at http://www.oracle.com/technetwork/java/javase/versioning-naming-139433.html
// However, many alternate implementations differ. For example, Debian used 9-debian as the version string
private static final int majorJavaVersion = determineMajorJavaVersion();
private static int determineMajorJavaVersion() {
String javaVersion = System.getProperty("java.version");
return getMajorJavaVersion(javaVersion);
}
// Visible for testing only
static int getMajorJavaVersion(String javaVersion) {
int version = parseDotted(javaVersion);
if (version == -1) {
version = extractBeginningInt(javaVersion);
}
if (version == -1) {
return 6; // Choose minimum supported JDK version as default
}
return version;
}
// Parses both legacy 1.8 style and newer 9.0.4 style
private static int parseDotted(String javaVersion) {
try {
String[] parts = javaVersion.split("[._]");
int firstVer = Integer.parseInt(parts[0]);
if (firstVer == 1 && parts.length > 1) {
return Integer.parseInt(parts[1]);
} else {
return firstVer;
}
} catch (NumberFormatException e) {
return -1;
}
}
private static int extractBeginningInt(String javaVersion) {
try {
StringBuilder num = new StringBuilder();
for (int i = 0; i < javaVersion.length(); ++i) {
char c = javaVersion.charAt(i);
if (Character.isDigit(c)) {
num.append(c);
} else {
break;
}
}
return Integer.parseInt(num.toString());
} catch (NumberFormatException e) {
return -1;
}
}
/**
* @return the major Java version, i.e. '8' for Java 1.8, '9' for Java 9 etc.
*/
public static int getMajorJavaVersion() {
return majorJavaVersion;
}
/**
* @return {@code true} if the application is running on Java 9 or later; and {@code false} otherwise.
*/
public static boolean isJava9OrLater() {
return majorJavaVersion >= 9;
}
}

View File

@ -20,13 +20,13 @@ import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.internal.JavaVersion;
import com.google.gson.internal.PreJava9DateFormatProvider;
import com.google.gson.internal.bind.util.ISO8601Utils;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import com.google.gson.util.VersionUtils;
import java.io.IOException;
import java.text.DateFormat;
@ -62,7 +62,7 @@ public final class DateTypeAdapter extends TypeAdapter<Date> {
if (!Locale.getDefault().equals(Locale.US)) {
dateFormats.add(DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT));
}
if (VersionUtils.isJava9OrLater()) {
if (JavaVersion.isJava9OrLater()) {
dateFormats.add(PreJava9DateFormatProvider.getUSDateTimeFormat(DateFormat.DEFAULT, DateFormat.DEFAULT));
}
}

View File

@ -25,12 +25,9 @@ import java.lang.reflect.AccessibleObject;
*/
final class PreJava9ReflectionAccessor extends ReflectionAccessor {
/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
@Override
public void makeAccessible(AccessibleObject ao) {
ao.setAccessible(true);
}
}

View File

@ -15,10 +15,10 @@
*/
package com.google.gson.internal.reflect;
import com.google.gson.util.VersionUtils;
import java.lang.reflect.AccessibleObject;
import com.google.gson.internal.JavaVersion;
/**
* Provides a replacement for {@link AccessibleObject#setAccessible(boolean)}, which may be used to
* avoid reflective access issues appeared in Java 9, like {@link java.lang.reflect.InaccessibleObjectException}
@ -33,7 +33,7 @@ import java.lang.reflect.AccessibleObject;
public abstract class ReflectionAccessor {
// the singleton instance, use getInstance() to obtain
private static final ReflectionAccessor instance = VersionUtils.getMajorJavaVersion() < 9 ? new PreJava9ReflectionAccessor() : new UnsafeReflectionAccessor();
private static final ReflectionAccessor instance = JavaVersion.getMajorJavaVersion() < 9 ? new PreJava9ReflectionAccessor() : new UnsafeReflectionAccessor();
/**
* Does the same as {@code ao.setAccessible(true)}, but never throws

View File

@ -15,10 +15,11 @@
*/
package com.google.gson.internal.reflect;
import sun.misc.Unsafe;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import com.google.gson.JsonIOException;
/**
* An implementation of {@link ReflectionAccessor} based on {@link Unsafe}.
@ -26,29 +27,51 @@ import java.lang.reflect.Field;
* NOTE: This implementation is designed for Java 9. Although it should work with earlier Java releases, it is better to
* use {@link PreJava9ReflectionAccessor} for them.
*/
@SuppressWarnings({"unchecked", "rawtypes"})
final class UnsafeReflectionAccessor extends ReflectionAccessor {
private final Unsafe theUnsafe = getUnsafeInstance();
private static Class unsafeClass;
private final Object theUnsafe = getUnsafeInstance();
private final Field overrideField = getOverrideField();
/**
* {@inheritDoc}
*/
/** {@inheritDoc} */
@Override
public void makeAccessible(AccessibleObject ao) {
if (theUnsafe != null && overrideField != null) {
long overrideOffset = theUnsafe.objectFieldOffset(overrideField);
theUnsafe.putBoolean(ao, overrideOffset, true);
boolean success = makeAccessibleWithUnsafe(ao);
if (!success) {
try {
// unsafe couldn't be found, so try using accessible anyway
ao.setAccessible(true);
} catch (SecurityException e) {
throw new JsonIOException("Gson couldn't modify fields for " + ao
+ "\nand sun.misc.Unsafe not found.\nEither write a custom type adapter,"
+ " or make fields accessible, or include sun.misc.Unsafe.", e);
}
}
}
private static Unsafe getUnsafeInstance() {
// Visible for testing only
boolean makeAccessibleWithUnsafe(AccessibleObject ao) {
if (theUnsafe != null && overrideField != null) {
try {
Method method = unsafeClass.getMethod("objectFieldOffset", Field.class);
long overrideOffset = (Long) method.invoke(theUnsafe, overrideField); // long overrideOffset = theUnsafe.objectFieldOffset(overrideField);
Method putBooleanMethod = unsafeClass.getMethod("putBoolean", Object.class, long.class, boolean.class);
putBooleanMethod.invoke(theUnsafe, ao, overrideOffset, true); // theUnsafe.putBoolean(ao, overrideOffset, true);
return true;
} catch (Exception ignored) { // do nothing
}
}
return false;
}
private static Object getUnsafeInstance() {
try {
Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
unsafeClass = Class.forName("sun.misc.Unsafe");
Field unsafeField = unsafeClass.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
return (Unsafe) unsafeField.get(null);
return unsafeField.get(null);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
@ -57,7 +80,6 @@ final class UnsafeReflectionAccessor extends ReflectionAccessor {
try {
return AccessibleObject.class.getDeclaredField("override");
} catch (NoSuchFieldException e) {
e.printStackTrace();
return null;
}
}

View File

@ -1,49 +0,0 @@
/*
* Copyright (C) 2017 The Gson authors
*
* 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.google.gson.util;
/**
* Utility to check the major Java version of the current JVM.
*/
public class VersionUtils {
private static final int majorJavaVersion = determineMajorJavaVersion();
private static int determineMajorJavaVersion() {
String[] parts = System.getProperty("java.version").split("[._]");
int firstVer = Integer.parseInt(parts[0]);
if (firstVer == 1 && parts.length > 1) {
return Integer.parseInt(parts[1]);
} else {
return firstVer;
}
}
/**
* @return the major Java version, i.e. '8' for Java 1.8, '9' for Java 9 etc.
*/
public static int getMajorJavaVersion() {
return majorJavaVersion;
}
/**
* @return {@code true} if the application is running on Java 9 or later; and {@code false} otherwise.
*/
public static boolean isJava9OrLater() {
return majorJavaVersion >= 9;
}
}

View File

@ -23,7 +23,8 @@ import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import com.google.gson.util.VersionUtils;
import com.google.gson.internal.JavaVersion;
import junit.framework.TestCase;
/**
@ -47,9 +48,9 @@ public class DefaultDateTypeAdapterTest extends TestCase {
Locale defaultLocale = Locale.getDefault();
Locale.setDefault(locale);
try {
String afterYearSep = VersionUtils.isJava9OrLater() ? ", " : " ";
String afterYearLongSep = VersionUtils.isJava9OrLater() ? " at " : " ";
String utcFull = VersionUtils.isJava9OrLater() ? "Coordinated Universal Time" : "UTC";
String afterYearSep = JavaVersion.isJava9OrLater() ? ", " : " ";
String afterYearLongSep = JavaVersion.isJava9OrLater() ? " at " : " ";
String utcFull = JavaVersion.isJava9OrLater() ? "Coordinated Universal Time" : "UTC";
assertFormatted(String.format("Jan 1, 1970%s12:00:00 AM", afterYearSep),
new DefaultDateTypeAdapter(Date.class));
assertFormatted("1/1/70", new DefaultDateTypeAdapter(Date.class, DateFormat.SHORT));
@ -75,7 +76,7 @@ public class DefaultDateTypeAdapterTest extends TestCase {
Locale defaultLocale = Locale.getDefault();
Locale.setDefault(Locale.FRANCE);
try {
String afterYearSep = VersionUtils.isJava9OrLater() ? " à " : " ";
String afterYearSep = JavaVersion.isJava9OrLater() ? " à " : " ";
assertParsed(String.format("1 janv. 1970%s00:00:00", afterYearSep),
new DefaultDateTypeAdapter(Date.class));
assertParsed("01/01/70", new DefaultDateTypeAdapter(Date.class, DateFormat.SHORT));
@ -87,7 +88,7 @@ public class DefaultDateTypeAdapterTest extends TestCase {
new DefaultDateTypeAdapter(DateFormat.MEDIUM, DateFormat.MEDIUM));
assertParsed(String.format("1 janvier 1970%s00:00:00 UTC", afterYearSep),
new DefaultDateTypeAdapter(DateFormat.LONG, DateFormat.LONG));
assertParsed(VersionUtils.isJava9OrLater() ?
assertParsed(JavaVersion.isJava9OrLater() ?
"jeudi 1 janvier 1970 à 00:00:00 Coordinated Universal Time" :
"jeudi 1 janvier 1970 00 h 00 UTC",
new DefaultDateTypeAdapter(DateFormat.FULL, DateFormat.FULL));
@ -127,7 +128,7 @@ public class DefaultDateTypeAdapterTest extends TestCase {
Locale defaultLocale = Locale.getDefault();
Locale.setDefault(Locale.US);
try {
String afterYearSep = VersionUtils.isJava9OrLater() ? ", " : " ";
String afterYearSep = JavaVersion.isJava9OrLater() ? ", " : " ";
assertFormatted(String.format("Dec 31, 1969%s4:00:00 PM", afterYearSep),
new DefaultDateTypeAdapter(Date.class));
assertParsed("Dec 31, 1969 4:00:00 PM", new DefaultDateTypeAdapter(Date.class));

View File

View File

View File

@ -27,6 +27,7 @@ import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSyntaxException;
import com.google.gson.TypeAdapter;
import com.google.gson.internal.JavaVersion;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
@ -56,7 +57,6 @@ import java.util.TimeZone;
import java.util.TreeSet;
import java.util.UUID;
import com.google.gson.util.VersionUtils;
import junit.framework.TestCase;
/**
@ -330,7 +330,7 @@ public class DefaultTypeAdaptersTest extends TestCase {
public void testDefaultDateSerialization() {
Date now = new Date(1315806903103L);
String json = gson.toJson(now);
if (VersionUtils.isJava9OrLater()) {
if (JavaVersion.isJava9OrLater()) {
assertEquals("\"Sep 11, 2011, 10:55:03 PM\"", json);
} else {
assertEquals("\"Sep 11, 2011 10:55:03 PM\"", json);
@ -375,7 +375,7 @@ public class DefaultTypeAdaptersTest extends TestCase {
public void testDefaultJavaSqlTimestampSerialization() {
Timestamp now = new java.sql.Timestamp(1259875082000L);
String json = gson.toJson(now);
if (VersionUtils.isJava9OrLater()) {
if (JavaVersion.isJava9OrLater()) {
assertEquals("\"Dec 3, 2009, 1:18:02 PM\"", json);
} else {
assertEquals("\"Dec 3, 2009 1:18:02 PM\"", json);
@ -405,7 +405,7 @@ public class DefaultTypeAdaptersTest extends TestCase {
Gson gson = new GsonBuilder().create();
Date now = new Date(1315806903103L);
String json = gson.toJson(now);
if (VersionUtils.isJava9OrLater()) {
if (JavaVersion.isJava9OrLater()) {
assertEquals("\"Sep 11, 2011, 10:55:03 PM\"", json);
} else {
assertEquals("\"Sep 11, 2011 10:55:03 PM\"", json);

View File

View File

@ -63,6 +63,20 @@ public class NamingPolicyTest extends TestCase {
+ target.someConstantStringInstanceField + "\"}", gson.toJson(target));
}
public void testGsonWithLowerCaseDotPolicySerialization() {
Gson gson = builder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DOTS).create();
StringWrapper target = new StringWrapper("blah");
assertEquals("{\"some.constant.string.instance.field\":\""
+ target.someConstantStringInstanceField + "\"}", gson.toJson(target));
}
public void testGsonWithLowerCaseDotPolicyDeserialiation() {
Gson gson = builder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DOTS).create();
String target = "{\"some.constant.string.instance.field\":\"someValue\"}";
StringWrapper deserializedObject = gson.fromJson(target, StringWrapper.class);
assertEquals("someValue", deserializedObject.someConstantStringInstanceField);
}
public void testGsonWithLowerCaseDashPolicyDeserialiation() {
Gson gson = builder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DASHES).create();
String target = "{\"some-constant-string-instance-field\":\"someValue\"}";

View File

@ -33,6 +33,7 @@ import com.google.gson.common.TestTypes.ClassWithObjects;
import com.google.gson.common.TestTypes.ClassWithTransientFields;
import com.google.gson.common.TestTypes.Nested;
import com.google.gson.common.TestTypes.PrimitiveArray;
import com.google.gson.internal.JavaVersion;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.ArrayList;
@ -44,7 +45,6 @@ import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import com.google.gson.util.VersionUtils;
import junit.framework.TestCase;
/**
@ -484,7 +484,7 @@ public class ObjectTest extends TestCase {
public void testDateAsMapObjectField() {
HasObjectMap a = new HasObjectMap();
a.map.put("date", new Date(0));
if (VersionUtils.isJava9OrLater()) {
if (JavaVersion.isJava9OrLater()) {
assertEquals("{\"map\":{\"date\":\"Dec 31, 1969, 4:00:00 PM\"}}", gson.toJson(a));
} else {
assertEquals("{\"map\":{\"date\":\"Dec 31, 1969 4:00:00 PM\"}}", gson.toJson(a));

View File

@ -0,0 +1,81 @@
/*
* Copyright (C) 2017 The Gson authors
*
* 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.google.gson.internal;
import static org.junit.Assert.*;
import org.junit.Test;
import com.google.gson.internal.JavaVersion;
/**
* Unit and functional tests for {@link JavaVersion}
*
* @author Inderjeet Singh
*/
public class JavaVersionTest {
// Borrowed some of test strings from https://github.com/prestodb/presto/blob/master/presto-main/src/test/java/com/facebook/presto/server/TestJavaVersion.java
@Test
public void testGetMajorJavaVersion() {
JavaVersion.getMajorJavaVersion();
}
@Test
public void testJava6() {
assertEquals(6, JavaVersion.getMajorJavaVersion("1.6.0")); // http://www.oracle.com/technetwork/java/javase/version-6-141920.html
}
@Test
public void testJava7() {
assertEquals(7, JavaVersion.getMajorJavaVersion("1.7.0")); // http://www.oracle.com/technetwork/java/javase/jdk7-naming-418744.html
}
@Test
public void testJava8() {
assertEquals(8, JavaVersion.getMajorJavaVersion("1.8"));
assertEquals(8, JavaVersion.getMajorJavaVersion("1.8.0"));
assertEquals(8, JavaVersion.getMajorJavaVersion("1.8.0_131"));
assertEquals(8, JavaVersion.getMajorJavaVersion("1.8.0_60-ea"));
assertEquals(8, JavaVersion.getMajorJavaVersion("1.8.0_111-internal"));
// openjdk8 per https://github.com/AdoptOpenJDK/openjdk-build/issues/93
assertEquals(8, JavaVersion.getMajorJavaVersion("1.8.0-internal"));
assertEquals(8, JavaVersion.getMajorJavaVersion("1.8.0_131-adoptopenjdk"));
}
@Test
public void testJava9() {
// Legacy style
assertEquals(9, JavaVersion.getMajorJavaVersion("9.0.4")); // Oracle JDK 9
assertEquals(9, JavaVersion.getMajorJavaVersion("9-Debian")); // Debian as reported in https://github.com/google/gson/issues/1310
// New style
assertEquals(9, JavaVersion.getMajorJavaVersion("9-ea+19"));
assertEquals(9, JavaVersion.getMajorJavaVersion("9+100"));
assertEquals(9, JavaVersion.getMajorJavaVersion("9.0.1+20"));
assertEquals(9, JavaVersion.getMajorJavaVersion("9.1.1+20"));
}
@Test
public void testJava10() {
assertEquals(10, JavaVersion.getMajorJavaVersion("10.0.1")); // Oracle JDK 10.0.1
}
@Test
public void testUnknownVersionFormat() {
assertEquals(6, JavaVersion.getMajorJavaVersion("Java9")); // unknown format
}
}

View File

@ -0,0 +1,51 @@
/*
* Copyright (C) 2018 The Gson authors
*
* 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.google.gson.internal.reflect;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.lang.reflect.Field;
import org.junit.Test;
/**
* Unit tests for {@link UnsafeReflectionAccessor}
*
* @author Inderjeet Singh
*/
public class UnsafeReflectionAccessorTest {
@Test
public void testMakeAccessibleWithUnsafe() throws Exception {
UnsafeReflectionAccessor accessor = new UnsafeReflectionAccessor();
Field field = ClassWithPrivateFinalFields.class.getDeclaredField("a");
try {
boolean success = accessor.makeAccessibleWithUnsafe(field);
assertTrue(success);
} catch (Exception e) {
fail("Unsafe didn't work on the JDK");
}
}
@SuppressWarnings("unused")
private static final class ClassWithPrivateFinalFields {
private final String a;
public ClassWithPrivateFinalFields(String a) {
this.a = a;
}
}
}

View File

@ -11,7 +11,7 @@
<groupId>com.google.code.gson</groupId>
<artifactId>gson-parent</artifactId>
<version>2.8.3-SNAPSHOT</version>
<version>2.8.5-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Gson Parent</name>
@ -65,7 +65,9 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<excludes>**/module-info.java</excludes>
<excludes>
<exclude>**/module-info.java</exclude>
</excludes>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>

1
settings.gradle Normal file
View File

@ -0,0 +1 @@
include ':gson'