Compare commits
29 Commits
763e69a331
...
97aa219236
Author | SHA1 | Date |
---|---|---|
Johannes Frohnmeyer | 97aa219236 | |
Johannes Frohnmeyer | c2eb4aad9a | |
Johannes Frohnmeyer | 9409197165 | |
Marcono1234 | ff96296eea | |
Snowhite | dd6635dc61 | |
Johannes Frohnmeyer | f6e2bd0fb0 | |
Johannes Frohnmeyer | ded8d1c79f | |
Johannes Frohnmeyer | 8ec31281a7 | |
Johannes Frohnmeyer | e89fbec94a | |
Johannes Frohnmeyer | 67402b1acf | |
Johannes Frohnmeyer | f47c21fce7 | |
Johannes Frohnmeyer | ce02cb3bc1 | |
Johannes Frohnmeyer | 379b2563b2 | |
Johannes Frohnmeyer | 6a4f4329c0 | |
Johannes Frohnmeyer | 031f729d32 | |
Johannes Frohnmeyer | 41cafc0987 | |
Johannes Frohnmeyer | dc4e61ac7b | |
Johannes Frohnmeyer | ccf30b23e8 | |
Johannes Frohnmeyer | 66084ca5fb | |
Johannes Frohnmeyer | 35241fc7b2 | |
Johannes Frohnmeyer | 9d7fd891ee | |
tiegen | 9cf569698c | |
tiegen | 527c6cf0d0 | |
tiegen | e6b7da988a | |
tiegen | 8990169194 | |
tiegen | ccf8484915 | |
tiegen | 897452a3cf | |
tiegen | 08765cae4c | |
saddays | a0ea108c59 |
|
@ -20,3 +20,4 @@ build
|
|||
.DS_Store
|
||||
|
||||
examples/android-proguard-example/gen
|
||||
.attach_pid*
|
|
@ -0,0 +1,11 @@
|
|||
pipeline:
|
||||
maven:
|
||||
image: maven:3-openjdk-17
|
||||
environment:
|
||||
- MAVEN_OPTS=-Dhttps.protocols=TLSv1.2 -Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=WARN -Dorg.slf4j.simpleLogger.showDateTime=true -Djava.awt.headless=true
|
||||
- MAVEN_CLI_OPTS=--batch-mode --errors --fail-at-end --show-version -DinstallAtEnd=true -DdeployAtEnd=true
|
||||
commands:
|
||||
- mvn $MAVEN_CLI_OPTS deploy -s ci_settings.xml
|
||||
secrets: [ maven_token, maven_name ]
|
||||
when:
|
||||
- branch: master
|
105
CHANGELOG.md
105
CHANGELOG.md
|
@ -1,17 +1,38 @@
|
|||
Change Log
|
||||
==========
|
||||
|
||||
## Version 2.10
|
||||
|
||||
* Support for serializing and deserializing Java records, on Java ≥ 16. (https://github.com/google/gson/pull/2201)
|
||||
* Add `JsonArray.asList` and `JsonObject.asMap` view methods (https://github.com/google/gson/pull/2225)
|
||||
* Fix `TypeAdapterRuntimeTypeWrapper` not detecting reflective `TreeTypeAdapter` and `FutureTypeAdapter` (https://github.com/google/gson/pull/1787)
|
||||
* Improve `JsonReader.skipValue()` (https://github.com/google/gson/pull/2062)
|
||||
* Perform numeric conversion for primitive numeric type adapters (https://github.com/google/gson/pull/2158)
|
||||
* Add `Gson.fromJson(..., TypeToken)` overloads (https://github.com/google/gson/pull/1700)
|
||||
* Fix changes to `GsonBuilder` affecting existing `Gson` instances (https://github.com/google/gson/pull/1815)
|
||||
* Make `JsonElement` conversion methods more consistent and fix javadoc (https://github.com/google/gson/pull/2178)
|
||||
* Throw `UnsupportedOperationException` when `JsonWriter.jsonValue` is not supported (https://github.com/google/gson/pull/1651)
|
||||
* Disallow `JsonObject` `Entry.setValue(null)` (https://github.com/google/gson/pull/2167)
|
||||
* Fix `TypeAdapter.toJson` throwing AssertionError for custom IOException (https://github.com/google/gson/pull/2172)
|
||||
* Convert null to JsonNull for `JsonArray.set` (https://github.com/google/gson/pull/2170)
|
||||
* Fixed nullSafe usage. (https://github.com/google/gson/pull/1555)
|
||||
* Validate `TypeToken.getParameterized` arguments (https://github.com/google/gson/pull/2166)
|
||||
* Fix #1702: Gson.toJson creates CharSequence which does not implement toString (https://github.com/google/gson/pull/1703)
|
||||
* Prefer existing adapter for concurrent `Gson.getAdapter` calls (https://github.com/google/gson/pull/2153)
|
||||
* Improve `ArrayTypeAdapter` for `Object[]` (https://github.com/google/gson/pull/1716)
|
||||
* Improve `AppendableWriter` performance (https://github.com/google/gson/pull/1706)
|
||||
|
||||
## Version 2.9.1
|
||||
|
||||
* Make `Object` and `JsonElement` deserialization iterative rather than
|
||||
recursive (#1912)
|
||||
* Added parsing support for enum that has overridden toString() method (#1950)
|
||||
* Removed support for building Gson with Gradle (#2081)
|
||||
* Removed obsolete `codegen` hierarchy (#2099)
|
||||
* Add support for reflection access filter (#1905)
|
||||
* Improve `TypeToken` creation validation (#2072)
|
||||
* Add explicit support for `float` in `JsonWriter` (#2130, #2132)
|
||||
* Fail when parsing invalid local date (#2134)
|
||||
recursive (https://github.com/google/gson/pull/1912)
|
||||
* Added parsing support for enum that has overridden toString() method (https://github.com/google/gson/pull/1950)
|
||||
* Removed support for building Gson with Gradle (https://github.com/google/gson/pull/2081)
|
||||
* Removed obsolete `codegen` hierarchy (https://github.com/google/gson/pull/2099)
|
||||
* Add support for reflection access filter (https://github.com/google/gson/pull/1905)
|
||||
* Improve `TypeToken` creation validation (https://github.com/google/gson/pull/2072)
|
||||
* Add explicit support for `float` in `JsonWriter` (https://github.com/google/gson/pull/2130, https://github.com/google/gson/pull/2132)
|
||||
* Fail when parsing invalid local date (https://github.com/google/gson/pull/2134)
|
||||
|
||||
Also many small improvements to javadoc.
|
||||
|
||||
|
@ -19,52 +40,52 @@ Also many small improvements to javadoc.
|
|||
|
||||
**The minimum supported Java version changes from 6 to 7.**
|
||||
|
||||
* Change target Java version to 7 (#2043)
|
||||
* Put `module-info.class` into Multi-Release JAR folder (#2013)
|
||||
* Improve error message when abstract class cannot be constructed (#1814)
|
||||
* Support EnumMap deserialization (#2071)
|
||||
* Add LazilyParsedNumber default adapter (#2060)
|
||||
* Fix JsonReader.hasNext() returning true at end of document (#2061)
|
||||
* Change target Java version to 7 (https://github.com/google/gson/pull/2043)
|
||||
* Put `module-info.class` into Multi-Release JAR folder (https://github.com/google/gson/pull/2013)
|
||||
* Improve error message when abstract class cannot be constructed (https://github.com/google/gson/pull/1814)
|
||||
* Support EnumMap deserialization (https://github.com/google/gson/pull/2071)
|
||||
* Add LazilyParsedNumber default adapter (https://github.com/google/gson/pull/2060)
|
||||
* Fix JsonReader.hasNext() returning true at end of document (https://github.com/google/gson/pull/2061)
|
||||
* Remove Gradle build support. Build script was outdated and not actively
|
||||
maintained anymore (#2063)
|
||||
* Add `GsonBuilder.disableJdkUnsafe()` (#1904)
|
||||
* Add `UPPER_CASE_WITH_UNDERSCORES` in FieldNamingPolicy (#2024)
|
||||
* Fix failing to serialize Collection or Map with inaccessible constructor (#1902)
|
||||
* Improve TreeTypeAdapter thread-safety (#1976)
|
||||
* Fix `Gson.newJsonWriter` ignoring lenient and HTML-safe setting (#1989)
|
||||
* Delete unused LinkedHashTreeMap (#1992)
|
||||
* Make default adapters stricter; improve exception messages (#2000)
|
||||
* Fix `FieldNamingPolicy.upperCaseFirstLetter` uppercasing non-letter (#2004)
|
||||
maintained anymore (https://github.com/google/gson/pull/2063)
|
||||
* Add `GsonBuilder.disableJdkUnsafe()` (https://github.com/google/gson/pull/1904)
|
||||
* Add `UPPER_CASE_WITH_UNDERSCORES` in FieldNamingPolicy (https://github.com/google/gson/pull/2024)
|
||||
* Fix failing to serialize Collection or Map with inaccessible constructor (https://github.com/google/gson/pull/1902)
|
||||
* Improve TreeTypeAdapter thread-safety (https://github.com/google/gson/pull/1976)
|
||||
* Fix `Gson.newJsonWriter` ignoring lenient and HTML-safe setting (https://github.com/google/gson/pull/1989)
|
||||
* Delete unused LinkedHashTreeMap (https://github.com/google/gson/pull/1992)
|
||||
* Make default adapters stricter; improve exception messages (https://github.com/google/gson/pull/2000)
|
||||
* Fix `FieldNamingPolicy.upperCaseFirstLetter` uppercasing non-letter (https://github.com/google/gson/pull/2004)
|
||||
|
||||
## Version 2.8.9
|
||||
|
||||
* Make OSGi bundle's dependency on `sun.misc` optional (#1993).
|
||||
* Deprecate `Gson.excluder()` exposing internal `Excluder` class (#1986).
|
||||
* Prevent Java deserialization of internal classes (#1991).
|
||||
* Improve number strategy implementation (#1987).
|
||||
* Fix LongSerializationPolicy null handling being inconsistent with Gson (#1990).
|
||||
* Support arbitrary Number implementation for Object and Number deserialization (#1290).
|
||||
* Bump proguard-maven-plugin from 2.4.0 to 2.5.1 (#1980).
|
||||
* Don't exclude static local classes (#1969).
|
||||
* Fix `RuntimeTypeAdapterFactory` depending on internal `Streams` class (#1959).
|
||||
* Improve Maven build (#1964).
|
||||
* Make dependency on `java.sql` optional (#1707).
|
||||
* Make OSGi bundle's dependency on `sun.misc` optional (https://github.com/google/gson/pull/1993).
|
||||
* Deprecate `Gson.excluder()` exposing internal `Excluder` class (https://github.com/google/gson/pull/1986).
|
||||
* Prevent Java deserialization of internal classes (https://github.com/google/gson/pull/1991).
|
||||
* Improve number strategy implementation (https://github.com/google/gson/pull/1987).
|
||||
* Fix LongSerializationPolicy null handling being inconsistent with Gson (https://github.com/google/gson/pull/1990).
|
||||
* Support arbitrary Number implementation for Object and Number deserialization (https://github.com/google/gson/pull/1290).
|
||||
* Bump proguard-maven-plugin from 2.4.0 to 2.5.1 (https://github.com/google/gson/pull/1980).
|
||||
* Don't exclude static local classes (https://github.com/google/gson/pull/1969).
|
||||
* Fix `RuntimeTypeAdapterFactory` depending on internal `Streams` class (https://github.com/google/gson/pull/1959).
|
||||
* Improve Maven build (https://github.com/google/gson/pull/1964).
|
||||
* Make dependency on `java.sql` optional (https://github.com/google/gson/pull/1707).
|
||||
|
||||
## Version 2.8.8
|
||||
|
||||
* Fixed issue with recursive types (#1390).
|
||||
* Better behaviour with Java 9+ and `Unsafe` if there is a security manager (#1712).
|
||||
* `EnumTypeAdapter` now works better when ProGuard has obfuscated enum fields (#1495).
|
||||
* Fixed issue with recursive types (https://github.com/google/gson/issues/1390).
|
||||
* Better behaviour with Java 9+ and `Unsafe` if there is a security manager (https://github.com/google/gson/pull/1712).
|
||||
* `EnumTypeAdapter` now works better when ProGuard has obfuscated enum fields (https://github.com/google/gson/pull/1495).
|
||||
|
||||
## Version 2.8.7
|
||||
|
||||
* Fixed `ISO8601UtilsTest` failing on systems with UTC+X.
|
||||
* Improved javadoc for `JsonStreamParser`.
|
||||
* Updated proguard.cfg (#1693).
|
||||
* Fixed `IllegalStateException` in `JsonTreeWriter` (#1592).
|
||||
* Added `JsonArray.isEmpty()` (#1640).
|
||||
* Added new test cases (#1638).
|
||||
* Fixed OSGi metadata generation to work on JavaSE < 9 (#1603).
|
||||
* Updated proguard.cfg (https://github.com/google/gson/pull/1693).
|
||||
* Fixed `IllegalStateException` in `JsonTreeWriter` (https://github.com/google/gson/issues/1592).
|
||||
* Added `JsonArray.isEmpty()` (https://github.com/google/gson/pull/1640).
|
||||
* Added new test cases (https://github.com/google/gson/pull/1638).
|
||||
* Fixed OSGi metadata generation to work on JavaSE < 9 (https://github.com/google/gson/pull/1603).
|
||||
|
||||
## Version 2.8.6
|
||||
_2019-10-04_ [GitHub Diff](https://github.com/google/gson/compare/gson-parent-2.8.5...gson-parent-2.8.6)
|
||||
|
|
26
README.md
26
README.md
|
@ -1,3 +1,29 @@
|
|||
# About this fork
|
||||
|
||||
This fork of Gson adds several features which were originally denied due to Gson's maintenance status.
|
||||
Among them are:
|
||||
- support for writing comments
|
||||
- collections with single entries without array syntax (`"single entry"` can become a `List` or array)
|
||||
- stricter leniency enforcement from the main Gson class (`toJson`, `fromJson` will respect the choice)
|
||||
- slightly better error messages
|
||||
- skipping empty entries in arrays (`["one",, "two",]`)
|
||||
- optionally omitting quotes around entry names like in Json5
|
||||
- support for hexadecimal integers
|
||||
|
||||
This means the only thing lacking for Json5 support is trailing commas in objects
|
||||
|
||||
Please be aware that I also increased the minimum java version to 11
|
||||
To use this, add the following:
|
||||
```groovy
|
||||
maven {
|
||||
url = 'https://maven.frohnmeyer-wds.de/artifacts/'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation('io.gitlab.jfronny:gson:+')
|
||||
}
|
||||
```
|
||||
|
||||
# Gson
|
||||
|
||||
Gson is a Java library that can be used to convert Java Objects into their JSON representation. It can also be used to convert a JSON string to an equivalent Java object.
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
<settings xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd">
|
||||
<servers>
|
||||
<server>
|
||||
<id>jf-maven</id>
|
||||
<username>${MAVEN_NAME}</username>
|
||||
<password>${MAVEN_TOKEN}</password>
|
||||
</server>
|
||||
</servers>
|
||||
</settings>
|
|
@ -1,7 +1,7 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<groupId>io.gitlab.jfronny</groupId>
|
||||
<artifactId>gson-parent</artifactId>
|
||||
<version>2.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
@ -25,7 +25,7 @@
|
|||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<groupId>io.gitlab.jfronny</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
|
|
|
@ -58,7 +58,7 @@ public final class GraphAdapterBuilderTest {
|
|||
"'0x2':{'name':'SCISSORS','beats':'0x3'}," +
|
||||
"'0x3':{'name':'PAPER','beats':'0x1'}}";
|
||||
|
||||
GsonBuilder gsonBuilder = new GsonBuilder();
|
||||
GsonBuilder gsonBuilder = new GsonBuilder().setLenient();
|
||||
new GraphAdapterBuilder()
|
||||
.addType(Roshambo.class)
|
||||
.registerOn(gsonBuilder);
|
||||
|
@ -77,7 +77,7 @@ public final class GraphAdapterBuilderTest {
|
|||
public void testDeserializationDirectSelfReference() {
|
||||
String json = "{'0x1':{'name':'SUICIDE','beats':'0x1'}}";
|
||||
|
||||
GsonBuilder gsonBuilder = new GsonBuilder();
|
||||
GsonBuilder gsonBuilder = new GsonBuilder().setLenient();
|
||||
new GraphAdapterBuilder()
|
||||
.addType(Roshambo.class)
|
||||
.registerOn(gsonBuilder);
|
||||
|
@ -113,7 +113,7 @@ public final class GraphAdapterBuilderTest {
|
|||
Type listOfAnyType = new TypeToken<List<?>>() {}.getType();
|
||||
Type listOfListsType = new TypeToken<List<List<?>>>() {}.getType();
|
||||
|
||||
GsonBuilder gsonBuilder = new GsonBuilder();
|
||||
GsonBuilder gsonBuilder = new GsonBuilder().setLenient();
|
||||
new GraphAdapterBuilder()
|
||||
.addType(listOfListsType)
|
||||
.addType(listOfAnyType)
|
||||
|
@ -132,7 +132,7 @@ public final class GraphAdapterBuilderTest {
|
|||
new Employee("Jesse", google);
|
||||
new Employee("Joel", google);
|
||||
|
||||
GsonBuilder gsonBuilder = new GsonBuilder();
|
||||
GsonBuilder gsonBuilder = new GsonBuilder().setLenient();
|
||||
new GraphAdapterBuilder()
|
||||
.addType(Company.class)
|
||||
.addType(Employee.class)
|
||||
|
@ -147,7 +147,7 @@ public final class GraphAdapterBuilderTest {
|
|||
|
||||
@Test
|
||||
public void testDeserializationWithMultipleTypes() {
|
||||
GsonBuilder gsonBuilder = new GsonBuilder();
|
||||
GsonBuilder gsonBuilder = new GsonBuilder().setLenient();
|
||||
new GraphAdapterBuilder()
|
||||
.addType(Company.class)
|
||||
.addType(Employee.class)
|
||||
|
|
|
@ -46,6 +46,7 @@ public final class InterceptorTest extends TestCase {
|
|||
this.gson = new GsonBuilder()
|
||||
.registerTypeAdapterFactory(new InterceptorFactory())
|
||||
.enableComplexMapKeySerialization()
|
||||
.setLenient()
|
||||
.create();
|
||||
}
|
||||
|
||||
|
@ -109,6 +110,7 @@ public final class InterceptorTest extends TestCase {
|
|||
}
|
||||
})
|
||||
.registerTypeAdapterFactory(new InterceptorFactory())
|
||||
.setLenient()
|
||||
.create();
|
||||
UserGroup userGroup = gson.fromJson("{user:{name:'bob',password:'pwd'}}", UserGroup.class);
|
||||
assertEquals(User.DEFAULT_EMAIL, userGroup.user.email);
|
||||
|
|
|
@ -30,6 +30,7 @@ public final class RuntimeTypeAdapterFactoryTest extends TestCase {
|
|||
.registerSubtype(CreditCard.class);
|
||||
Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapterFactory(rta)
|
||||
.setLenient()
|
||||
.create();
|
||||
|
||||
CreditCard original = new CreditCard("Jesse", 234);
|
||||
|
@ -50,6 +51,7 @@ public final class RuntimeTypeAdapterFactoryTest extends TestCase {
|
|||
.recognizeSubtypes()
|
||||
.registerSubtype(CreditCard.class);
|
||||
Gson gson = new GsonBuilder()
|
||||
.setLenient()
|
||||
.registerTypeAdapterFactory(rta)
|
||||
.create();
|
||||
|
||||
|
@ -68,6 +70,7 @@ public final class RuntimeTypeAdapterFactoryTest extends TestCase {
|
|||
.registerSubtype(BillingInstrument.class);
|
||||
Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapterFactory(rta)
|
||||
.setLenient()
|
||||
.create();
|
||||
|
||||
BillingInstrument original = new BillingInstrument("Jesse");
|
||||
|
|
|
@ -29,6 +29,7 @@ import junit.framework.TestCase;
|
|||
public final class UtcDateTypeAdapterTest extends TestCase {
|
||||
private final Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapter(Date.class, new UtcDateTypeAdapter())
|
||||
.setLenient()
|
||||
.create();
|
||||
|
||||
public void testLocalTimeZone() {
|
||||
|
@ -56,6 +57,7 @@ public final class UtcDateTypeAdapterTest extends TestCase {
|
|||
public void testUtcDatesOnJdkBefore1_7() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapter(Date.class, new UtcDateTypeAdapter())
|
||||
.setLenient()
|
||||
.create();
|
||||
gson.fromJson("'2014-12-05T04:00:00.000Z'", Date.class);
|
||||
}
|
||||
|
|
109
gson/pom.xml
109
gson/pom.xml
|
@ -2,7 +2,7 @@
|
|||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<groupId>io.gitlab.jfronny</groupId>
|
||||
<artifactId>gson-parent</artifactId>
|
||||
<version>2.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
@ -77,6 +77,10 @@
|
|||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<source>8</source>
|
||||
<target>8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>biz.aQute.bnd</groupId>
|
||||
|
@ -109,82 +113,6 @@
|
|||
<argLine>--illegal-access=deny</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.coderplus.maven.plugins</groupId>
|
||||
<artifactId>copy-rename-maven-plugin</artifactId>
|
||||
<version>1.0.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>pre-obfuscate-class</id>
|
||||
<phase>process-test-classes</phase>
|
||||
<goals>
|
||||
<goal>rename</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<fileSets>
|
||||
<fileSet>
|
||||
<sourceFile>${project.build.directory}/test-classes/com/google/gson/functional/EnumWithObfuscatedTest.class</sourceFile>
|
||||
<destinationFile>${project.build.directory}/test-classes-obfuscated-injar/com/google/gson/functional/EnumWithObfuscatedTest.class</destinationFile>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<sourceFile>${project.build.directory}/test-classes/com/google/gson/functional/EnumWithObfuscatedTest$Gender.class</sourceFile>
|
||||
<destinationFile>${project.build.directory}/test-classes-obfuscated-injar/com/google/gson/functional/EnumWithObfuscatedTest$Gender.class</destinationFile>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.github.wvengen</groupId>
|
||||
<artifactId>proguard-maven-plugin</artifactId>
|
||||
<version>2.6.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>obfuscate-test-class</id>
|
||||
<phase>process-test-classes</phase>
|
||||
<goals>
|
||||
<goal>proguard</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<obfuscate>true</obfuscate>
|
||||
<injar>test-classes-obfuscated-injar</injar>
|
||||
<outjar>test-classes-obfuscated-outjar</outjar>
|
||||
<inFilter>**/*.class</inFilter>
|
||||
<proguardInclude>${basedir}/src/test/resources/testcases-proguard.conf</proguardInclude>
|
||||
<libs>
|
||||
<lib>${project.build.directory}/classes</lib>
|
||||
<lib>${java.home}/jmods/java.base.jmod</lib>
|
||||
</libs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>post-obfuscate-class</id>
|
||||
<phase>process-test-classes</phase>
|
||||
<goals>
|
||||
<goal>copy-resources</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>${project.build.directory}/test-classes/com/google/gson/functional</outputDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>${project.build.directory}/test-classes-obfuscated-outjar/com/google/gson/functional</directory>
|
||||
<includes>
|
||||
<include>EnumWithObfuscatedTest.class</include>
|
||||
<include>EnumWithObfuscatedTest$Gender.class</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<!--
|
||||
Plugins for building / modifying artifacts
|
||||
|
@ -199,33 +127,6 @@
|
|||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- Add module-info to JAR, see https://github.com/moditect/moditect#adding-module-descriptors-to-existing-jar-files -->
|
||||
<!-- Uses ModiTect instead of separate maven-compiler-plugin executions
|
||||
for better Eclipse IDE support, see https://github.com/eclipse-m2e/m2e-core/issues/393 -->
|
||||
<!-- Note: For some reason this has to be executed before javadoc plugin; otherwise `javadoc:jar` goal fails
|
||||
to find source files -->
|
||||
<plugin>
|
||||
<groupId>org.moditect</groupId>
|
||||
<artifactId>moditect-maven-plugin</artifactId>
|
||||
<version>1.0.0.RC2</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>add-module-info</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>add-module-info</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<jvmVersion>9</jvmVersion>
|
||||
<module>
|
||||
<moduleInfoFile>${project.build.sourceDirectory}/module-info.java</moduleInfoFile>
|
||||
</module>
|
||||
<!-- Overwrite the previously generated JAR file, if any -->
|
||||
<overwriteExistingFiles>true</overwriteExistingFiles>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<!-- Note: Javadoc plugin has to be run in combination with >= `package` phase,
|
||||
e.g. `mvn package javadoc:javadoc`, otherwise it fails with
|
||||
"Aggregator report contains named and unnamed modules" -->
|
||||
|
|
|
@ -16,12 +16,7 @@
|
|||
|
||||
package com.google.gson;
|
||||
|
||||
import com.google.gson.internal.ConstructorConstructor;
|
||||
import com.google.gson.internal.Excluder;
|
||||
import com.google.gson.internal.GsonBuildConfig;
|
||||
import com.google.gson.internal.LazilyParsedNumber;
|
||||
import com.google.gson.internal.Primitives;
|
||||
import com.google.gson.internal.Streams;
|
||||
import com.google.gson.internal.*;
|
||||
import com.google.gson.internal.bind.ArrayTypeAdapter;
|
||||
import com.google.gson.internal.bind.CollectionTypeAdapterFactory;
|
||||
import com.google.gson.internal.bind.DateTypeAdapter;
|
||||
|
@ -139,21 +134,6 @@ import java.util.concurrent.atomic.AtomicLongArray;
|
|||
* @author Jesse Wilson
|
||||
*/
|
||||
public final class Gson {
|
||||
static final boolean DEFAULT_JSON_NON_EXECUTABLE = false;
|
||||
static final boolean DEFAULT_LENIENT = false;
|
||||
static final boolean DEFAULT_PRETTY_PRINT = false;
|
||||
static final boolean DEFAULT_ESCAPE_HTML = true;
|
||||
static final boolean DEFAULT_SERIALIZE_NULLS = false;
|
||||
static final boolean DEFAULT_COMPLEX_MAP_KEYS = false;
|
||||
static final boolean DEFAULT_SPECIALIZE_FLOAT_VALUES = false;
|
||||
static final boolean DEFAULT_USE_JDK_UNSAFE = true;
|
||||
static final String DEFAULT_DATE_PATTERN = null;
|
||||
static final FieldNamingStrategy DEFAULT_FIELD_NAMING_STRATEGY = FieldNamingPolicy.IDENTITY;
|
||||
static final ToNumberStrategy DEFAULT_OBJECT_TO_NUMBER_STRATEGY = ToNumberPolicy.DOUBLE;
|
||||
static final ToNumberStrategy DEFAULT_NUMBER_TO_NUMBER_STRATEGY = ToNumberPolicy.LAZILY_PARSED_NUMBER;
|
||||
|
||||
private static final String JSON_NON_EXECUTABLE_PREFIX = ")]}'\n";
|
||||
|
||||
/**
|
||||
* This thread local guards against reentrant calls to getAdapter(). In
|
||||
* certain object graphs, creating an adapter for a type may recursively
|
||||
|
@ -176,10 +156,12 @@ public final class Gson {
|
|||
final Map<Type, InstanceCreator<?>> instanceCreators;
|
||||
final boolean serializeNulls;
|
||||
final boolean complexMapKeySerialization;
|
||||
final boolean duplicateMapKeyDeserialization;
|
||||
final boolean generateNonExecutableJson;
|
||||
final boolean htmlSafe;
|
||||
final boolean prettyPrinting;
|
||||
final boolean lenient;
|
||||
final boolean omitQuotes;
|
||||
final boolean serializeSpecialFloatingPointValues;
|
||||
final boolean useJdkUnsafe;
|
||||
final String datePattern;
|
||||
|
@ -227,21 +209,21 @@ public final class Gson {
|
|||
* </ul>
|
||||
*/
|
||||
public Gson() {
|
||||
this(Excluder.DEFAULT, DEFAULT_FIELD_NAMING_STRATEGY,
|
||||
Collections.<Type, InstanceCreator<?>>emptyMap(), DEFAULT_SERIALIZE_NULLS,
|
||||
DEFAULT_COMPLEX_MAP_KEYS, DEFAULT_JSON_NON_EXECUTABLE, DEFAULT_ESCAPE_HTML,
|
||||
DEFAULT_PRETTY_PRINT, DEFAULT_LENIENT, DEFAULT_SPECIALIZE_FLOAT_VALUES,
|
||||
DEFAULT_USE_JDK_UNSAFE,
|
||||
LongSerializationPolicy.DEFAULT, DEFAULT_DATE_PATTERN, DateFormat.DEFAULT, DateFormat.DEFAULT,
|
||||
this(Excluder.DEFAULT, DefaultConfig.DEFAULT_FIELD_NAMING_STRATEGY,
|
||||
Collections.<Type, InstanceCreator<?>>emptyMap(), DefaultConfig.DEFAULT_SERIALIZE_NULLS,
|
||||
DefaultConfig.DEFAULT_COMPLEX_MAP_KEYS, DefaultConfig.DEFAULT_DUPLICATE_MAP_KEYS, DefaultConfig.DEFAULT_JSON_NON_EXECUTABLE, DefaultConfig.DEFAULT_ESCAPE_HTML,
|
||||
DefaultConfig.DEFAULT_PRETTY_PRINT, true, DefaultConfig.DEFAULT_OMIT_QUOTES, DefaultConfig.DEFAULT_SPECIALIZE_FLOAT_VALUES,
|
||||
DefaultConfig.DEFAULT_USE_JDK_UNSAFE,
|
||||
LongSerializationPolicy.DEFAULT, DefaultConfig.DEFAULT_DATE_PATTERN, DateFormat.DEFAULT, DateFormat.DEFAULT,
|
||||
Collections.<TypeAdapterFactory>emptyList(), Collections.<TypeAdapterFactory>emptyList(),
|
||||
Collections.<TypeAdapterFactory>emptyList(), DEFAULT_OBJECT_TO_NUMBER_STRATEGY, DEFAULT_NUMBER_TO_NUMBER_STRATEGY,
|
||||
Collections.<TypeAdapterFactory>emptyList(), DefaultConfig.DEFAULT_OBJECT_TO_NUMBER_STRATEGY, DefaultConfig.DEFAULT_NUMBER_TO_NUMBER_STRATEGY,
|
||||
Collections.<ReflectionAccessFilter>emptyList());
|
||||
}
|
||||
|
||||
Gson(Excluder excluder, FieldNamingStrategy fieldNamingStrategy,
|
||||
Map<Type, InstanceCreator<?>> instanceCreators, boolean serializeNulls,
|
||||
boolean complexMapKeySerialization, boolean generateNonExecutableGson, boolean htmlSafe,
|
||||
boolean prettyPrinting, boolean lenient, boolean serializeSpecialFloatingPointValues,
|
||||
boolean complexMapKeySerialization, boolean duplicateMapKeyDeserialization, boolean generateNonExecutableGson, boolean htmlSafe,
|
||||
boolean prettyPrinting, boolean lenient, boolean omitQuotes, boolean serializeSpecialFloatingPointValues,
|
||||
boolean useJdkUnsafe,
|
||||
LongSerializationPolicy longSerializationPolicy, String datePattern, int dateStyle,
|
||||
int timeStyle, List<TypeAdapterFactory> builderFactories,
|
||||
|
@ -255,10 +237,12 @@ public final class Gson {
|
|||
this.constructorConstructor = new ConstructorConstructor(instanceCreators, useJdkUnsafe, reflectionFilters);
|
||||
this.serializeNulls = serializeNulls;
|
||||
this.complexMapKeySerialization = complexMapKeySerialization;
|
||||
this.duplicateMapKeyDeserialization = duplicateMapKeyDeserialization;
|
||||
this.generateNonExecutableJson = generateNonExecutableGson;
|
||||
this.htmlSafe = htmlSafe;
|
||||
this.prettyPrinting = prettyPrinting;
|
||||
this.lenient = lenient;
|
||||
this.omitQuotes = omitQuotes;
|
||||
this.serializeSpecialFloatingPointValues = serializeSpecialFloatingPointValues;
|
||||
this.useJdkUnsafe = useJdkUnsafe;
|
||||
this.longSerializationPolicy = longSerializationPolicy;
|
||||
|
@ -329,7 +313,7 @@ public final class Gson {
|
|||
|
||||
// type adapters for composite and user-defined types
|
||||
factories.add(new CollectionTypeAdapterFactory(constructorConstructor));
|
||||
factories.add(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization));
|
||||
factories.add(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization, duplicateMapKeyDeserialization));
|
||||
this.jsonAdapterFactory = new JsonAdapterAnnotationTypeAdapterFactory(constructorConstructor);
|
||||
factories.add(jsonAdapterFactory);
|
||||
factories.add(TypeAdapters.ENUM_FACTORY);
|
||||
|
@ -350,15 +334,6 @@ public final class Gson {
|
|||
return new GsonBuilder(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method by accident exposes an internal Gson class; it might be removed in a
|
||||
* future version.
|
||||
*/
|
||||
@Deprecated
|
||||
public Excluder excluder() {
|
||||
return excluder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the field naming strategy used by this Gson instance.
|
||||
*
|
||||
|
@ -816,7 +791,9 @@ public final class Gson {
|
|||
@SuppressWarnings("unchecked")
|
||||
TypeAdapter<Object> adapter = (TypeAdapter<Object>) getAdapter(TypeToken.get(typeOfSrc));
|
||||
boolean oldLenient = writer.isLenient();
|
||||
writer.setLenient(true);
|
||||
writer.setLenient(lenient);
|
||||
boolean oldOmitQuotes = writer.getOmitQuotes();
|
||||
writer.setOmitQuotes(omitQuotes);
|
||||
boolean oldHtmlSafe = writer.isHtmlSafe();
|
||||
writer.setHtmlSafe(htmlSafe);
|
||||
boolean oldSerializeNulls = writer.getSerializeNulls();
|
||||
|
@ -831,6 +808,7 @@ public final class Gson {
|
|||
throw error;
|
||||
} finally {
|
||||
writer.setLenient(oldLenient);
|
||||
writer.setOmitQuotes(oldOmitQuotes);
|
||||
writer.setHtmlSafe(oldHtmlSafe);
|
||||
writer.setSerializeNulls(oldSerializeNulls);
|
||||
}
|
||||
|
@ -875,12 +853,13 @@ public final class Gson {
|
|||
* <li>{@link GsonBuilder#generateNonExecutableJson()}</li>
|
||||
* <li>{@link GsonBuilder#serializeNulls()}</li>
|
||||
* <li>{@link GsonBuilder#setLenient()}</li>
|
||||
* <li>{@link GsonBuilder#setOmitQuotes()}</li>
|
||||
* <li>{@link GsonBuilder#setPrettyPrinting()}</li>
|
||||
* </ul>
|
||||
*/
|
||||
public JsonWriter newJsonWriter(Writer writer) throws IOException {
|
||||
if (generateNonExecutableJson) {
|
||||
writer.write(JSON_NON_EXECUTABLE_PREFIX);
|
||||
writer.write(DefaultConfig.JSON_NON_EXECUTABLE_PREFIX);
|
||||
}
|
||||
JsonWriter jsonWriter = new JsonWriter(writer);
|
||||
if (prettyPrinting) {
|
||||
|
@ -888,7 +867,9 @@ public final class Gson {
|
|||
}
|
||||
jsonWriter.setHtmlSafe(htmlSafe);
|
||||
jsonWriter.setLenient(lenient);
|
||||
jsonWriter.setOmitQuotes(omitQuotes);
|
||||
jsonWriter.setSerializeNulls(serializeNulls);
|
||||
jsonWriter.setSerializeSpecialFloatingPointValues(serializeSpecialFloatingPointValues);
|
||||
return jsonWriter;
|
||||
}
|
||||
|
||||
|
@ -903,6 +884,7 @@ public final class Gson {
|
|||
public JsonReader newJsonReader(Reader reader) {
|
||||
JsonReader jsonReader = new JsonReader(reader);
|
||||
jsonReader.setLenient(lenient);
|
||||
jsonReader.setSerializeSpecialFloatingPointValues(serializeSpecialFloatingPointValues);
|
||||
return jsonReader;
|
||||
}
|
||||
|
||||
|
@ -921,7 +903,9 @@ public final class Gson {
|
|||
*/
|
||||
public void toJson(JsonElement jsonElement, JsonWriter writer) throws JsonIOException {
|
||||
boolean oldLenient = writer.isLenient();
|
||||
writer.setLenient(true);
|
||||
writer.setLenient(lenient);
|
||||
boolean oldOmitQuotes = writer.getOmitQuotes();
|
||||
writer.setOmitQuotes(omitQuotes);
|
||||
boolean oldHtmlSafe = writer.isHtmlSafe();
|
||||
writer.setHtmlSafe(htmlSafe);
|
||||
boolean oldSerializeNulls = writer.getSerializeNulls();
|
||||
|
@ -936,6 +920,7 @@ public final class Gson {
|
|||
throw error;
|
||||
} finally {
|
||||
writer.setLenient(oldLenient);
|
||||
writer.setOmitQuotes(oldOmitQuotes);
|
||||
writer.setHtmlSafe(oldHtmlSafe);
|
||||
writer.setSerializeNulls(oldSerializeNulls);
|
||||
}
|
||||
|
@ -1206,7 +1191,7 @@ public final class Gson {
|
|||
public <T> T fromJson(JsonReader reader, TypeToken<T> typeOfT) throws JsonIOException, JsonSyntaxException {
|
||||
boolean isEmpty = true;
|
||||
boolean oldLenient = reader.isLenient();
|
||||
reader.setLenient(true);
|
||||
reader.setLenient(lenient);
|
||||
try {
|
||||
reader.peek();
|
||||
isEmpty = false;
|
||||
|
|
|
@ -16,17 +16,7 @@
|
|||
|
||||
package com.google.gson;
|
||||
|
||||
import static com.google.gson.Gson.DEFAULT_COMPLEX_MAP_KEYS;
|
||||
import static com.google.gson.Gson.DEFAULT_DATE_PATTERN;
|
||||
import static com.google.gson.Gson.DEFAULT_ESCAPE_HTML;
|
||||
import static com.google.gson.Gson.DEFAULT_JSON_NON_EXECUTABLE;
|
||||
import static com.google.gson.Gson.DEFAULT_LENIENT;
|
||||
import static com.google.gson.Gson.DEFAULT_NUMBER_TO_NUMBER_STRATEGY;
|
||||
import static com.google.gson.Gson.DEFAULT_OBJECT_TO_NUMBER_STRATEGY;
|
||||
import static com.google.gson.Gson.DEFAULT_PRETTY_PRINT;
|
||||
import static com.google.gson.Gson.DEFAULT_SERIALIZE_NULLS;
|
||||
import static com.google.gson.Gson.DEFAULT_SPECIALIZE_FLOAT_VALUES;
|
||||
import static com.google.gson.Gson.DEFAULT_USE_JDK_UNSAFE;
|
||||
import static com.google.gson.internal.DefaultConfig.*;
|
||||
|
||||
import com.google.gson.annotations.Since;
|
||||
import com.google.gson.annotations.Until;
|
||||
|
@ -96,11 +86,13 @@ public final class GsonBuilder {
|
|||
private int dateStyle = DateFormat.DEFAULT;
|
||||
private int timeStyle = DateFormat.DEFAULT;
|
||||
private boolean complexMapKeySerialization = DEFAULT_COMPLEX_MAP_KEYS;
|
||||
private boolean duplicateMapKeyDeserialization = DEFAULT_DUPLICATE_MAP_KEYS;
|
||||
private boolean serializeSpecialFloatingPointValues = DEFAULT_SPECIALIZE_FLOAT_VALUES;
|
||||
private boolean escapeHtmlChars = DEFAULT_ESCAPE_HTML;
|
||||
private boolean prettyPrinting = DEFAULT_PRETTY_PRINT;
|
||||
private boolean generateNonExecutableJson = DEFAULT_JSON_NON_EXECUTABLE;
|
||||
private boolean lenient = DEFAULT_LENIENT;
|
||||
private boolean omitQuotes = DEFAULT_OMIT_QUOTES;
|
||||
private boolean useJdkUnsafe = DEFAULT_USE_JDK_UNSAFE;
|
||||
private ToNumberStrategy objectToNumberStrategy = DEFAULT_OBJECT_TO_NUMBER_STRATEGY;
|
||||
private ToNumberStrategy numberToNumberStrategy = DEFAULT_NUMBER_TO_NUMBER_STRATEGY;
|
||||
|
@ -127,10 +119,12 @@ public final class GsonBuilder {
|
|||
this.instanceCreators.putAll(gson.instanceCreators);
|
||||
this.serializeNulls = gson.serializeNulls;
|
||||
this.complexMapKeySerialization = gson.complexMapKeySerialization;
|
||||
this.duplicateMapKeyDeserialization = gson.duplicateMapKeyDeserialization;
|
||||
this.generateNonExecutableJson = gson.generateNonExecutableJson;
|
||||
this.escapeHtmlChars = gson.htmlSafe;
|
||||
this.prettyPrinting = gson.prettyPrinting;
|
||||
this.lenient = gson.lenient;
|
||||
this.omitQuotes = gson.omitQuotes;
|
||||
this.serializeSpecialFloatingPointValues = gson.serializeSpecialFloatingPointValues;
|
||||
this.longSerializationPolicy = gson.longSerializationPolicy;
|
||||
this.datePattern = gson.datePattern;
|
||||
|
@ -311,6 +305,22 @@ public final class GsonBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures Gson to deserialize duplicate map keys. Only the value of last entry with the same key will be used, previous values
|
||||
* will be discarded. By default, Gson throws a {@link JsonSyntaxException} when a key occurs more than once.
|
||||
*
|
||||
* <p>Note that enabling support for duplicate maps keys is discouraged because it can make an application less secure.
|
||||
* When an application interacts with other components using different JSON libraries, they might treat duplicate keys
|
||||
* differently, allowing an attacker to circumvent security checks.
|
||||
*
|
||||
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
|
||||
* @since 2.8
|
||||
*/
|
||||
public GsonBuilder enableDuplicateMapKeyDeserialization() {
|
||||
duplicateMapKeyDeserialization = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures Gson to exclude inner classes (= non-{@code static} nested classes) during serialization
|
||||
* and deserialization. This is a convenience method which behaves as if an {@link ExclusionStrategy}
|
||||
|
@ -503,6 +513,15 @@ public final class GsonBuilder {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* By default, Gson always writes quotes around entry names.
|
||||
* This option allows omitting quotes if the name is alphanumeric.
|
||||
*/
|
||||
public GsonBuilder setOmitQuotes() {
|
||||
omitQuotes = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* By default, Gson escapes HTML characters such as < > etc. Use this option to configure
|
||||
* Gson to pass-through HTML characters as is.
|
||||
|
@ -760,8 +779,8 @@ public final class GsonBuilder {
|
|||
addTypeAdaptersForDate(datePattern, dateStyle, timeStyle, factories);
|
||||
|
||||
return new Gson(excluder, fieldNamingPolicy, new HashMap<>(instanceCreators),
|
||||
serializeNulls, complexMapKeySerialization,
|
||||
generateNonExecutableJson, escapeHtmlChars, prettyPrinting, lenient,
|
||||
serializeNulls, complexMapKeySerialization, duplicateMapKeyDeserialization,
|
||||
generateNonExecutableJson, escapeHtmlChars, prettyPrinting, lenient, omitQuotes,
|
||||
serializeSpecialFloatingPointValues, useJdkUnsafe, longSerializationPolicy,
|
||||
datePattern, dateStyle, timeStyle, new ArrayList<>(this.factories),
|
||||
new ArrayList<>(this.hierarchyFactories), factories,
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
package com.google.gson.internal;
|
||||
|
||||
import com.google.gson.*;
|
||||
import com.google.gson.reflect.*;
|
||||
|
||||
public class DefaultConfig {
|
||||
public static final boolean DEFAULT_JSON_NON_EXECUTABLE = false;
|
||||
public static final boolean DEFAULT_LENIENT = false;
|
||||
public static final boolean DEFAULT_OMIT_QUOTES = false;
|
||||
public static final boolean DEFAULT_PRETTY_PRINT = false;
|
||||
public static final boolean DEFAULT_ESCAPE_HTML = true;
|
||||
public static final boolean DEFAULT_SERIALIZE_NULLS = false;
|
||||
public static final boolean DEFAULT_COMPLEX_MAP_KEYS = false;
|
||||
public static final boolean DEFAULT_DUPLICATE_MAP_KEYS = false;
|
||||
public static final boolean DEFAULT_SPECIALIZE_FLOAT_VALUES = false;
|
||||
public static final boolean DEFAULT_USE_JDK_UNSAFE = true;
|
||||
public static final String DEFAULT_DATE_PATTERN = null;
|
||||
public static final FieldNamingStrategy DEFAULT_FIELD_NAMING_STRATEGY = FieldNamingPolicy.IDENTITY;
|
||||
public static final ToNumberStrategy DEFAULT_OBJECT_TO_NUMBER_STRATEGY = ToNumberPolicy.DOUBLE;
|
||||
public static final ToNumberStrategy DEFAULT_NUMBER_TO_NUMBER_STRATEGY = ToNumberPolicy.LAZILY_PARSED_NUMBER;
|
||||
public static final TypeToken<?> NULL_KEY_SURROGATE = TypeToken.get(Object.class);
|
||||
public static final String JSON_NON_EXECUTABLE_PREFIX = ")]}'\n";
|
||||
}
|
|
@ -65,6 +65,12 @@ public final class ArrayTypeAdapter<E> extends TypeAdapter<Object> {
|
|||
in.nextNull();
|
||||
return null;
|
||||
}
|
||||
if (in.isLenient() && in.peek() != JsonToken.BEGIN_ARRAY) {
|
||||
// Coerce
|
||||
Object array = Array.newInstance(componentType, 1);
|
||||
Array.set(array, 0, componentTypeAdapter.read(in));
|
||||
return array;
|
||||
}
|
||||
|
||||
ArrayList<E> list = new ArrayList<>();
|
||||
in.beginArray();
|
||||
|
|
|
@ -77,12 +77,17 @@ public final class CollectionTypeAdapterFactory implements TypeAdapterFactory {
|
|||
}
|
||||
|
||||
Collection<E> collection = constructor.construct();
|
||||
in.beginArray();
|
||||
while (in.hasNext()) {
|
||||
E instance = elementTypeAdapter.read(in);
|
||||
collection.add(instance);
|
||||
if (!in.isLenient() || in.peek() == JsonToken.BEGIN_ARRAY) {
|
||||
in.beginArray();
|
||||
while (in.hasNext()) {
|
||||
E instance = elementTypeAdapter.read(in);
|
||||
collection.add(instance);
|
||||
}
|
||||
in.endArray();
|
||||
} else {
|
||||
// Coerce
|
||||
collection.add(elementTypeAdapter.read(in));
|
||||
}
|
||||
in.endArray();
|
||||
return collection;
|
||||
}
|
||||
|
||||
|
|
|
@ -277,17 +277,17 @@ public final class JsonTreeReader extends JsonReader {
|
|||
JsonToken peeked = peek();
|
||||
switch (peeked) {
|
||||
case NAME:
|
||||
@SuppressWarnings("unused")
|
||||
String unused = nextName(true);
|
||||
break;
|
||||
case END_ARRAY:
|
||||
endArray();
|
||||
break;
|
||||
throw new IllegalStateException("Attempt to skip led outside its parent");
|
||||
case END_OBJECT:
|
||||
endObject();
|
||||
break;
|
||||
throw new IllegalStateException("Attempt to skip led outside its parent");
|
||||
case END_DOCUMENT:
|
||||
// Do nothing
|
||||
break;
|
||||
throw new IllegalStateException("Attempt to skip led outside the document");
|
||||
default:
|
||||
popStack();
|
||||
if (stackSize > 0) {
|
||||
|
|
|
@ -73,7 +73,12 @@ public final class JsonTreeWriter extends JsonWriter {
|
|||
return stack.get(stack.size() - 1);
|
||||
}
|
||||
|
||||
private void put(JsonElement value) {
|
||||
@Override
|
||||
public JsonWriter comment(String comment) throws IOException {
|
||||
return this;
|
||||
}
|
||||
|
||||
private void put(JsonElement value) {
|
||||
if (pendingName != null) {
|
||||
if (!value.isJsonNull() || getSerializeNulls()) {
|
||||
JsonObject object = (JsonObject) peek();
|
||||
|
|
|
@ -105,11 +105,13 @@ import java.util.Map;
|
|||
public final class MapTypeAdapterFactory implements TypeAdapterFactory {
|
||||
private final ConstructorConstructor constructorConstructor;
|
||||
final boolean complexMapKeySerialization;
|
||||
final boolean duplicateMapKeyDeserialization;
|
||||
|
||||
public MapTypeAdapterFactory(ConstructorConstructor constructorConstructor,
|
||||
boolean complexMapKeySerialization) {
|
||||
boolean complexMapKeySerialization, boolean duplicateMapKeyDeserialization) {
|
||||
this.constructorConstructor = constructorConstructor;
|
||||
this.complexMapKeySerialization = complexMapKeySerialization;
|
||||
this.duplicateMapKeyDeserialization = duplicateMapKeyDeserialization;
|
||||
}
|
||||
|
||||
@Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
|
||||
|
@ -172,7 +174,7 @@ public final class MapTypeAdapterFactory implements TypeAdapterFactory {
|
|||
K key = keyTypeAdapter.read(in);
|
||||
V value = valueTypeAdapter.read(in);
|
||||
V replaced = map.put(key, value);
|
||||
if (replaced != null) {
|
||||
if (!duplicateMapKeyDeserialization && replaced != null) {
|
||||
throw new JsonSyntaxException("duplicate key: " + key);
|
||||
}
|
||||
in.endArray();
|
||||
|
@ -185,7 +187,7 @@ public final class MapTypeAdapterFactory implements TypeAdapterFactory {
|
|||
K key = keyTypeAdapter.read(in);
|
||||
V value = valueTypeAdapter.read(in);
|
||||
V replaced = map.put(key, value);
|
||||
if (replaced != null) {
|
||||
if (!duplicateMapKeyDeserialization && replaced != null) {
|
||||
throw new JsonSyntaxException("duplicate key: " + key);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
package com.google.gson.stream;
|
||||
|
||||
import com.google.gson.internal.JsonReaderInternalAccess;
|
||||
import com.google.gson.internal.*;
|
||||
import com.google.gson.internal.bind.JsonTreeReader;
|
||||
import java.io.Closeable;
|
||||
import java.io.EOFException;
|
||||
|
@ -227,7 +227,9 @@ public class JsonReader implements Closeable {
|
|||
private final Reader in;
|
||||
|
||||
/** True to accept non-spec compliant JSON */
|
||||
private boolean lenient = false;
|
||||
private boolean lenient = DefaultConfig.DEFAULT_LENIENT;
|
||||
|
||||
private boolean serializeSpecialFloatingPointValues = DefaultConfig.DEFAULT_SPECIALIZE_FLOAT_VALUES;
|
||||
|
||||
static final int BUFFER_SIZE = 1024;
|
||||
/**
|
||||
|
@ -311,8 +313,7 @@ public class JsonReader implements Closeable {
|
|||
* <li>Names that are unquoted or {@code 'single quoted'}.
|
||||
* <li>Strings that are unquoted or {@code 'single quoted'}.
|
||||
* <li>Array elements separated by {@code ;} instead of {@code ,}.
|
||||
* <li>Unnecessary array separators. These are interpreted as if null
|
||||
* was the omitted value.
|
||||
* <li>Unnecessary array separators. These are ignored.
|
||||
* <li>Names and values separated by {@code =} or {@code =>} instead of
|
||||
* {@code :}.
|
||||
* <li>Name/value pairs separated by {@code ;} instead of {@code ,}.
|
||||
|
@ -332,6 +333,7 @@ public class JsonReader implements Closeable {
|
|||
*/
|
||||
public final void setLenient(boolean lenient) {
|
||||
this.lenient = lenient;
|
||||
if (lenient) serializeSpecialFloatingPointValues = true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -341,6 +343,14 @@ public class JsonReader implements Closeable {
|
|||
return lenient;
|
||||
}
|
||||
|
||||
public void setSerializeSpecialFloatingPointValues(boolean serializeSpecialFloatingPointValues) {
|
||||
this.serializeSpecialFloatingPointValues = serializeSpecialFloatingPointValues;
|
||||
}
|
||||
|
||||
public boolean isSerializeSpecialFloatingPointValues() {
|
||||
return serializeSpecialFloatingPointValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* Consumes the next token from the JSON stream and asserts that it is the
|
||||
* beginning of a new array.
|
||||
|
@ -482,7 +492,7 @@ public class JsonReader implements Closeable {
|
|||
case ',':
|
||||
break;
|
||||
default:
|
||||
throw syntaxError("Unterminated array");
|
||||
throw syntaxError("Unterminated array at " + (char)c);
|
||||
}
|
||||
} else if (peekStack == JsonScope.EMPTY_OBJECT || peekStack == JsonScope.NONEMPTY_OBJECT) {
|
||||
stack[stackSize - 1] = JsonScope.DANGLING_NAME;
|
||||
|
@ -497,7 +507,7 @@ public class JsonReader implements Closeable {
|
|||
case ',':
|
||||
break;
|
||||
default:
|
||||
throw syntaxError("Unterminated object");
|
||||
throw syntaxError("Unterminated object at " + (char)c);
|
||||
}
|
||||
}
|
||||
int c = nextNonWhitespace(true);
|
||||
|
@ -555,35 +565,8 @@ public class JsonReader implements Closeable {
|
|||
throw new IllegalStateException("JsonReader is closed");
|
||||
}
|
||||
|
||||
int c = nextNonWhitespace(true);
|
||||
switch (c) {
|
||||
case ']':
|
||||
if (peekStack == JsonScope.EMPTY_ARRAY) {
|
||||
return peeked = PEEKED_END_ARRAY;
|
||||
}
|
||||
// fall-through to handle ",]"
|
||||
case ';':
|
||||
case ',':
|
||||
// In lenient mode, a 0-length literal in an array means 'null'.
|
||||
if (peekStack == JsonScope.EMPTY_ARRAY || peekStack == JsonScope.NONEMPTY_ARRAY) {
|
||||
checkLenient();
|
||||
pos--;
|
||||
return peeked = PEEKED_NULL;
|
||||
} else {
|
||||
throw syntaxError("Unexpected value");
|
||||
}
|
||||
case '\'':
|
||||
checkLenient();
|
||||
return peeked = PEEKED_SINGLE_QUOTED;
|
||||
case '"':
|
||||
return peeked = PEEKED_DOUBLE_QUOTED;
|
||||
case '[':
|
||||
return peeked = PEEKED_BEGIN_ARRAY;
|
||||
case '{':
|
||||
return peeked = PEEKED_BEGIN_OBJECT;
|
||||
default:
|
||||
pos--; // Don't consume the first character in a literal value.
|
||||
}
|
||||
if (checkNextNonWhitespace(peekStack))
|
||||
return peeked;
|
||||
|
||||
int result = peekKeyword();
|
||||
if (result != PEEKED_NONE) {
|
||||
|
@ -603,6 +586,45 @@ public class JsonReader implements Closeable {
|
|||
return peeked = PEEKED_UNQUOTED;
|
||||
}
|
||||
|
||||
private boolean checkNextNonWhitespace(int peekStack) throws IOException {
|
||||
int c = nextNonWhitespace(true);
|
||||
switch (c) {
|
||||
case ']':
|
||||
if (peekStack == JsonScope.EMPTY_ARRAY || peekStack == JsonScope.NONEMPTY_ARRAY) {
|
||||
peeked = PEEKED_END_ARRAY;
|
||||
return true;
|
||||
}
|
||||
throw syntaxError("Unexpected value");
|
||||
case ';':
|
||||
case ',':
|
||||
// In lenient mode, a 0-length literal in an array should be skipped.
|
||||
if (peekStack == JsonScope.EMPTY_ARRAY || peekStack == JsonScope.NONEMPTY_ARRAY) {
|
||||
checkLenient();
|
||||
//pos--;
|
||||
//peeked = PEEKED_NULL;
|
||||
return checkNextNonWhitespace(peekStack);
|
||||
} else {
|
||||
throw syntaxError("Unexpected value");
|
||||
}
|
||||
case '\'':
|
||||
checkLenient();
|
||||
peeked = PEEKED_SINGLE_QUOTED;
|
||||
return true;
|
||||
case '"':
|
||||
peeked = PEEKED_DOUBLE_QUOTED;
|
||||
return true;
|
||||
case '[':
|
||||
peeked = PEEKED_BEGIN_ARRAY;
|
||||
return true;
|
||||
case '{':
|
||||
peeked = PEEKED_BEGIN_OBJECT;
|
||||
return true;
|
||||
default:
|
||||
pos--; // Don't consume the first character in a literal value.
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private int peekKeyword() throws IOException {
|
||||
// Figure out which keyword we're matching against by its first character.
|
||||
char c = buffer[pos];
|
||||
|
@ -918,7 +940,7 @@ public class JsonReader implements Closeable {
|
|||
|
||||
peeked = PEEKED_BUFFERED;
|
||||
double result = Double.parseDouble(peekedString); // don't catch this NumberFormatException.
|
||||
if (!lenient && (Double.isNaN(result) || Double.isInfinite(result))) {
|
||||
if (!serializeSpecialFloatingPointValues && (Double.isNaN(result) || Double.isInfinite(result))) {
|
||||
throw new MalformedJsonException(
|
||||
"JSON forbids NaN and infinities: " + result + locationString());
|
||||
}
|
||||
|
@ -1210,10 +1232,14 @@ public class JsonReader implements Closeable {
|
|||
}
|
||||
|
||||
peeked = PEEKED_BUFFERED;
|
||||
double asDouble = Double.parseDouble(peekedString); // don't catch this NumberFormatException.
|
||||
result = (int) asDouble;
|
||||
if (result != asDouble) { // Make sure no precision was lost casting to 'int'.
|
||||
throw new NumberFormatException("Expected an int but was " + peekedString + locationString());
|
||||
if (peekedString.startsWith("0x")) {
|
||||
result = Integer.decode(peekedString);
|
||||
} else {
|
||||
double asDouble = Double.parseDouble(peekedString); // don't catch this NumberFormatException.
|
||||
result = (int) asDouble;
|
||||
if (result != asDouble) { // Make sure no precision was lost casting to 'int'.
|
||||
throw new NumberFormatException("Expected an int but was " + peekedString + locationString());
|
||||
}
|
||||
}
|
||||
peekedString = null;
|
||||
peeked = PEEKED_NONE;
|
||||
|
@ -1241,9 +1267,8 @@ public class JsonReader implements Closeable {
|
|||
* <li>Primitive value (for example a JSON number): The primitive value is skipped.</li>
|
||||
* <li>Property name: Only the name but not the value of the property is skipped.
|
||||
* {@code skipValue()} has to be called again to skip the property value as well.</li>
|
||||
* <li>End of a JSON array or object: Only this end token is skipped.</li>
|
||||
* <li>End of JSON document: Skipping has no effect, the next token continues to be the
|
||||
* end of the document.</li>
|
||||
* <li>End of a JSON array or object: Only this end token is skipped and an exception is thrown.</li>
|
||||
* <li>End of JSON document: Skipping has no effect on the state, but an exception is thrown.</li>
|
||||
* </ul>
|
||||
*/
|
||||
public void skipValue() throws IOException {
|
||||
|
@ -1309,14 +1334,14 @@ public class JsonReader implements Closeable {
|
|||
pos += peekedNumberLength;
|
||||
break;
|
||||
case PEEKED_EOF:
|
||||
// Do nothing
|
||||
return;
|
||||
throw new IllegalStateException("Attempt to skip led outside the document");
|
||||
// For all other tokens there is nothing to do; token has already been consumed from underlying reader
|
||||
}
|
||||
peeked = PEEKED_NONE;
|
||||
} while (count > 0);
|
||||
|
||||
pathIndices[stackSize - 1]++;
|
||||
if (count < 0) throw new IllegalStateException("Attempt to skip led outside its parent");
|
||||
}
|
||||
|
||||
private void push(int newTop) {
|
||||
|
@ -1511,7 +1536,8 @@ public class JsonReader implements Closeable {
|
|||
String locationString() {
|
||||
int line = lineNumber + 1;
|
||||
int column = pos - lineStart + 1;
|
||||
return " at line " + line + " column " + column + " path " + getPath();
|
||||
String charInterjection = pos < buffer.length ? " (char '" + buffer[pos] + "')" : "";
|
||||
return " at line " + line + " column " + column + charInterjection + " path " + getPath();
|
||||
}
|
||||
|
||||
private String getPath(boolean usePreviousPath) {
|
||||
|
|
|
@ -24,14 +24,15 @@ import static com.google.gson.stream.JsonScope.NONEMPTY_ARRAY;
|
|||
import static com.google.gson.stream.JsonScope.NONEMPTY_DOCUMENT;
|
||||
import static com.google.gson.stream.JsonScope.NONEMPTY_OBJECT;
|
||||
|
||||
import com.google.gson.internal.*;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.Flushable;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.regex.Pattern;
|
||||
|
@ -190,7 +191,11 @@ public class JsonWriter implements Closeable, Flushable {
|
|||
*/
|
||||
private String separator = ":";
|
||||
|
||||
private boolean lenient;
|
||||
private boolean lenient = DefaultConfig.DEFAULT_LENIENT;
|
||||
|
||||
private boolean serializeSpecialFloatingPointValues = DefaultConfig.DEFAULT_SPECIALIZE_FLOAT_VALUES;
|
||||
|
||||
private boolean omitQuotes = DefaultConfig.DEFAULT_OMIT_QUOTES;
|
||||
|
||||
private boolean htmlSafe;
|
||||
|
||||
|
@ -198,6 +203,8 @@ public class JsonWriter implements Closeable, Flushable {
|
|||
|
||||
private boolean serializeNulls = true;
|
||||
|
||||
private List<String> deferredComment = new LinkedList<>();
|
||||
|
||||
/**
|
||||
* Creates a new instance that writes a JSON-encoded stream to {@code out}.
|
||||
* For best performance, ensure {@link Writer} is buffered; wrapping in
|
||||
|
@ -237,6 +244,7 @@ public class JsonWriter implements Closeable, Flushable {
|
|||
*/
|
||||
public final void setLenient(boolean lenient) {
|
||||
this.lenient = lenient;
|
||||
if (lenient) this.serializeSpecialFloatingPointValues = true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -246,6 +254,14 @@ public class JsonWriter implements Closeable, Flushable {
|
|||
return lenient;
|
||||
}
|
||||
|
||||
public void setSerializeSpecialFloatingPointValues(boolean serializeSpecialFloatingPointValues) {
|
||||
this.serializeSpecialFloatingPointValues = serializeSpecialFloatingPointValues;
|
||||
}
|
||||
|
||||
public boolean isSerializeSpecialFloatingPointValues() {
|
||||
return serializeSpecialFloatingPointValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure this writer to emit JSON that's safe for direct inclusion in HTML
|
||||
* and XML documents. This escapes the HTML characters {@code <}, {@code >},
|
||||
|
@ -281,6 +297,18 @@ public class JsonWriter implements Closeable, Flushable {
|
|||
return serializeNulls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether serialized entry names may omit quotes (like in json5)
|
||||
* The default is false
|
||||
*/
|
||||
public final void setOmitQuotes(boolean omitQuotes) {
|
||||
this.omitQuotes = omitQuotes;
|
||||
}
|
||||
|
||||
public final boolean getOmitQuotes() {
|
||||
return omitQuotes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Begins encoding a new array. Each call to this method must be paired with
|
||||
* a call to {@link #endArray}.
|
||||
|
@ -346,6 +374,12 @@ public class JsonWriter implements Closeable, Flushable {
|
|||
throw new IllegalStateException("Dangling name: " + deferredName);
|
||||
}
|
||||
|
||||
if (!deferredComment.isEmpty()) {
|
||||
newline();
|
||||
writeDeferredComment();
|
||||
context = nonempty;
|
||||
}
|
||||
|
||||
stackSize--;
|
||||
if (context == nonempty) {
|
||||
newline();
|
||||
|
@ -378,6 +412,39 @@ public class JsonWriter implements Closeable, Flushable {
|
|||
stack[stackSize - 1] = topOfStack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a comment at the current location.
|
||||
* May create a new line.
|
||||
* This writer MUST be lenient to use this
|
||||
*/
|
||||
public JsonWriter comment(String comment) throws IOException {
|
||||
if (!lenient) throw new MalformedJsonException("Cannot write comment in non-lenient JsonWriter.");
|
||||
if (comment == null || comment.isBlank()) return this;
|
||||
String[] parts = comment.split("\n");
|
||||
Collections.addAll(deferredComment, parts);
|
||||
if (peek() == NONEMPTY_DOCUMENT) {
|
||||
newline();
|
||||
writeDeferredComment();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private void writeDeferredComment() throws IOException {
|
||||
if (!deferredComment.isEmpty()) {
|
||||
if (indent == null) {
|
||||
out.append("/* ").append(String.join(" / ", deferredComment)).append(" */");
|
||||
} else {
|
||||
boolean first = true;
|
||||
for (String s : deferredComment) {
|
||||
if (!first) newline();
|
||||
first = false;
|
||||
out.append("// ").append(s);
|
||||
}
|
||||
}
|
||||
deferredComment.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the property name.
|
||||
*
|
||||
|
@ -399,7 +466,12 @@ public class JsonWriter implements Closeable, Flushable {
|
|||
private void writeDeferredName() throws IOException {
|
||||
if (deferredName != null) {
|
||||
beforeName();
|
||||
string(deferredName);
|
||||
if (omitQuotes && deferredName.matches("[a-zA-Z_$][\\w$]*")) {
|
||||
out.write(deferredName);
|
||||
}
|
||||
else {
|
||||
string(deferredName);
|
||||
}
|
||||
deferredName = null;
|
||||
}
|
||||
}
|
||||
|
@ -501,7 +573,7 @@ public class JsonWriter implements Closeable, Flushable {
|
|||
*/
|
||||
public JsonWriter value(float value) throws IOException {
|
||||
writeDeferredName();
|
||||
if (!lenient && (Float.isNaN(value) || Float.isInfinite(value))) {
|
||||
if (!serializeSpecialFloatingPointValues && (Float.isNaN(value) || Float.isInfinite(value))) {
|
||||
throw new IllegalArgumentException("Numeric values must be finite, but was " + value);
|
||||
}
|
||||
beforeValue();
|
||||
|
@ -520,7 +592,7 @@ public class JsonWriter implements Closeable, Flushable {
|
|||
*/
|
||||
public JsonWriter value(double value) throws IOException {
|
||||
writeDeferredName();
|
||||
if (!lenient && (Double.isNaN(value) || Double.isInfinite(value))) {
|
||||
if (!serializeSpecialFloatingPointValues && (Double.isNaN(value) || Double.isInfinite(value))) {
|
||||
throw new IllegalArgumentException("Numeric values must be finite, but was " + value);
|
||||
}
|
||||
beforeValue();
|
||||
|
@ -570,7 +642,7 @@ public class JsonWriter implements Closeable, Flushable {
|
|||
writeDeferredName();
|
||||
String string = value.toString();
|
||||
if (string.equals("-Infinity") || string.equals("Infinity") || string.equals("NaN")) {
|
||||
if (!lenient) {
|
||||
if (!serializeSpecialFloatingPointValues) {
|
||||
throw new IllegalArgumentException("Numeric values must be finite, but was " + string);
|
||||
}
|
||||
} else {
|
||||
|
@ -667,6 +739,10 @@ public class JsonWriter implements Closeable, Flushable {
|
|||
throw new IllegalStateException("Nesting problem.");
|
||||
}
|
||||
newline();
|
||||
if (!deferredComment.isEmpty()) {
|
||||
writeDeferredComment();
|
||||
newline();
|
||||
}
|
||||
replaceTop(DANGLING_NAME);
|
||||
}
|
||||
|
||||
|
@ -680,26 +756,42 @@ public class JsonWriter implements Closeable, Flushable {
|
|||
switch (peek()) {
|
||||
case NONEMPTY_DOCUMENT:
|
||||
if (!lenient) {
|
||||
throw new IllegalStateException(
|
||||
"JSON must have only one top-level value.");
|
||||
throw new IllegalStateException("JSON must have only one top-level value.");
|
||||
}
|
||||
// fall-through
|
||||
case EMPTY_DOCUMENT: // first in document
|
||||
replaceTop(NONEMPTY_DOCUMENT);
|
||||
if (!deferredComment.isEmpty()) {
|
||||
writeDeferredComment();
|
||||
newline();
|
||||
}
|
||||
break;
|
||||
|
||||
case EMPTY_ARRAY: // first in array
|
||||
replaceTop(NONEMPTY_ARRAY);
|
||||
newline();
|
||||
if (!deferredComment.isEmpty()) {
|
||||
writeDeferredComment();
|
||||
newline();
|
||||
}
|
||||
break;
|
||||
|
||||
case NONEMPTY_ARRAY: // another in array
|
||||
out.append(',');
|
||||
newline();
|
||||
if (!deferredComment.isEmpty()) {
|
||||
writeDeferredComment();
|
||||
newline();
|
||||
}
|
||||
break;
|
||||
|
||||
case DANGLING_NAME: // value for name
|
||||
out.append(separator);
|
||||
if (!deferredComment.isEmpty()) {
|
||||
newline();
|
||||
writeDeferredComment();
|
||||
newline();
|
||||
}
|
||||
replaceTop(NONEMPTY_OBJECT);
|
||||
break;
|
||||
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2010 Google Inc.
|
||||
*
|
||||
* 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;
|
||||
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* @author Jesse Wilson
|
||||
*/
|
||||
public final class CommentsTest extends TestCase {
|
||||
|
||||
/**
|
||||
* Test for issue 212.
|
||||
*/
|
||||
public void testParseComments() {
|
||||
String json = "[\n"
|
||||
+ " // this is a comment\n"
|
||||
+ " \"a\",\n"
|
||||
+ " /* this is another comment */\n"
|
||||
+ " \"b\",\n"
|
||||
+ " # this is yet another comment\n"
|
||||
+ " \"c\"\n"
|
||||
+ "]";
|
||||
|
||||
List<String> abc = new Gson().fromJson(json, new TypeToken<List<String>>() {}.getType());
|
||||
assertEquals(Arrays.asList("a", "b", "c"), abc);
|
||||
}
|
||||
}
|
|
@ -56,8 +56,8 @@ public final class GsonTest extends TestCase {
|
|||
|
||||
public void testOverridesDefaultExcluder() {
|
||||
Gson gson = new Gson(CUSTOM_EXCLUDER, CUSTOM_FIELD_NAMING_STRATEGY,
|
||||
new HashMap<Type, InstanceCreator<?>>(), true, false, true, false,
|
||||
true, true, false, true, LongSerializationPolicy.DEFAULT, null, DateFormat.DEFAULT,
|
||||
new HashMap<Type, InstanceCreator<?>>(), true, false, false, true, false,
|
||||
true, true, false, false, true, LongSerializationPolicy.DEFAULT, null, DateFormat.DEFAULT,
|
||||
DateFormat.DEFAULT, new ArrayList<TypeAdapterFactory>(),
|
||||
new ArrayList<TypeAdapterFactory>(), new ArrayList<TypeAdapterFactory>(),
|
||||
CUSTOM_OBJECT_TO_NUMBER_STRATEGY, CUSTOM_NUMBER_TO_NUMBER_STRATEGY,
|
||||
|
@ -71,8 +71,8 @@ public final class GsonTest extends TestCase {
|
|||
|
||||
public void testClonedTypeAdapterFactoryListsAreIndependent() {
|
||||
Gson original = new Gson(CUSTOM_EXCLUDER, CUSTOM_FIELD_NAMING_STRATEGY,
|
||||
new HashMap<Type, InstanceCreator<?>>(), true, false, true, false,
|
||||
true, true, false, true, LongSerializationPolicy.DEFAULT, null, DateFormat.DEFAULT,
|
||||
new HashMap<Type, InstanceCreator<?>>(), true, false, false, true, false,
|
||||
true, true, false, false, true, LongSerializationPolicy.DEFAULT, null, DateFormat.DEFAULT,
|
||||
DateFormat.DEFAULT, new ArrayList<TypeAdapterFactory>(),
|
||||
new ArrayList<TypeAdapterFactory>(), new ArrayList<TypeAdapterFactory>(),
|
||||
CUSTOM_OBJECT_TO_NUMBER_STRATEGY, CUSTOM_NUMBER_TO_NUMBER_STRATEGY,
|
||||
|
@ -157,7 +157,7 @@ public final class GsonTest extends TestCase {
|
|||
|
||||
public void testNewJsonWriter_Default() throws IOException {
|
||||
StringWriter writer = new StringWriter();
|
||||
JsonWriter jsonWriter = new Gson().newJsonWriter(writer);
|
||||
JsonWriter jsonWriter = new GsonBuilder().create().newJsonWriter(writer);
|
||||
jsonWriter.beginObject();
|
||||
jsonWriter.name("test");
|
||||
jsonWriter.nullValue();
|
||||
|
@ -203,7 +203,7 @@ public final class GsonTest extends TestCase {
|
|||
|
||||
public void testNewJsonReader_Default() throws IOException {
|
||||
String json = "test"; // String without quotes
|
||||
JsonReader jsonReader = new Gson().newJsonReader(new StringReader(json));
|
||||
JsonReader jsonReader = new GsonBuilder().create().newJsonReader(new StringReader(json));
|
||||
try {
|
||||
jsonReader.nextString();
|
||||
fail();
|
||||
|
|
|
@ -203,7 +203,7 @@ public final class MixedStreamTest extends TestCase {
|
|||
|
||||
StringWriter writer = new StringWriter();
|
||||
JsonWriter jsonWriter = new JsonWriter(writer);
|
||||
new GsonBuilder().serializeSpecialFloatingPointValues().create()
|
||||
new GsonBuilder().setLenient().serializeSpecialFloatingPointValues().create()
|
||||
.toJson(doubles, type, jsonWriter);
|
||||
assertEquals("[NaN,-Infinity,Infinity,-0.0,0.5,0.0]", writer.toString());
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ public class ToNumberPolicyTest extends TestCase {
|
|||
strategy.readNumber(fromString("1e400"));
|
||||
fail();
|
||||
} catch (MalformedJsonException expected) {
|
||||
assertEquals("JSON forbids NaN and infinities: Infinity at line 1 column 6 path $", expected.getMessage());
|
||||
assertEquals("JSON forbids NaN and infinities: Infinity at line 1 column 6 (char '\0') path $", expected.getMessage());
|
||||
}
|
||||
try {
|
||||
strategy.readNumber(fromString("\"not-a-number\""));
|
||||
|
@ -74,19 +74,19 @@ public class ToNumberPolicyTest extends TestCase {
|
|||
strategy.readNumber(fromString("NaN"));
|
||||
fail();
|
||||
} catch (MalformedJsonException expected) {
|
||||
assertEquals("Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1 path $", expected.getMessage());
|
||||
assertEquals("Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1 (char 'N') path $", expected.getMessage());
|
||||
}
|
||||
try {
|
||||
strategy.readNumber(fromString("Infinity"));
|
||||
fail();
|
||||
} catch (MalformedJsonException expected) {
|
||||
assertEquals("Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1 path $", expected.getMessage());
|
||||
assertEquals("Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1 (char 'I') path $", expected.getMessage());
|
||||
}
|
||||
try {
|
||||
strategy.readNumber(fromString("-Infinity"));
|
||||
fail();
|
||||
} catch (MalformedJsonException expected) {
|
||||
assertEquals("Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1 path $", expected.getMessage());
|
||||
assertEquals("Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1 (char '-') path $", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -185,7 +185,7 @@ public class ArrayTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testArrayOfPrimitivesAsObjectsDeserialization() throws Exception {
|
||||
String json = "[1,'abc',0.3,1.1,5]";
|
||||
String json = "[1,\"abc\",0.3,1.1,5]";
|
||||
Object[] objs = gson.fromJson(json, Object[].class);
|
||||
assertEquals(1, ((Number)objs[0]).intValue());
|
||||
assertEquals("abc", objs[1]);
|
||||
|
@ -253,8 +253,8 @@ public class ArrayTest extends TestCase {
|
|||
* Regression tests for Issue 272
|
||||
*/
|
||||
public void testMultidimensionalArraysDeserialization() {
|
||||
String json = "[['3m Co','71.72','0.02','0.03','4/2 12:00am','Manufacturing'],"
|
||||
+ "['Alcoa Inc','29.01','0.42','1.47','4/1 12:00am','Manufacturing']]";
|
||||
String json = "[[\"3m Co\",\"71.72\",\"0.02\",\"0.03\",\"4/2 12:00am\",\"Manufacturing\"],"
|
||||
+ "[\"Alcoa Inc\",\"29.01\",\"0.42\",\"1.47\",\"4/1 12:00am\",\"Manufacturing\"]]";
|
||||
String[][] items = gson.fromJson(json, String[][].class);
|
||||
assertEquals("3m Co", items[0][0]);
|
||||
assertEquals("Manufacturing", items[1][5]);
|
||||
|
|
|
@ -100,7 +100,7 @@ public class CollectionTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testLinkedListDeserialization() {
|
||||
String json = "['a1','a2']";
|
||||
String json = "[\"a1\",\"a2\"]";
|
||||
Type linkedListType = new TypeToken<LinkedList<String>>() {}.getType();
|
||||
List<String> list = gson.fromJson(json, linkedListType);
|
||||
assertEquals("a1", list.get(0));
|
||||
|
@ -118,7 +118,7 @@ public class CollectionTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testQueueDeserialization() {
|
||||
String json = "['a1','a2']";
|
||||
String json = "[\"a1\",\"a2\"]";
|
||||
Type queueType = new TypeToken<Queue<String>>() {}.getType();
|
||||
Queue<String> queue = gson.fromJson(json, queueType);
|
||||
assertEquals("a1", queue.element());
|
||||
|
@ -381,7 +381,7 @@ public class CollectionTest extends TestCase {
|
|||
assertTrue(json.contains("2"));
|
||||
}
|
||||
public void testSetDeserialization() {
|
||||
String json = "[{value:1},{value:2}]";
|
||||
String json = "[{\"value\":1},{\"value\":2}]";
|
||||
Type type = new TypeToken<Set<Entry>>() {}.getType();
|
||||
Set<Entry> set = gson.fromJson(json, type);
|
||||
assertEquals(2, set.size());
|
||||
|
|
|
@ -56,7 +56,7 @@ public class ConcurrencyTest extends TestCase {
|
|||
*/
|
||||
public void testSingleThreadDeserialization() {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
gson.fromJson("{'a':'hello','b':'world','i':1}", MyObject.class);
|
||||
gson.fromJson("{\"a\":\"hello\",\"b\":\"world\",\"i\":1}", MyObject.class);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,7 @@ public class ConcurrencyTest extends TestCase {
|
|||
try {
|
||||
startLatch.await();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
gson.fromJson("{'a':'hello','b':'world','i':1}", MyObject.class);
|
||||
gson.fromJson("{\"a\":\"hello\",\"b\":\"world\",\"i\":1}", MyObject.class);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
failed.set(true);
|
||||
|
|
|
@ -112,12 +112,11 @@ public class CustomDeserializerTest extends TestCase {
|
|||
|
||||
public void testJsonTypeFieldBasedDeserialization() {
|
||||
String json = "{field1:'abc',field2:'def',__type__:'SUB_TYPE1'}";
|
||||
Gson gson = new GsonBuilder().registerTypeAdapter(MyBase.class, new JsonDeserializer<MyBase>() {
|
||||
@Override public MyBase deserialize(JsonElement json, Type pojoType,
|
||||
JsonDeserializationContext context) throws JsonParseException {
|
||||
String type = json.getAsJsonObject().get(MyBase.TYPE_ACCESS).getAsString();
|
||||
return context.deserialize(json, SubTypes.valueOf(type).getSubclass());
|
||||
}
|
||||
Gson gson = new GsonBuilder()
|
||||
.setLenient()
|
||||
.registerTypeAdapter(MyBase.class, (JsonDeserializer<MyBase>) (json1, pojoType, context) -> {
|
||||
String type = json1.getAsJsonObject().get(MyBase.TYPE_ACCESS).getAsString();
|
||||
return context.deserialize(json1, SubTypes.valueOf(type).getSubclass());
|
||||
}).create();
|
||||
SubType1 target = (SubType1) gson.fromJson(json, MyBase.class);
|
||||
assertEquals("abc", target.field1);
|
||||
|
@ -150,13 +149,8 @@ public class CustomDeserializerTest extends TestCase {
|
|||
|
||||
public void testCustomDeserializerReturnsNullForTopLevelObject() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapter(Base.class, new JsonDeserializer<Base>() {
|
||||
@Override
|
||||
public Base deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
return null;
|
||||
}
|
||||
}).create();
|
||||
.setLenient()
|
||||
.registerTypeAdapter(Base.class, (JsonDeserializer<Base>) (json, typeOfT, context) -> null).create();
|
||||
String json = "{baseName:'Base',subName:'SubRevised'}";
|
||||
Base target = gson.fromJson(json, Base.class);
|
||||
assertNull(target);
|
||||
|
@ -164,13 +158,8 @@ public class CustomDeserializerTest extends TestCase {
|
|||
|
||||
public void testCustomDeserializerReturnsNull() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapter(Base.class, new JsonDeserializer<Base>() {
|
||||
@Override
|
||||
public Base deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
return null;
|
||||
}
|
||||
}).create();
|
||||
.setLenient()
|
||||
.registerTypeAdapter(Base.class, (JsonDeserializer<Base>) (json, typeOfT, context) -> null).create();
|
||||
String json = "{base:{baseName:'Base',subName:'SubRevised'}}";
|
||||
ClassWithBaseField target = gson.fromJson(json, ClassWithBaseField.class);
|
||||
assertNull(target.base);
|
||||
|
@ -178,13 +167,8 @@ public class CustomDeserializerTest extends TestCase {
|
|||
|
||||
public void testCustomDeserializerReturnsNullForArrayElements() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapter(Base.class, new JsonDeserializer<Base>() {
|
||||
@Override
|
||||
public Base deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
return null;
|
||||
}
|
||||
}).create();
|
||||
.setLenient()
|
||||
.registerTypeAdapter(Base.class, (JsonDeserializer<Base>) (json, typeOfT, context) -> null).create();
|
||||
String json = "[{baseName:'Base'},{baseName:'Base'}]";
|
||||
Base[] target = gson.fromJson(json, Base[].class);
|
||||
assertNull(target[0]);
|
||||
|
@ -193,13 +177,8 @@ public class CustomDeserializerTest extends TestCase {
|
|||
|
||||
public void testCustomDeserializerReturnsNullForArrayElementsForArrayField() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapter(Base.class, new JsonDeserializer<Base>() {
|
||||
@Override
|
||||
public Base deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
return null;
|
||||
}
|
||||
}).create();
|
||||
.setLenient()
|
||||
.registerTypeAdapter(Base.class, (JsonDeserializer<Base>) (json, typeOfT, context) -> null).create();
|
||||
String json = "{bases:[{baseName:'Base'},{baseName:'Base'}]}";
|
||||
ClassWithBaseArray target = gson.fromJson(json, ClassWithBaseArray.class);
|
||||
assertNull(target.bases[0]);
|
||||
|
|
|
@ -261,7 +261,7 @@ public class CustomTypeAdaptersTest extends TestCase {
|
|||
}
|
||||
});
|
||||
Gson gson = gsonBuilder.create();
|
||||
String json = "'0123456789'";
|
||||
String json = "\"0123456789\"";
|
||||
byte[] actual = gson.fromJson(json, byte[].class);
|
||||
byte[] expected = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
for (int i = 0; i < actual.length; ++i) {
|
||||
|
@ -335,7 +335,7 @@ public class CustomTypeAdaptersTest extends TestCase {
|
|||
.registerTypeAdapter(StringHolder.class, new StringHolderTypeAdapter())
|
||||
.create();
|
||||
Type setType = new TypeToken<Set<StringHolder>>() {}.getType();
|
||||
Set<StringHolder> setOfHolders = gson.fromJson("['Jacob:Tomaw']", setType);
|
||||
Set<StringHolder> setOfHolders = gson.fromJson("[\"Jacob:Tomaw\"]", setType);
|
||||
assertEquals(1, setOfHolders.size());
|
||||
StringHolder foo = setOfHolders.iterator().next();
|
||||
assertEquals("Jacob", foo.part1);
|
||||
|
@ -373,7 +373,7 @@ public class CustomTypeAdaptersTest extends TestCase {
|
|||
.registerTypeAdapter(StringHolder.class, new StringHolderTypeAdapter())
|
||||
.create();
|
||||
Type mapType = new TypeToken<Map<String, StringHolder>>() {}.getType();
|
||||
Map<String, StringHolder> mapOfFoo = gson.fromJson("{'foo':'Jacob:Tomaw'}", mapType);
|
||||
Map<String, StringHolder> mapOfFoo = gson.fromJson("{\"foo\":\"Jacob:Tomaw\"}", mapType);
|
||||
assertEquals(1, mapOfFoo.size());
|
||||
StringHolder foo = mapOfFoo.get("foo");
|
||||
assertEquals("Jacob", foo.part1);
|
||||
|
@ -391,8 +391,9 @@ public class CustomTypeAdaptersTest extends TestCase {
|
|||
|
||||
public void testEnsureCustomDeserializerNotInvokedForNullValues() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapter(DataHolder.class, new DataHolderDeserializer())
|
||||
.create();
|
||||
.setLenient()
|
||||
.registerTypeAdapter(DataHolder.class, new DataHolderDeserializer())
|
||||
.create();
|
||||
String json = "{wrappedData:null}";
|
||||
DataHolderWrapper actual = gson.fromJson(json, DataHolderWrapper.class);
|
||||
assertNull(actual.wrappedData);
|
||||
|
@ -401,8 +402,8 @@ public class CustomTypeAdaptersTest extends TestCase {
|
|||
// Test created from Issue 352
|
||||
public void testRegisterHierarchyAdapterForDate() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.registerTypeHierarchyAdapter(Date.class, new DateTypeAdapter())
|
||||
.create();
|
||||
.registerTypeHierarchyAdapter(Date.class, new DateTypeAdapter())
|
||||
.create();
|
||||
assertEquals("0", gson.toJson(new Date(0)));
|
||||
assertEquals("0", gson.toJson(new java.sql.Date(0)));
|
||||
assertEquals(new Date(0), gson.fromJson("0", Date.class));
|
||||
|
|
|
@ -103,7 +103,7 @@ public class DefaultTypeAdaptersTest extends TestCase {
|
|||
} catch (UnsupportedOperationException expected) {
|
||||
}
|
||||
// Override with a custom type adapter for class.
|
||||
gson = new GsonBuilder().registerTypeAdapter(Class.class, new MyClassTypeAdapter()).create();
|
||||
gson = new GsonBuilder().setLenient().registerTypeAdapter(Class.class, new MyClassTypeAdapter()).create();
|
||||
assertEquals(String.class, gson.fromJson("java.lang.String", Class.class));
|
||||
}
|
||||
|
||||
|
@ -409,7 +409,7 @@ public class DefaultTypeAdaptersTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testDefaultCalendarDeserialization() throws Exception {
|
||||
Gson gson = new GsonBuilder().create();
|
||||
Gson gson = new Gson();
|
||||
String json = "{year:2009,month:2,dayOfMonth:11,hourOfDay:14,minute:29,second:23}";
|
||||
Calendar cal = gson.fromJson(json, Calendar.class);
|
||||
assertEquals(2009, cal.get(Calendar.YEAR));
|
||||
|
@ -433,7 +433,7 @@ public class DefaultTypeAdaptersTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testDefaultGregorianCalendarDeserialization() throws Exception {
|
||||
Gson gson = new GsonBuilder().create();
|
||||
Gson gson = new Gson();
|
||||
String json = "{year:2009,month:2,dayOfMonth:11,hourOfDay:14,minute:29,second:23}";
|
||||
GregorianCalendar cal = gson.fromJson(json, GregorianCalendar.class);
|
||||
assertEquals(2009, cal.get(Calendar.YEAR));
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Google Inc.
|
||||
*
|
||||
* 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.functional;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Functional tests for enums with Proguard.
|
||||
*
|
||||
* @author Young Cha
|
||||
*/
|
||||
public class EnumWithObfuscatedTest extends TestCase {
|
||||
private Gson gson;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
gson = new Gson();
|
||||
}
|
||||
|
||||
public enum Gender {
|
||||
@SerializedName("MAIL")
|
||||
MALE,
|
||||
|
||||
@SerializedName("FEMAIL")
|
||||
FEMALE
|
||||
}
|
||||
|
||||
public void testEnumClassWithObfuscated() {
|
||||
for (Gender enumConstant: Gender.class.getEnumConstants()) {
|
||||
try {
|
||||
Gender.class.getField(enumConstant.name());
|
||||
fail("Enum is not obfuscated");
|
||||
} catch (NoSuchFieldException ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
assertEquals(Gender.MALE, gson.fromJson("\"MAIL\"", Gender.class));
|
||||
assertEquals("\"MAIL\"", gson.toJson(Gender.MALE, Gender.class));
|
||||
}
|
||||
}
|
|
@ -38,6 +38,7 @@ public class ExposeFieldsTest extends TestCase {
|
|||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
gson = new GsonBuilder()
|
||||
.setLenient()
|
||||
.excludeFieldsWithoutExposeAnnotation()
|
||||
.registerTypeAdapter(SomeInterface.class, new SomeInterfaceInstanceCreator())
|
||||
.create();
|
||||
|
|
|
@ -40,12 +40,9 @@ public class InstanceCreatorTest extends TestCase {
|
|||
|
||||
public void testInstanceCreatorReturnsBaseType() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapter(Base.class, new InstanceCreator<Base>() {
|
||||
@Override public Base createInstance(Type type) {
|
||||
return new Base();
|
||||
}
|
||||
})
|
||||
.create();
|
||||
.setLenient()
|
||||
.registerTypeAdapter(Base.class, (InstanceCreator<Base>) type -> new Base())
|
||||
.create();
|
||||
String json = "{baseName:'BaseRevised',subName:'Sub'}";
|
||||
Base base = gson.fromJson(json, Base.class);
|
||||
assertEquals("BaseRevised", base.baseName);
|
||||
|
@ -53,12 +50,9 @@ public class InstanceCreatorTest extends TestCase {
|
|||
|
||||
public void testInstanceCreatorReturnsSubTypeForTopLevelObject() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapter(Base.class, new InstanceCreator<Base>() {
|
||||
@Override public Base createInstance(Type type) {
|
||||
return new Sub();
|
||||
}
|
||||
})
|
||||
.create();
|
||||
.setLenient()
|
||||
.registerTypeAdapter(Base.class, (InstanceCreator<Base>) type -> new Sub())
|
||||
.create();
|
||||
|
||||
String json = "{baseName:'Base',subName:'SubRevised'}";
|
||||
Base base = gson.fromJson(json, Base.class);
|
||||
|
@ -71,12 +65,9 @@ public class InstanceCreatorTest extends TestCase {
|
|||
|
||||
public void testInstanceCreatorReturnsSubTypeForField() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapter(Base.class, new InstanceCreator<Base>() {
|
||||
@Override public Base createInstance(Type type) {
|
||||
return new Sub();
|
||||
}
|
||||
})
|
||||
.create();
|
||||
.setLenient()
|
||||
.registerTypeAdapter(Base.class, (InstanceCreator<Base>) type -> new Sub())
|
||||
.create();
|
||||
String json = "{base:{baseName:'Base',subName:'SubRevised'}}";
|
||||
ClassWithBaseField target = gson.fromJson(json, ClassWithBaseField.class);
|
||||
assertTrue(target.base instanceof Sub);
|
||||
|
|
|
@ -48,7 +48,7 @@ public class InternationalizationTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testStringsWithUnicodeChineseCharactersEscapedDeserialization() throws Exception {
|
||||
String actual = gson.fromJson("'\\u597d\\u597d\\u597d'", String.class);
|
||||
String actual = gson.fromJson("\"\\u597d\\u597d\\u597d\"", String.class);
|
||||
assertEquals("\u597d\u597d\u597d", actual);
|
||||
}
|
||||
|
||||
|
|
|
@ -248,6 +248,7 @@ public final class Java17RecordTest {
|
|||
throw new AssertionError("not needed for test");
|
||||
}
|
||||
})
|
||||
.setLenient()
|
||||
.create();
|
||||
|
||||
String s = "{'aString': 's', 'aByte': 0}";
|
||||
|
|
|
@ -65,7 +65,7 @@ public class JavaUtilConcurrentAtomicTest extends TestCase {
|
|||
Gson gson = new GsonBuilder()
|
||||
.setLongSerializationPolicy(LongSerializationPolicy.STRING)
|
||||
.create();
|
||||
AtomicLongHolder target = gson.fromJson("{'value':'10'}", AtomicLongHolder.class);
|
||||
AtomicLongHolder target = gson.fromJson("{\"value\":\"10\"}", AtomicLongHolder.class);
|
||||
assertEquals(10, target.value.get());
|
||||
String json = gson.toJson(target);
|
||||
assertEquals("{\"value\":\"10\"}", json);
|
||||
|
@ -95,7 +95,7 @@ public class JavaUtilConcurrentAtomicTest extends TestCase {
|
|||
Gson gson = new GsonBuilder()
|
||||
.setLongSerializationPolicy(LongSerializationPolicy.STRING)
|
||||
.create();
|
||||
AtomicLongArray target = gson.fromJson("['10', '13', '14']", AtomicLongArray.class);
|
||||
AtomicLongArray target = gson.fromJson("[\"10\", \"13\", \"14\"]", AtomicLongArray.class);
|
||||
assertEquals(3, target.length());
|
||||
assertEquals(10, target.get(0));
|
||||
assertEquals(13, target.get(1));
|
||||
|
|
|
@ -36,7 +36,7 @@ public class JavaUtilTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testCurrency() throws Exception {
|
||||
CurrencyHolder target = gson.fromJson("{'value':'USD'}", CurrencyHolder.class);
|
||||
CurrencyHolder target = gson.fromJson("{\"value\":\"USD\"}", CurrencyHolder.class);
|
||||
assertEquals("USD", target.value.getCurrencyCode());
|
||||
String json = gson.toJson(target);
|
||||
assertEquals("{\"value\":\"USD\"}", json);
|
||||
|
@ -52,7 +52,7 @@ public class JavaUtilTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testProperties() {
|
||||
Properties props = gson.fromJson("{'a':'v1','b':'v2'}", Properties.class);
|
||||
Properties props = gson.fromJson("{\"a\":\"v1\",\"b\":\"v2\"}", Properties.class);
|
||||
assertEquals("v1", props.getProperty("a"));
|
||||
assertEquals("v2", props.getProperty("b"));
|
||||
String json = gson.toJson(props);
|
||||
|
|
|
@ -49,7 +49,7 @@ public final class JsonAdapterAnnotationOnClassesTest extends TestCase {
|
|||
// Also invoke the JsonAdapter javadoc sample
|
||||
json = gson.toJson(new User("Inderjeet", "Singh"));
|
||||
assertEquals("{\"name\":\"Inderjeet Singh\"}", json);
|
||||
User user = gson.fromJson("{'name':'Joel Leitch'}", User.class);
|
||||
User user = gson.fromJson("{\"name\":\"Joel Leitch\"}", User.class);
|
||||
assertEquals("Joel", user.firstName);
|
||||
assertEquals("Leitch", user.lastName);
|
||||
|
||||
|
@ -94,6 +94,7 @@ public final class JsonAdapterAnnotationOnClassesTest extends TestCase {
|
|||
}
|
||||
};
|
||||
Gson gson = new GsonBuilder()
|
||||
.setLenient()
|
||||
.registerTypeAdapter(A.class, serializer)
|
||||
.create();
|
||||
String json = gson.toJson(new A("abcd"));
|
||||
|
@ -113,6 +114,7 @@ public final class JsonAdapterAnnotationOnClassesTest extends TestCase {
|
|||
}
|
||||
};
|
||||
Gson gson = new GsonBuilder()
|
||||
.setLenient()
|
||||
.registerTypeAdapter(A.class, deserializer)
|
||||
.create();
|
||||
String json = gson.toJson(new A("abcd"));
|
||||
|
|
|
@ -57,12 +57,13 @@ public final class JsonAdapterAnnotationOnFieldsTest extends TestCase {
|
|||
.create();
|
||||
String json = gson.toJson(new Computer(new User("Inderjeet Singh")));
|
||||
assertEquals("{\"user\":\"RegisteredUserAdapter\"}", json);
|
||||
Computer computer = gson.fromJson("{'user':'Inderjeet Singh'}", Computer.class);
|
||||
Computer computer = gson.fromJson("{\"user\":\"Inderjeet Singh\"}", Computer.class);
|
||||
assertEquals("RegisteredUserAdapter", computer.user.name);
|
||||
}
|
||||
|
||||
public void testFieldAnnotationTakesPrecedenceOverRegisteredTypeAdapter() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.setLenient()
|
||||
.registerTypeAdapter(Part.class, new TypeAdapter<Part>() {
|
||||
@Override public void write(JsonWriter out, Part part) throws IOException {
|
||||
throw new AssertionError();
|
||||
|
|
|
@ -16,13 +16,7 @@
|
|||
|
||||
package com.google.gson.functional;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import com.google.gson.*;
|
||||
import com.google.gson.common.TestTypes.BagOfPrimitives;
|
||||
import com.google.gson.common.TestTypes.Nested;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
@ -123,9 +117,9 @@ public class JsonParserTest extends TestCase {
|
|||
|
||||
public void testExtraCommasInArrays() {
|
||||
Type type = new TypeToken<List<String>>() {}.getType();
|
||||
assertEquals(Arrays.asList("a", null, "b", null, null), gson.fromJson("[a,,b,,]", type));
|
||||
assertEquals(Arrays.asList(null, null), gson.fromJson("[,]", type));
|
||||
assertEquals(Arrays.asList("a", null), gson.fromJson("[a,]", type));
|
||||
assertEquals(Arrays.asList("a", "b"), gson.fromJson("[a,,b,,]", type));
|
||||
assertEquals(Arrays.asList(), gson.fromJson("[,]", type));
|
||||
assertEquals(Arrays.asList("a"), gson.fromJson("[a,]", type));
|
||||
}
|
||||
|
||||
public void testExtraCommasInMaps() {
|
||||
|
|
|
@ -33,7 +33,7 @@ public class LeniencyTest extends TestCase {
|
|||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
gson = new GsonBuilder().setLenient().create();
|
||||
gson = new Gson();
|
||||
}
|
||||
|
||||
public void testLenientFromJson() {
|
||||
|
|
|
@ -106,7 +106,7 @@ public class MapAsArrayTypeAdapterTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testMapWithTypeVariableDeserialization() {
|
||||
Gson gson = new GsonBuilder().enableComplexMapKeySerialization().create();
|
||||
Gson gson = new GsonBuilder().setLenient().enableComplexMapKeySerialization().create();
|
||||
String json = "{map:[[{x:2,y:3},{x:4,y:5}]]}";
|
||||
Type type = new TypeToken<PointWithProperty<Point>>(){}.getType();
|
||||
PointWithProperty<Point> map = gson.fromJson(json, type);
|
||||
|
|
|
@ -76,6 +76,17 @@ public class MapTest extends TestCase {
|
|||
assertEquals(2, target.get("b").intValue());
|
||||
}
|
||||
|
||||
public void testMapDuplicateKeyDeserialization() {
|
||||
Gson gsonWithDuplicateKeys = new GsonBuilder()
|
||||
.enableDuplicateMapKeyDeserialization()
|
||||
.create();
|
||||
Type typeOfMap = new TypeToken<Map<String,Integer>>(){}.getType();
|
||||
String json = "{\"a\":1,\"b\":2,\"b\":3}";
|
||||
Map<String,Integer> target = gsonWithDuplicateKeys.fromJson(json, typeOfMap);
|
||||
assertEquals(1, target.get("a").intValue());
|
||||
assertEquals(3, target.get("b").intValue());
|
||||
}
|
||||
|
||||
public void testObjectMapSerialization() {
|
||||
Map<String, Object> map = new LinkedHashMap<>();
|
||||
map.put("a", 1);
|
||||
|
@ -141,7 +152,7 @@ public class MapTest extends TestCase {
|
|||
assertEquals(123, map.get("null").intValue());
|
||||
assertNull(map.get(null));
|
||||
|
||||
map = gson.fromJson("{null:123}", typeOfMap);
|
||||
map = gson.fromJson("{'null':123}", typeOfMap);
|
||||
assertEquals(1, map.size());
|
||||
assertEquals(123, map.get("null").intValue());
|
||||
assertNull(map.get(null));
|
||||
|
|
|
@ -99,7 +99,7 @@ public class NullObjectAndFieldTest extends TestCase {
|
|||
*/
|
||||
public void testNullWrappedPrimitiveMemberDeserialization() {
|
||||
Gson gson = gsonBuilder.create();
|
||||
String json = "{'value':null}";
|
||||
String json = "{\"value\":null}";
|
||||
ClassWithNullWrappedPrimitive target = gson.fromJson(json, ClassWithNullWrappedPrimitive.class);
|
||||
assertNull(target.value);
|
||||
}
|
||||
|
@ -223,12 +223,8 @@ public class NullObjectAndFieldTest extends TestCase {
|
|||
|
||||
public void testCustomTypeAdapterPassesNullDesrialization() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapter(ObjectWithField.class, new JsonDeserializer<ObjectWithField>() {
|
||||
@Override public ObjectWithField deserialize(JsonElement json, Type type,
|
||||
JsonDeserializationContext context) {
|
||||
return context.deserialize(null, type);
|
||||
}
|
||||
}).create();
|
||||
.setLenient()
|
||||
.registerTypeAdapter(ObjectWithField.class, (JsonDeserializer<ObjectWithField>) (json, type, context) -> context.deserialize(null, type)).create();
|
||||
String json = "{value:'value1'}";
|
||||
ObjectWithField target = gson.fromJson(json, ObjectWithField.class);
|
||||
assertNull(target);
|
||||
|
|
|
@ -344,7 +344,7 @@ public class ObjectTest extends TestCase {
|
|||
return p.new Child();
|
||||
}
|
||||
}).create();
|
||||
String json = "{'value2':3}";
|
||||
String json = "{\"value2\":3}";
|
||||
Parent.Child c = gson.fromJson(json, Parent.Child.class);
|
||||
assertEquals(3, c.value2);
|
||||
}
|
||||
|
|
|
@ -16,10 +16,9 @@
|
|||
|
||||
package com.google.gson.functional;
|
||||
|
||||
import com.google.gson.*;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
|
||||
/**
|
||||
* Functional tests for Java Character values.
|
||||
*
|
||||
|
|
|
@ -18,11 +18,7 @@ package com.google.gson.functional;
|
|||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import com.google.gson.LongSerializationPolicy;
|
||||
import com.google.gson.*;
|
||||
import com.google.gson.internal.LazilyParsedNumber;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import java.io.Serializable;
|
||||
|
@ -100,7 +96,7 @@ public class PrimitiveTest extends TestCase {
|
|||
gson.fromJson("2147483648", byte.class);
|
||||
fail();
|
||||
} catch (JsonSyntaxException e) {
|
||||
assertEquals("java.lang.NumberFormatException: Expected an int but was 2147483648 at line 1 column 11 path $", e.getMessage());
|
||||
assertEquals("java.lang.NumberFormatException: Expected an int but was 2147483648 at line 1 column 11 (char '\0') path $", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,7 +141,7 @@ public class PrimitiveTest extends TestCase {
|
|||
gson.fromJson("2147483648", short.class);
|
||||
fail();
|
||||
} catch (JsonSyntaxException e) {
|
||||
assertEquals("java.lang.NumberFormatException: Expected an int but was 2147483648 at line 1 column 11 path $", e.getMessage());
|
||||
assertEquals("java.lang.NumberFormatException: Expected an int but was 2147483648 at line 1 column 11 (char '\0') path $", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -495,7 +491,7 @@ public class PrimitiveTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testDoubleNaNSerialization() {
|
||||
Gson gson = new GsonBuilder().serializeSpecialFloatingPointValues().create();
|
||||
Gson gson = new GsonBuilder().setLenient().serializeSpecialFloatingPointValues().create();
|
||||
double nan = Double.NaN;
|
||||
assertEquals("NaN", gson.toJson(nan));
|
||||
assertEquals("NaN", gson.toJson(Double.NaN));
|
||||
|
@ -521,7 +517,7 @@ public class PrimitiveTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testFloatNaNSerialization() {
|
||||
Gson gson = new GsonBuilder().serializeSpecialFloatingPointValues().create();
|
||||
Gson gson = new GsonBuilder().setLenient().serializeSpecialFloatingPointValues().create();
|
||||
float nan = Float.NaN;
|
||||
assertEquals("NaN", gson.toJson(nan));
|
||||
assertEquals("NaN", gson.toJson(Float.NaN));
|
||||
|
@ -555,7 +551,7 @@ public class PrimitiveTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testDoubleInfinitySerialization() {
|
||||
Gson gson = new GsonBuilder().serializeSpecialFloatingPointValues().create();
|
||||
Gson gson = new GsonBuilder().setLenient().serializeSpecialFloatingPointValues().create();
|
||||
double infinity = Double.POSITIVE_INFINITY;
|
||||
assertEquals("Infinity", gson.toJson(infinity));
|
||||
assertEquals("Infinity", gson.toJson(Double.POSITIVE_INFINITY));
|
||||
|
@ -581,7 +577,7 @@ public class PrimitiveTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testFloatInfinitySerialization() {
|
||||
Gson gson = new GsonBuilder().serializeSpecialFloatingPointValues().create();
|
||||
Gson gson = new GsonBuilder().setLenient().serializeSpecialFloatingPointValues().create();
|
||||
float infinity = Float.POSITIVE_INFINITY;
|
||||
assertEquals("Infinity", gson.toJson(infinity));
|
||||
assertEquals("Infinity", gson.toJson(Float.POSITIVE_INFINITY));
|
||||
|
@ -615,7 +611,7 @@ public class PrimitiveTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testNegativeInfinitySerialization() {
|
||||
Gson gson = new GsonBuilder().serializeSpecialFloatingPointValues().create();
|
||||
Gson gson = new GsonBuilder().setLenient().serializeSpecialFloatingPointValues().create();
|
||||
double negativeInfinity = Double.NEGATIVE_INFINITY;
|
||||
assertEquals("-Infinity", gson.toJson(negativeInfinity));
|
||||
assertEquals("-Infinity", gson.toJson(Double.NEGATIVE_INFINITY));
|
||||
|
@ -641,7 +637,7 @@ public class PrimitiveTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testNegativeInfinityFloatSerialization() {
|
||||
Gson gson = new GsonBuilder().serializeSpecialFloatingPointValues().create();
|
||||
Gson gson = new GsonBuilder().setLenient().serializeSpecialFloatingPointValues().create();
|
||||
float negativeInfinity = Float.NEGATIVE_INFINITY;
|
||||
assertEquals("-Infinity", gson.toJson(negativeInfinity));
|
||||
assertEquals("-Infinity", gson.toJson(Float.NEGATIVE_INFINITY));
|
||||
|
@ -693,7 +689,7 @@ public class PrimitiveTest extends TestCase {
|
|||
|
||||
String value = "String Blah Blah Blah...1, 2, 3";
|
||||
try {
|
||||
gson.fromJson(value, String.class);
|
||||
new Gson().fromJson(value, String.class);
|
||||
fail();
|
||||
} catch (JsonSyntaxException expected) { }
|
||||
}
|
||||
|
|
|
@ -30,69 +30,6 @@ public class ReflectionAccessTest {
|
|||
}
|
||||
}
|
||||
|
||||
private static Class<?> loadClassWithDifferentClassLoader(Class<?> c) throws Exception {
|
||||
URL url = c.getProtectionDomain().getCodeSource().getLocation();
|
||||
URLClassLoader classLoader = new URLClassLoader(new URL[] { url }, null);
|
||||
return classLoader.loadClass(c.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("removal") // java.lang.SecurityManager deprecation in Java 17
|
||||
public void testRestrictiveSecurityManager() throws Exception {
|
||||
// Must use separate class loader, otherwise permission is not checked, see Class.getDeclaredFields()
|
||||
Class<?> clazz = loadClassWithDifferentClassLoader(ClassWithPrivateMembers.class);
|
||||
|
||||
final Permission accessDeclaredMembers = new RuntimePermission("accessDeclaredMembers");
|
||||
final Permission suppressAccessChecks = new ReflectPermission("suppressAccessChecks");
|
||||
SecurityManager original = System.getSecurityManager();
|
||||
SecurityManager restrictiveManager = new SecurityManager() {
|
||||
@Override
|
||||
public void checkPermission(Permission perm) {
|
||||
if (accessDeclaredMembers.equals(perm)) {
|
||||
throw new SecurityException("Gson: no-member-access");
|
||||
}
|
||||
if (suppressAccessChecks.equals(perm)) {
|
||||
throw new SecurityException("Gson: no-suppress-access-check");
|
||||
}
|
||||
}
|
||||
};
|
||||
System.setSecurityManager(restrictiveManager);
|
||||
|
||||
try {
|
||||
Gson gson = new Gson();
|
||||
try {
|
||||
// Getting reflection based adapter should fail
|
||||
gson.getAdapter(clazz);
|
||||
fail();
|
||||
} catch (SecurityException e) {
|
||||
assertEquals("Gson: no-member-access", e.getMessage());
|
||||
}
|
||||
|
||||
final AtomicBoolean wasReadCalled = new AtomicBoolean(false);
|
||||
gson = new GsonBuilder()
|
||||
.registerTypeAdapter(clazz, new TypeAdapter<Object>() {
|
||||
@Override
|
||||
public void write(JsonWriter out, Object value) throws IOException {
|
||||
out.value("custom-write");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object read(JsonReader in) throws IOException {
|
||||
in.skipValue();
|
||||
wasReadCalled.set(true);
|
||||
return null;
|
||||
}}
|
||||
)
|
||||
.create();
|
||||
|
||||
assertEquals("\"custom-write\"", gson.toJson(null, clazz));
|
||||
assertNull(gson.fromJson("{}", clazz));
|
||||
assertTrue(wasReadCalled.get());
|
||||
} finally {
|
||||
System.setSecurityManager(original);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test serializing an instance of a non-accessible internal class, but where
|
||||
* Gson supports serializing one of its superinterfaces.
|
||||
|
|
|
@ -38,7 +38,7 @@ public class SecurityTest extends TestCase {
|
|||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
gsonBuilder = new GsonBuilder();
|
||||
gsonBuilder = new GsonBuilder().setLenient();
|
||||
}
|
||||
|
||||
public void testNonExecutableJsonSerialization() {
|
||||
|
|
|
@ -159,7 +159,7 @@ public final class StreamingTypeAdaptersTest extends TestCase {
|
|||
out.value(person.name + "," + person.age);
|
||||
}
|
||||
};
|
||||
Gson gson = new GsonBuilder().registerTypeAdapter(
|
||||
Gson gson = new GsonBuilder().setLenient().registerTypeAdapter(
|
||||
Person.class, typeAdapter).create();
|
||||
Truck truck = new Truck();
|
||||
truck.horsePower = 1.0D;
|
||||
|
@ -175,7 +175,7 @@ public final class StreamingTypeAdaptersTest extends TestCase {
|
|||
gson.fromJson(json, Truck.class);
|
||||
fail();
|
||||
} catch (JsonSyntaxException expected) {}
|
||||
gson = new GsonBuilder().registerTypeAdapter(Person.class, typeAdapter.nullSafe()).create();
|
||||
gson = new GsonBuilder().setLenient().registerTypeAdapter(Person.class, typeAdapter.nullSafe()).create();
|
||||
assertEquals("{\"horsePower\":1.0,\"passengers\":[null,\"jesse,30\"]}",
|
||||
gson.toJson(truck, Truck.class));
|
||||
truck = gson.fromJson(json, Truck.class);
|
||||
|
|
|
@ -52,6 +52,7 @@ public class TreeTypeAdaptersTest extends TestCase {
|
|||
@Override
|
||||
protected void setUp() {
|
||||
gson = new GsonBuilder()
|
||||
.setLenient()
|
||||
.registerTypeAdapter(Id.class, new IdTreeTypeAdapter())
|
||||
.create();
|
||||
course = new Course<>(COURSE_ID, 4,
|
||||
|
|
|
@ -34,6 +34,7 @@ import junit.framework.TestCase;
|
|||
public final class TypeAdapterPrecedenceTest extends TestCase {
|
||||
public void testNonstreamingFollowedByNonstreaming() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.setLenient()
|
||||
.registerTypeAdapter(Foo.class, newSerializer("serializer 1"))
|
||||
.registerTypeAdapter(Foo.class, newSerializer("serializer 2"))
|
||||
.registerTypeAdapter(Foo.class, newDeserializer("deserializer 1"))
|
||||
|
@ -45,6 +46,7 @@ public final class TypeAdapterPrecedenceTest extends TestCase {
|
|||
|
||||
public void testStreamingFollowedByStreaming() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.setLenient()
|
||||
.registerTypeAdapter(Foo.class, newTypeAdapter("type adapter 1"))
|
||||
.registerTypeAdapter(Foo.class, newTypeAdapter("type adapter 2"))
|
||||
.create();
|
||||
|
@ -54,6 +56,7 @@ public final class TypeAdapterPrecedenceTest extends TestCase {
|
|||
|
||||
public void testSerializeNonstreamingTypeAdapterFollowedByStreamingTypeAdapter() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.setLenient()
|
||||
.registerTypeAdapter(Foo.class, newSerializer("serializer"))
|
||||
.registerTypeAdapter(Foo.class, newDeserializer("deserializer"))
|
||||
.registerTypeAdapter(Foo.class, newTypeAdapter("type adapter"))
|
||||
|
@ -64,6 +67,7 @@ public final class TypeAdapterPrecedenceTest extends TestCase {
|
|||
|
||||
public void testStreamingFollowedByNonstreaming() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.setLenient()
|
||||
.registerTypeAdapter(Foo.class, newTypeAdapter("type adapter"))
|
||||
.registerTypeAdapter(Foo.class, newSerializer("serializer"))
|
||||
.registerTypeAdapter(Foo.class, newDeserializer("deserializer"))
|
||||
|
@ -74,6 +78,7 @@ public final class TypeAdapterPrecedenceTest extends TestCase {
|
|||
|
||||
public void testStreamingHierarchicalFollowedByNonstreaming() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.setLenient()
|
||||
.registerTypeHierarchyAdapter(Foo.class, newTypeAdapter("type adapter"))
|
||||
.registerTypeAdapter(Foo.class, newSerializer("serializer"))
|
||||
.registerTypeAdapter(Foo.class, newDeserializer("deserializer"))
|
||||
|
@ -89,11 +94,12 @@ public final class TypeAdapterPrecedenceTest extends TestCase {
|
|||
.registerTypeHierarchyAdapter(Foo.class, newDeserializer("deserializer"))
|
||||
.create();
|
||||
assertEquals("\"foo via type adapter\"", gson.toJson(new Foo("foo")));
|
||||
assertEquals("foo via type adapter", gson.fromJson("foo", Foo.class).name);
|
||||
assertEquals("foo via type adapter", gson.fromJson("\"foo\"", Foo.class).name);
|
||||
}
|
||||
|
||||
public void testStreamingHierarchicalFollowedByNonstreamingHierarchical() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.setLenient()
|
||||
.registerTypeHierarchyAdapter(Foo.class, newSerializer("serializer"))
|
||||
.registerTypeHierarchyAdapter(Foo.class, newDeserializer("deserializer"))
|
||||
.registerTypeHierarchyAdapter(Foo.class, newTypeAdapter("type adapter"))
|
||||
|
@ -104,6 +110,7 @@ public final class TypeAdapterPrecedenceTest extends TestCase {
|
|||
|
||||
public void testNonstreamingHierarchicalFollowedByNonstreaming() {
|
||||
Gson gson = new GsonBuilder()
|
||||
.setLenient()
|
||||
.registerTypeHierarchyAdapter(Foo.class, newSerializer("hierarchical"))
|
||||
.registerTypeHierarchyAdapter(Foo.class, newDeserializer("hierarchical"))
|
||||
.registerTypeAdapter(Foo.class, newSerializer("non hierarchical"))
|
||||
|
|
|
@ -29,6 +29,8 @@ import java.util.Arrays;
|
|||
import java.util.List;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import static org.junit.Assert.assertThrows;
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
public class JsonTreeReaderTest extends TestCase {
|
||||
public void testSkipValue_emptyJsonObject() throws IOException {
|
||||
|
@ -75,7 +77,7 @@ public class JsonTreeReaderTest extends TestCase {
|
|||
assertEquals(JsonToken.END_DOCUMENT, reader.peek());
|
||||
|
||||
assertEquals("$", reader.getPath());
|
||||
reader.skipValue();
|
||||
assertThrows("Attempt to skip led outside the document", IllegalStateException.class, reader::skipValue);
|
||||
assertEquals(JsonToken.END_DOCUMENT, reader.peek());
|
||||
assertEquals("$", reader.getPath());
|
||||
}
|
||||
|
@ -83,7 +85,7 @@ public class JsonTreeReaderTest extends TestCase {
|
|||
public void testSkipValue_atArrayEnd() throws IOException {
|
||||
JsonTreeReader reader = new JsonTreeReader(new JsonArray());
|
||||
reader.beginArray();
|
||||
reader.skipValue();
|
||||
assertThrows("Attempt to skip led outside its parent", IllegalStateException.class, reader::skipValue);
|
||||
assertEquals(JsonToken.END_DOCUMENT, reader.peek());
|
||||
assertEquals("$", reader.getPath());
|
||||
}
|
||||
|
@ -91,7 +93,7 @@ public class JsonTreeReaderTest extends TestCase {
|
|||
public void testSkipValue_atObjectEnd() throws IOException {
|
||||
JsonTreeReader reader = new JsonTreeReader(new JsonObject());
|
||||
reader.beginObject();
|
||||
reader.skipValue();
|
||||
assertThrows("Attempt to skip led outside its parent", IllegalStateException.class, reader::skipValue);
|
||||
assertEquals(JsonToken.END_DOCUMENT, reader.peek());
|
||||
assertEquals("$", reader.getPath());
|
||||
}
|
||||
|
@ -133,7 +135,8 @@ public class JsonTreeReaderTest extends TestCase {
|
|||
* {@code JsonReader} must be overridden.
|
||||
*/
|
||||
public void testOverrides() {
|
||||
List<String> ignoredMethods = Arrays.asList("setLenient(boolean)", "isLenient()");
|
||||
List<String> ignoredMethods = Arrays.asList("setLenient(boolean)", "isLenient()",
|
||||
"setSerializeSpecialFloatingPointValues(boolean)", "isSerializeSpecialFloatingPointValues()");
|
||||
MoreAsserts.assertOverridesMethods(JsonReader.class, JsonTreeReader.class, ignoredMethods);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -256,8 +256,12 @@ public final class JsonTreeWriterTest extends TestCase {
|
|||
* methods of {@code JsonWriter} must be overridden.
|
||||
*/
|
||||
public void testOverrides() {
|
||||
List<String> ignoredMethods = Arrays.asList("setLenient(boolean)", "isLenient()", "setIndent(java.lang.String)",
|
||||
"setHtmlSafe(boolean)", "isHtmlSafe()", "setSerializeNulls(boolean)", "getSerializeNulls()");
|
||||
List<String> ignoredMethods = Arrays.asList("setLenient(boolean)", "isLenient()",
|
||||
"setSerializeSpecialFloatingPointValues(boolean)", "isSerializeSpecialFloatingPointValues()",
|
||||
"setIndent(java.lang.String)",
|
||||
"setHtmlSafe(boolean)", "isHtmlSafe()",
|
||||
"setSerializeNulls(boolean)", "getSerializeNulls()",
|
||||
"setOmitQuotes(boolean)", "getOmitQuotes()");
|
||||
MoreAsserts.assertOverridesMethods(JsonWriter.class, JsonTreeWriter.class, ignoredMethods);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ public class SqlTypesGsonTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testDefaultSqlDateDeserialization() {
|
||||
String json = "'Dec 3, 2009'";
|
||||
String json = "\"Dec 3, 2009\"";
|
||||
java.sql.Date extracted = gson.fromJson(json, java.sql.Date.class);
|
||||
DefaultTypeAdaptersTest.assertEqualsDate(extracted, 2009, 11, 3);
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ public class SqlTypesGsonTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testDefaultSqlTimeDeserialization() {
|
||||
String json = "'1:18:02 PM'";
|
||||
String json = "\"1:18:02 PM\"";
|
||||
Time extracted = gson.fromJson(json, Time.class);
|
||||
DefaultTypeAdaptersTest.assertEqualsTime(extracted, 13, 18, 2);
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ public class SqlTypesGsonTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testDefaultSqlTimestampDeserialization() {
|
||||
String json = "'Dec 3, 2009 1:18:02 PM'";
|
||||
String json = "\"Dec 3, 2009 1:18:02 PM\"";
|
||||
Timestamp extracted = gson.fromJson(json, Timestamp.class);
|
||||
DefaultTypeAdaptersTest.assertEqualsDate(extracted, 2009, 11, 3);
|
||||
DefaultTypeAdaptersTest.assertEqualsTime(extracted, 13, 18, 2);
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright (C) 2010 Google Inc.
|
||||
*
|
||||
* 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.jf;
|
||||
|
||||
import com.google.gson.*;
|
||||
import com.google.gson.common.*;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gson.stream.*;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* @author Jesse Wilson
|
||||
*/
|
||||
public final class CommentsTest extends TestCase {
|
||||
|
||||
/**
|
||||
* Test for issue 212.
|
||||
*/
|
||||
public void testParseComments() {
|
||||
String json = "[\n"
|
||||
+ " // this is a comment\n"
|
||||
+ " \"a\",\n"
|
||||
+ " /* this is another comment */\n"
|
||||
+ " \"b\",\n"
|
||||
+ " # this is yet another comment\n"
|
||||
+ " \"c\"\n"
|
||||
+ "]";
|
||||
|
||||
List<String> abc = new GsonBuilder().setLenient().create().fromJson(json, new TypeToken<List<String>>() {}.getType());
|
||||
assertEquals(Arrays.asList("a", "b", "c"), abc);
|
||||
}
|
||||
|
||||
public void testWriteComments() throws IOException {
|
||||
String expectedJson = "// comment at file head\n"
|
||||
+ "[\n"
|
||||
+ " // comment directly after context\n"
|
||||
+ " \"a\",\n"
|
||||
+ " // comment before context\n"
|
||||
+ " {\n"
|
||||
+ " // comment directly after object context\n"
|
||||
+ " \"b\": \"c\",\n"
|
||||
+ " // comment before name, after value\n"
|
||||
+ " \"d\": \"e\"\n"
|
||||
+ " }\n"
|
||||
+ " // comment before context end\n"
|
||||
+ "]\n"
|
||||
+ "// comment behind the object";
|
||||
|
||||
StringWriter sw = new StringWriter();
|
||||
JsonWriter jw = new JsonWriter(sw);
|
||||
jw.setLenient(true);
|
||||
jw.setIndent(" ");
|
||||
|
||||
jw.comment("comment at file head")
|
||||
.beginArray()
|
||||
.comment("comment directly after context")
|
||||
.value("a")
|
||||
.comment("comment before context")
|
||||
.beginObject()
|
||||
.comment("comment directly after object context")
|
||||
.name("b").value("c")
|
||||
.comment("comment before name, after value")
|
||||
.name("d").value("e")
|
||||
.endObject()
|
||||
.comment("comment before context end")
|
||||
.endArray()
|
||||
.comment("comment behind the object");
|
||||
|
||||
jw.close();
|
||||
assertEquals(expectedJson, sw.toString());
|
||||
sw.close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package com.google.gson.jf;
|
||||
|
||||
import junit.framework.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class ExtraAssert {
|
||||
public static <T> void assertListEquals(List<T> expecteds, List<T> actuals) {
|
||||
TestCase.assertNotNull(expecteds);
|
||||
TestCase.assertNotNull(actuals);
|
||||
TestCase.assertEquals(expecteds.size(), actuals.size());
|
||||
for (int i = 0; i < expecteds.size(); i++) {
|
||||
TestCase.assertEquals(expecteds.get(i), actuals.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
public static class StringArrayBox {
|
||||
public String[] collection;
|
||||
}
|
||||
|
||||
public static class StringListBox {
|
||||
public List<String> collection;
|
||||
}
|
||||
|
||||
public static class IntListBox {
|
||||
public List<Integer> collection;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package com.google.gson.jf;
|
||||
|
||||
import com.google.gson.*;
|
||||
import junit.framework.*;
|
||||
|
||||
public class Json5Test extends TestCase {
|
||||
public void testShortExample() {
|
||||
// Taken from the official example
|
||||
assertTrue(new Gson().fromJson("{\n" +
|
||||
" // comments\n" +
|
||||
" unquoted: 'and you can quote me on that',\n" +
|
||||
" singleQuotes: 'I can use \"double quotes\" here',\n" +
|
||||
" lineBreaks: \"Look, Mom! \\\n" +
|
||||
"No \\\\n's!\",\n" +
|
||||
" hexadecimal: 0xdecaf,\n" +
|
||||
" leadingDecimalPoint: .8675309, andTrailing: 8675309.,\n" +
|
||||
" positiveSign: +1,\n" +
|
||||
" trailingComma: 'in objects', andIn: ['arrays',],\n" +
|
||||
" \"backwardsCompatible\": \"with JSON\"\n" + // The original includes a trailing comma here, that is not yet supported
|
||||
"}", ExampleModel.class).isDefault());
|
||||
}
|
||||
|
||||
public static class ExampleModel {
|
||||
public String unquoted;
|
||||
public String singleQuotes;
|
||||
public String lineBreaks;
|
||||
public Integer hexadecimal;
|
||||
public Double leadingDecimalPoint;
|
||||
public Double andTrailing;
|
||||
public Integer positiveSign;
|
||||
public String trailingComma;
|
||||
public String[] andIn;
|
||||
public String backwardsCompatible;
|
||||
|
||||
public boolean isDefault() {
|
||||
return unquoted.equals("and you can quote me on that")
|
||||
&& singleQuotes.equals("I can use \"double quotes\" here")
|
||||
&& lineBreaks.equals("Look, Mom! \nNo \\n's!")
|
||||
&& hexadecimal.equals(0xdecaf)
|
||||
&& leadingDecimalPoint.equals(.8675309)
|
||||
&& andTrailing.equals(8675309.)
|
||||
&& positiveSign.equals(1)
|
||||
&& trailingComma.equals("in objects")
|
||||
&& andIn.length == 1 && andIn[0].equals("arrays")
|
||||
&& backwardsCompatible.equals("with JSON");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package com.google.gson.jf;
|
||||
|
||||
import com.google.gson.*;
|
||||
import junit.framework.TestCase;
|
||||
import java.util.*;
|
||||
|
||||
import static com.google.gson.jf.ExtraAssert.*;
|
||||
|
||||
public class LenientCollectionCommaTest extends TestCase {
|
||||
private Gson lenient;
|
||||
private static final String json = "{\"collection\": [1, 2,, 3, , , 4, 5,]}";
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
lenient = new GsonBuilder().setLenient().create();
|
||||
}
|
||||
|
||||
public void testElementSkipping() {
|
||||
assertListEquals(List.of(1, 2, 3, 4, 5), lenient.fromJson(json, IntListBox.class).collection);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package com.google.gson.jf;
|
||||
|
||||
import com.google.gson.*;
|
||||
import junit.framework.TestCase;
|
||||
import java.util.*;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static com.google.gson.jf.ExtraAssert.*;
|
||||
|
||||
public class LenientCollectionTest extends TestCase {
|
||||
private Gson lenient;
|
||||
private Gson strict;
|
||||
private static final String json = "{\"collection\": \"example\"}";
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
lenient = new GsonBuilder().setLenient().create();
|
||||
strict = new GsonBuilder().create();
|
||||
}
|
||||
|
||||
public void testLenientArray() {
|
||||
assertArrayEquals(new String[] {"example"}, lenient.fromJson(json, StringArrayBox.class).collection);
|
||||
}
|
||||
|
||||
public void testLenientList() {
|
||||
assertListEquals(List.of("example"), lenient.fromJson(json, StringListBox.class).collection);
|
||||
}
|
||||
|
||||
public void testStrictArray() {
|
||||
try {
|
||||
strict.fromJson(json, StringArrayBox.class);
|
||||
fail("Strict Gson should not deserialize array without brackets");
|
||||
} catch (JsonParseException expected) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testStrictList() {
|
||||
try {
|
||||
strict.fromJson(json, StringListBox.class);
|
||||
fail("Strict Gson should not deserialize list without brackets");
|
||||
} catch (JsonParseException expected) {
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package com.google.gson.jf;
|
||||
|
||||
import com.google.gson.*;
|
||||
import junit.framework.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static com.google.gson.jf.ExtraAssert.*;
|
||||
|
||||
public class OmitQuotesTest extends TestCase {
|
||||
private Gson lenient;
|
||||
private Gson strict;
|
||||
private static final String lenientJson = "{collection:[\"example\"]}";
|
||||
private static final String strictJson = "{\"collection\":[\"example\"]}";
|
||||
private StringListBox slb;
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
lenient = new GsonBuilder().setOmitQuotes().create();
|
||||
strict = new GsonBuilder().create();
|
||||
slb = new StringListBox();
|
||||
slb.collection = List.of("example");
|
||||
}
|
||||
|
||||
public void testLenient() {
|
||||
assertEquals(lenientJson, lenient.toJson(slb));
|
||||
}
|
||||
|
||||
public void testStrict() {
|
||||
assertEquals(strictJson, strict.toJson(slb));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package com.google.gson.jf;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
public class ReadNullTest extends TestCase {
|
||||
public void testReadNull() throws IOException {
|
||||
Gson gson = new GsonBuilder().serializeNulls().setLenient().create();
|
||||
String exampleFile = "{\n // Yes\n \"value1\": 1024,\n \"value2\": null,\n \"value3\": 10\n}";
|
||||
try (Reader r = new StringReader(exampleFile); var jr = gson.newJsonReader(r)) {
|
||||
jr.beginObject();
|
||||
assertEquals("value1", jr.nextName());
|
||||
assertEquals(1024, jr.nextInt());
|
||||
assertEquals("value2", jr.nextName());
|
||||
jr.nextNull();
|
||||
assertEquals("value3", jr.nextName());
|
||||
assertEquals(10, jr.nextInt());
|
||||
jr.endObject();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -162,7 +162,7 @@ public class PerformanceTest extends TestCase {
|
|||
* Created in response to http://code.google.com/p/google-gson/issues/detail?id=96
|
||||
*/
|
||||
// Last I tested, Gson was able to deserialize a byte array of 11MB
|
||||
public void disable_testByteArrayDeserialization() {
|
||||
public void disabled_testByteArrayDeserialization() {
|
||||
for (int numElements = 10639296; true; numElements += 16384) {
|
||||
StringBuilder sb = new StringBuilder(numElements*2);
|
||||
sb.append("[");
|
||||
|
@ -218,7 +218,7 @@ public class PerformanceTest extends TestCase {
|
|||
System.out.printf("Deserialize classes avg time: %d ms\n", avg);
|
||||
}
|
||||
|
||||
public void disable_testLargeObjectSerializationAndDeserialization() {
|
||||
public void disabled_testLargeObjectSerializationAndDeserialization() {
|
||||
Map<String, Long> largeObject = new HashMap<>();
|
||||
for (long l = 0; l < 100000; l++) {
|
||||
largeObject.put("field" + l, l);
|
||||
|
@ -343,4 +343,4 @@ public class PerformanceTest extends TestCase {
|
|||
this.field = field;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ public class JsonAdapterNullSafeTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testNullSafeBugDeserialize() throws Exception {
|
||||
Device device = gson.fromJson("{'id':'ec57803e2'}", Device.class);
|
||||
Device device = gson.fromJson("{\"id\":\"ec57803e2\"}", Device.class);
|
||||
assertEquals("ec57803e2", device.id);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package com.google.gson.stream;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
|
@ -227,7 +228,8 @@ public class JsonReaderPathTest {
|
|||
reader.beginArray();
|
||||
assertEquals("$[0][0]", reader.getPreviousPath());
|
||||
assertEquals("$[0][0]", reader.getPath());
|
||||
reader.skipValue(); // skip end of array
|
||||
// skip end of array
|
||||
assertThrows("Attempt to skip led outside its parent", IllegalStateException.class, reader::skipValue);
|
||||
assertEquals("$[0]", reader.getPreviousPath());
|
||||
assertEquals("$[1]", reader.getPath());
|
||||
}
|
||||
|
@ -265,7 +267,9 @@ public class JsonReaderPathTest {
|
|||
reader.beginObject();
|
||||
assertEquals("$.a.", reader.getPreviousPath());
|
||||
assertEquals("$.a.", reader.getPath());
|
||||
reader.skipValue(); // skip end of object
|
||||
// skip end of object
|
||||
assertEquals(JsonToken.END_OBJECT, reader.peek());
|
||||
assertThrows("Attempt to skip led outside its parent", IllegalStateException.class, reader::skipValue);
|
||||
assertEquals("$.a", reader.getPreviousPath());
|
||||
assertEquals("$.a", reader.getPath());
|
||||
}
|
||||
|
@ -284,10 +288,7 @@ public class JsonReaderPathTest {
|
|||
reader.endArray();
|
||||
assertEquals("$", reader.getPreviousPath());
|
||||
assertEquals("$", reader.getPath());
|
||||
reader.skipValue();
|
||||
assertEquals("$", reader.getPreviousPath());
|
||||
assertEquals("$", reader.getPath());
|
||||
reader.skipValue();
|
||||
assertThrows("Attempt to skip led outside the document", IllegalStateException.class, reader::skipValue);
|
||||
assertEquals("$", reader.getPreviousPath());
|
||||
assertEquals("$", reader.getPath());
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import static com.google.gson.stream.JsonToken.NAME;
|
|||
import static com.google.gson.stream.JsonToken.NULL;
|
||||
import static com.google.gson.stream.JsonToken.NUMBER;
|
||||
import static com.google.gson.stream.JsonToken.STRING;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
|
@ -200,7 +201,7 @@ public final class JsonReaderTest extends TestCase {
|
|||
assertEquals(JsonToken.END_DOCUMENT, reader.peek());
|
||||
|
||||
assertEquals("$", reader.getPath());
|
||||
reader.skipValue();
|
||||
assertThrows("Attempt to skip led outside the document", IllegalStateException.class, reader::skipValue);
|
||||
assertEquals(JsonToken.END_DOCUMENT, reader.peek());
|
||||
assertEquals("$", reader.getPath());
|
||||
}
|
||||
|
@ -208,7 +209,7 @@ public final class JsonReaderTest extends TestCase {
|
|||
public void testSkipValueAtArrayEnd() throws IOException {
|
||||
JsonReader reader = new JsonReader(reader("[]"));
|
||||
reader.beginArray();
|
||||
reader.skipValue();
|
||||
assertThrows("Attempt to skip led outside its parent", IllegalStateException.class, reader::skipValue);
|
||||
assertEquals(JsonToken.END_DOCUMENT, reader.peek());
|
||||
assertEquals("$", reader.getPath());
|
||||
}
|
||||
|
@ -216,7 +217,7 @@ public final class JsonReaderTest extends TestCase {
|
|||
public void testSkipValueAtObjectEnd() throws IOException {
|
||||
JsonReader reader = new JsonReader(reader("{}"));
|
||||
reader.beginObject();
|
||||
reader.skipValue();
|
||||
assertThrows("Attempt to skip led outside its parent", IllegalStateException.class, reader::skipValue);
|
||||
assertEquals(JsonToken.END_DOCUMENT, reader.peek());
|
||||
assertEquals("$", reader.getPath());
|
||||
}
|
||||
|
@ -1229,7 +1230,7 @@ public final class JsonReaderTest extends TestCase {
|
|||
try {
|
||||
reader.nextNull();
|
||||
fail();
|
||||
} catch (IOException expected) {
|
||||
} catch (IllegalStateException expected) {
|
||||
}
|
||||
|
||||
reader = new JsonReader(reader("[,]"));
|
||||
|
@ -1246,14 +1247,14 @@ public final class JsonReaderTest extends TestCase {
|
|||
reader.setLenient(true);
|
||||
reader.beginArray();
|
||||
assertEquals(true, reader.nextBoolean());
|
||||
reader.nextNull();
|
||||
//reader.nextNull();
|
||||
assertEquals(true, reader.nextBoolean());
|
||||
reader.endArray();
|
||||
|
||||
reader = new JsonReader(reader("[,true]"));
|
||||
reader.setLenient(true);
|
||||
reader.beginArray();
|
||||
reader.nextNull();
|
||||
//reader.nextNull();
|
||||
assertEquals(true, reader.nextBoolean());
|
||||
reader.endArray();
|
||||
|
||||
|
@ -1261,14 +1262,14 @@ public final class JsonReaderTest extends TestCase {
|
|||
reader.setLenient(true);
|
||||
reader.beginArray();
|
||||
assertEquals(true, reader.nextBoolean());
|
||||
reader.nextNull();
|
||||
//reader.nextNull();
|
||||
reader.endArray();
|
||||
|
||||
reader = new JsonReader(reader("[,]"));
|
||||
reader.setLenient(true);
|
||||
reader.beginArray();
|
||||
reader.nextNull();
|
||||
reader.nextNull();
|
||||
//reader.nextNull();
|
||||
//reader.nextNull();
|
||||
reader.endArray();
|
||||
}
|
||||
|
||||
|
@ -1296,7 +1297,7 @@ public final class JsonReaderTest extends TestCase {
|
|||
try {
|
||||
reader.skipValue();
|
||||
fail();
|
||||
} catch (IOException expected) {
|
||||
} catch (IllegalStateException expected) {
|
||||
}
|
||||
|
||||
reader = new JsonReader(reader("[,]"));
|
||||
|
@ -1436,46 +1437,46 @@ public final class JsonReaderTest extends TestCase {
|
|||
}
|
||||
|
||||
public void testFailWithPosition() throws IOException {
|
||||
testFailWithPosition("Expected value at line 6 column 5 path $[1]",
|
||||
testFailWithPosition("Expected value at line 6 column 5 (char '}') path $[1]",
|
||||
"[\n\n\n\n\n\"a\",}]");
|
||||
}
|
||||
|
||||
public void testFailWithPositionGreaterThanBufferSize() throws IOException {
|
||||
String spaces = repeat(' ', 8192);
|
||||
testFailWithPosition("Expected value at line 6 column 5 path $[1]",
|
||||
testFailWithPosition("Expected value at line 6 column 5 (char '}') path $[1]",
|
||||
"[\n\n" + spaces + "\n\n\n\"a\",}]");
|
||||
}
|
||||
|
||||
public void testFailWithPositionOverSlashSlashEndOfLineComment() throws IOException {
|
||||
testFailWithPosition("Expected value at line 5 column 6 path $[1]",
|
||||
testFailWithPosition("Expected value at line 5 column 6 (char '}') path $[1]",
|
||||
"\n// foo\n\n//bar\r\n[\"a\",}");
|
||||
}
|
||||
|
||||
public void testFailWithPositionOverHashEndOfLineComment() throws IOException {
|
||||
testFailWithPosition("Expected value at line 5 column 6 path $[1]",
|
||||
testFailWithPosition("Expected value at line 5 column 6 (char '}') path $[1]",
|
||||
"\n# foo\n\n#bar\r\n[\"a\",}");
|
||||
}
|
||||
|
||||
public void testFailWithPositionOverCStyleComment() throws IOException {
|
||||
testFailWithPosition("Expected value at line 6 column 12 path $[1]",
|
||||
testFailWithPosition("Expected value at line 6 column 12 (char '}') path $[1]",
|
||||
"\n\n/* foo\n*\n*\r\nbar */[\"a\",}");
|
||||
}
|
||||
|
||||
public void testFailWithPositionOverQuotedString() throws IOException {
|
||||
testFailWithPosition("Expected value at line 5 column 3 path $[1]",
|
||||
testFailWithPosition("Expected value at line 5 column 3 (char '}') path $[1]",
|
||||
"[\"foo\nbar\r\nbaz\n\",\n }");
|
||||
}
|
||||
|
||||
public void testFailWithPositionOverUnquotedString() throws IOException {
|
||||
testFailWithPosition("Expected value at line 5 column 2 path $[1]", "[\n\nabcd\n\n,}");
|
||||
testFailWithPosition("Expected value at line 5 column 2 (char '}') path $[1]", "[\n\nabcd\n\n,}");
|
||||
}
|
||||
|
||||
public void testFailWithEscapedNewlineCharacter() throws IOException {
|
||||
testFailWithPosition("Expected value at line 5 column 3 path $[1]", "[\n\n\"\\\n\n\",}");
|
||||
testFailWithPosition("Expected value at line 5 column 3 (char '}') path $[1]", "[\n\n\"\\\n\n\",}");
|
||||
}
|
||||
|
||||
public void testFailWithPositionIsOffsetByBom() throws IOException {
|
||||
testFailWithPosition("Expected value at line 1 column 6 path $[1]",
|
||||
testFailWithPosition("Expected value at line 1 column 6 (char '}') path $[1]",
|
||||
"\ufeff[\"a\",}]");
|
||||
}
|
||||
|
||||
|
@ -1518,7 +1519,7 @@ public final class JsonReaderTest extends TestCase {
|
|||
reader.peek();
|
||||
fail();
|
||||
} catch (IOException expected) {
|
||||
assertEquals("Expected value at line 1 column 14 path $[1].a[2]", expected.getMessage());
|
||||
assertEquals("Expected value at line 1 column 14 (char '}') path $[1].a[2]", expected.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1785,7 +1786,7 @@ public final class JsonReaderTest extends TestCase {
|
|||
assertDocument("{\"name\"=>\"string\",", BEGIN_OBJECT, NAME, STRING, IOException.class);
|
||||
assertDocument("{\"name\"=>\"string\",\"name\"", BEGIN_OBJECT, NAME, STRING, NAME);
|
||||
assertDocument("[}", BEGIN_ARRAY, IOException.class);
|
||||
assertDocument("[,]", BEGIN_ARRAY, NULL, NULL, END_ARRAY);
|
||||
assertDocument("[,]", BEGIN_ARRAY, END_ARRAY);
|
||||
assertDocument("{", BEGIN_OBJECT, IOException.class);
|
||||
assertDocument("{\"name\"", BEGIN_OBJECT, NAME, IOException.class);
|
||||
assertDocument("{\"name\",", BEGIN_OBJECT, NAME, IOException.class);
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
# Options from Android Gradle Plugins
|
||||
# https://android.googlesource.com/platform/tools/base/+/refs/heads/studio-master-dev/build-system/gradle-core/src/main/resources/com/android/build/gradle
|
||||
-optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*
|
||||
-optimizationpasses 5
|
||||
-allowaccessmodification
|
||||
# On Windows mixed case class names might cause problems
|
||||
-dontusemixedcaseclassnames
|
||||
-keepattributes *Annotation*,Signature,InnerClasses,EnclosingMethod
|
||||
-keepclassmembers enum * {
|
||||
public static **[] values();
|
||||
public static ** valueOf(java.lang.String);
|
||||
}
|
||||
|
||||
-keep enum com.google.gson.functional.EnumWithObfuscatedTest$Gender
|
||||
-keep class com.google.gson.functional.EnumWithObfuscatedTest {
|
||||
public void test*();
|
||||
protected void setUp();
|
||||
}
|
||||
|
||||
-dontwarn com.google.gson.functional.EnumWithObfuscatedTest
|
||||
-dontwarn junit.framework.TestCase
|
||||
# Ignore notes about duplicate JDK classes
|
||||
-dontnote module-info,jdk.internal.**
|
|
@ -1,7 +1,7 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<groupId>io.gitlab.jfronny</groupId>
|
||||
<artifactId>gson-parent</artifactId>
|
||||
<version>2.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
@ -25,7 +25,7 @@
|
|||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<groupId>io.gitlab.jfronny</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
|
|
33
pom.xml
33
pom.xml
|
@ -3,7 +3,7 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<groupId>io.gitlab.jfronny</groupId>
|
||||
<artifactId>gson-parent</artifactId>
|
||||
<version>2.11-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
@ -21,7 +21,7 @@
|
|||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.release>7</maven.compiler.release>
|
||||
<javaVersion>11</javaVersion>
|
||||
</properties>
|
||||
|
||||
<scm>
|
||||
|
@ -33,8 +33,9 @@
|
|||
|
||||
<developers>
|
||||
<developer>
|
||||
<id>google</id>
|
||||
<organization>Google</organization>
|
||||
<organizationUrl>http://www.google.com</organizationUrl>
|
||||
<organizationUrl>https://www.google.com</organizationUrl>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
|
@ -50,12 +51,21 @@
|
|||
</license>
|
||||
</licenses>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>jf-maven</id>
|
||||
<url>https://maven.frohnmeyer-wds.de/artifacts</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<id>sonatype-nexus-staging</id>
|
||||
<name>Nexus Release Repository</name>
|
||||
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
|
||||
<id>jf-maven</id>
|
||||
<url>https://maven.frohnmeyer-wds.de/artifacts</url>
|
||||
</repository>
|
||||
<snapshotRepository>
|
||||
<id>jf-maven</id>
|
||||
<url>https://maven.frohnmeyer-wds.de/artifacts</url>
|
||||
</snapshotRepository>
|
||||
</distributionManagement>
|
||||
|
||||
<dependencyManagement>
|
||||
|
@ -79,7 +89,7 @@
|
|||
<configuration>
|
||||
<showWarnings>true</showWarnings>
|
||||
<showDeprecation>true</showDeprecation>
|
||||
<failOnWarning>true</failOnWarning>
|
||||
<failOnWarning>false</failOnWarning>
|
||||
<compilerArgs>
|
||||
<!-- Enable all warnings, except for ones which cause issues when building with newer JDKs, see also
|
||||
https://docs.oracle.com/en/java/javase/11/tools/javac.html -->
|
||||
|
@ -144,10 +154,11 @@
|
|||
<useReleaseProfile>false</useReleaseProfile>
|
||||
<releaseProfiles>release</releaseProfiles>
|
||||
<!-- Run custom goals to replace version references, see plugin configuration below -->
|
||||
<!-- Also run `package`; otherwise goals fail for modules depending on each; possibly
|
||||
same issue as https://issues.apache.org/jira/browse/MRELEASE-271 -->
|
||||
<!-- Also run `verify` to make sure tests still pass with new version number;
|
||||
also seems to be necessary because without `package`, goals fail for modules depending
|
||||
on each other; possibly same issue as https://issues.apache.org/jira/browse/MRELEASE-271 -->
|
||||
<preparationGoals>
|
||||
package -DskipTests
|
||||
clean verify
|
||||
antrun:run@replace-version-placeholders
|
||||
antrun:run@replace-old-version-references
|
||||
antrun:run@git-add-changed
|
||||
|
@ -210,6 +221,8 @@
|
|||
<target>
|
||||
<exec executable="git" dir="${project.basedir}" failonerror="true">
|
||||
<arg value="add" />
|
||||
<!-- Don't add (unrelated) not yet tracked files -->
|
||||
<arg value="--update" />
|
||||
<arg value="." />
|
||||
</exec>
|
||||
</target>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<groupId>io.gitlab.jfronny</groupId>
|
||||
<artifactId>gson-parent</artifactId>
|
||||
<version>2.11-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
@ -22,7 +22,7 @@
|
|||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<groupId>io.gitlab.jfronny</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
|
|
|
@ -45,6 +45,7 @@ public class ProtosWithComplexAndRepeatedFieldsTest extends TestCase {
|
|||
ProtoTypeAdapter.newBuilder()
|
||||
.setEnumSerialization(EnumSerialization.NUMBER)
|
||||
.build())
|
||||
.setLenient()
|
||||
.create();
|
||||
upperCamelGson =
|
||||
new GsonBuilder()
|
||||
|
@ -53,6 +54,7 @@ public class ProtosWithComplexAndRepeatedFieldsTest extends TestCase {
|
|||
.setFieldNameSerializationFormat(
|
||||
CaseFormat.LOWER_UNDERSCORE, CaseFormat.UPPER_CAMEL)
|
||||
.build())
|
||||
.setLenient()
|
||||
.create();
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ public class ProtosWithPrimitiveTypesTest extends TestCase {
|
|||
GeneratedMessageV3.class, ProtoTypeAdapter.newBuilder()
|
||||
.setEnumSerialization(EnumSerialization.NUMBER)
|
||||
.build())
|
||||
.setLenient()
|
||||
.create();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue