Perform minor code clean-up (#2544)

* Perform minor code clean-up

Notable changes:
- Replace most usages of `<code>` with `{@code ...}` in Javadoc
- Add proper summary sentence to `GsonBuilder.enableComplexMapKeySerialization`
- Extend documentation for `GsonBuilder.setDateFormat` methods
- Fix `TypeToken.isAssignableFrom(Type)` throwing AssertionError in some cases
  Maybe the method should not throw an exception in the first place, but it
  might not matter much since it is deprecated already anyway.
- Remove outdated `throws NumberFormatException` from internal
  `JsonReader.nextQuotedValue`; the behavior had been changed by
  85ebaf7c35
- Fix incorrect documentation on JsonScope fields
- Fix unit tests having 'expected' and 'actual' switched
- Use dedicated Truth methods instead of `isTrue()` / `isFalse()`
- Use common helper methods in JsonWriterTest to avoid duplication

* Implement `toString()` for ReflectionAccessFilter constants

* Address most of the review comments

* Add comment about `source.scm.tag=HEAD` warning

Actually it looks like the warning is not actually caused by usage of
`HEAD` as value, but rather because the project has a snapshot version
during development (which is expected though), see
https://github.com/apache/maven-artifact-plugin/blob/maven-artifact-plugin-3.5.0/src/main/java/org/apache/maven/plugins/artifact/buildinfo/BuildInfoWriter.java#L140

But this is not a problem either since during release a non-snapshot
version is used.
This commit is contained in:
Marcono1234 2023-11-19 18:01:19 +01:00 committed by GitHub
parent 6684726476
commit 08174e2019
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 215 additions and 265 deletions

View File

@ -41,13 +41,13 @@ public class GsonProguardExampleActivity extends Activity {
Cart cart = buildCart();
StringBuilder sb = new StringBuilder();
sb.append("Gson.toJson() example: \n");
sb.append(" Cart Object: ").append(cart).append("\n");
sb.append(" Cart JSON: ").append(gson.toJson(cart)).append("\n");
sb.append(" Cart Object: ").append(cart).append('\n');
sb.append(" Cart JSON: ").append(gson.toJson(cart)).append('\n');
sb.append("\n\nGson.fromJson() example: \n");
String json = "{buyer:'Happy Camper',creditCard:'4111-1111-1111-1111',"
+ "lineItems:[{name:'nails',priceInMicros:100000,quantity:100,currencyCode:'USD'}]}";
sb.append("Cart JSON: ").append(json).append("\n");
sb.append("Cart Object: ").append(gson.fromJson(json, Cart.class)).append("\n");
sb.append("Cart JSON: ").append(json).append('\n');
sb.append("Cart Object: ").append(gson.fromJson(json, Cart.class)).append('\n');
tv.setText(sb.toString());
tv.invalidate();
}

View File

@ -216,9 +216,9 @@ public final class Gson {
* following settings:
*
* <ul>
* <li>The JSON generated by <code>toJson</code> methods is in compact representation. This
* means that all the unneeded white-space is removed. You can change this behavior with
* {@link GsonBuilder#setPrettyPrinting()}.
* <li>The JSON generated by {@code toJson} methods is in compact representation. This means
* that all the unneeded white-space is removed. You can change this behavior with {@link
* GsonBuilder#setPrettyPrinting()}.
* <li>When the JSON generated contains more than one line, the kind of newline and indent to
* use can be configured with {@link GsonBuilder#setFormattingStyle(FormattingStyle)}.
* <li>The generated JSON omits all the fields that are null. Note that nulls in arrays are kept
@ -240,13 +240,12 @@ public final class Gson {
* <li>By default, Gson ignores the {@link com.google.gson.annotations.Since} annotation. You
* can enable Gson to use this annotation through {@link GsonBuilder#setVersion(double)}.
* <li>The default field naming policy for the output JSON is same as in Java. So, a Java class
* field <code>versionNumber</code> will be output as <code>&quot;versionNumber&quot;</code>
* in JSON. The same rules are applied for mapping incoming JSON to the Java classes. You
* can change this policy through {@link
* GsonBuilder#setFieldNamingPolicy(FieldNamingPolicy)}.
* <li>By default, Gson excludes <code>transient</code> or <code>static</code> fields from
* consideration for serialization and deserialization. You can change this behavior through
* {@link GsonBuilder#excludeFieldsWithModifiers(int...)}.
* field {@code versionNumber} will be output as {@code "versionNumber"} in JSON. The same
* rules are applied for mapping incoming JSON to the Java classes. You can change this
* policy through {@link GsonBuilder#setFieldNamingPolicy(FieldNamingPolicy)}.
* <li>By default, Gson excludes {@code transient} or {@code static} fields from consideration
* for serialization and deserialization. You can change this behavior through {@link
* GsonBuilder#excludeFieldsWithModifiers(int...)}.
* <li>No explicit strictness is set. You can change this by calling {@link
* GsonBuilder#setStrictness(Strictness)}.
* </ul>
@ -665,8 +664,8 @@ public final class Gson {
* is an example:
*
* <p>Let's say we want to write a type adapter that counts the number of objects being read from
* or written to JSON. We can achieve this by writing a type adapter factory that uses the <code>
* getDelegateAdapter</code> method:
* or written to JSON. We can achieve this by writing a type adapter factory that uses the {@code
* getDelegateAdapter} method:
*
* <pre>{@code
* class StatsTypeAdapterFactory implements TypeAdapterFactory {

View File

@ -227,8 +227,8 @@ public final class GsonBuilder {
}
/**
* Configure Gson to serialize null fields. By default, Gson omits all fields that are null during
* serialization.
* Configures Gson to serialize null fields. By default, Gson omits all fields that are null
* during serialization.
*
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.2
@ -240,10 +240,11 @@ public final class GsonBuilder {
}
/**
* Enabling this feature will only change the serialized form if the map key is a complex type
* (i.e. non-primitive) in its <strong>serialized</strong> JSON form. The default implementation
* of map serialization uses {@code toString()} on the key; however, when this is called then one
* of the following cases apply:
* Configures Gson to serialize {@code Map} objects with complex keys as JSON arrays. Enabling
* this feature will only change the serialized form if the map key is a complex type (i.e.
* non-primitive) in its <strong>serialized</strong> JSON form. The default implementation of map
* serialization uses {@code toString()} on the key; however, when this is called then one of the
* following cases apply:
*
* <p><b>Maps as JSON objects</b>
*
@ -622,23 +623,24 @@ public final class GsonBuilder {
}
/**
* Configures Gson to serialize {@code Date} objects according to the style value provided. You
* can call this method or {@link #setDateFormat(String)} multiple times, but only the last
* invocation will be used to decide the serialization format.
* Configures Gson to serialize {@code Date} objects according to the date style value provided.
* You can call this method or {@link #setDateFormat(String)} multiple times, but only the last
* invocation will be used to decide the serialization format. This methods leaves the current
* 'time style' unchanged.
*
* <p>Note that this style value should be one of the predefined constants in the {@code
* DateFormat} class. See the documentation in {@link java.text.DateFormat} for more information
* on the valid style constants.
* <p>Note that this style value should be one of the predefined constants in the {@link
* DateFormat} class, such as {@link DateFormat#MEDIUM}. See the documentation of the {@link
* DateFormat} class for more information on the valid style constants.
*
* @param style the predefined date style that date objects will be serialized/deserialized
* @param dateStyle the predefined date style that date objects will be serialized/deserialized
* to/from
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @throws IllegalArgumentException if the style is invalid
* @since 1.2
*/
@CanIgnoreReturnValue
public GsonBuilder setDateFormat(int style) {
this.dateStyle = checkDateFormatStyle(style);
public GsonBuilder setDateFormat(int dateStyle) {
this.dateStyle = checkDateFormatStyle(dateStyle);
this.datePattern = null;
return this;
}
@ -648,9 +650,9 @@ public final class GsonBuilder {
* can call this method or {@link #setDateFormat(String)} multiple times, but only the last
* invocation will be used to decide the serialization format.
*
* <p>Note that this style value should be one of the predefined constants in the {@code
* DateFormat} class. See the documentation in {@link java.text.DateFormat} for more information
* on the valid style constants.
* <p>Note that this style value should be one of the predefined constants in the {@link
* DateFormat} class, such as {@link DateFormat#MEDIUM}. See the documentation of the {@link
* DateFormat} class for more information on the valid style constants.
*
* @param dateStyle the predefined date style that date objects will be serialized/deserialized
* to/from

View File

@ -117,6 +117,11 @@ public interface ReflectionAccessFilter {
? FilterResult.BLOCK_INACCESSIBLE
: FilterResult.INDECISIVE;
}
@Override
public String toString() {
return "ReflectionAccessFilter#BLOCK_INACCESSIBLE_JAVA";
}
};
/**
@ -143,6 +148,11 @@ public interface ReflectionAccessFilter {
? FilterResult.BLOCK_ALL
: FilterResult.INDECISIVE;
}
@Override
public String toString() {
return "ReflectionAccessFilter#BLOCK_ALL_JAVA";
}
};
/**
@ -169,6 +179,11 @@ public interface ReflectionAccessFilter {
? FilterResult.BLOCK_ALL
: FilterResult.INDECISIVE;
}
@Override
public String toString() {
return "ReflectionAccessFilter#BLOCK_ALL_ANDROID";
}
};
/**
@ -196,6 +211,11 @@ public interface ReflectionAccessFilter {
? FilterResult.BLOCK_ALL
: FilterResult.INDECISIVE;
}
@Override
public String toString() {
return "ReflectionAccessFilter#BLOCK_ALL_PLATFORM";
}
};
/**

View File

@ -68,11 +68,11 @@ import java.io.Writer;
* #write(JsonWriter,Object) write()} must write exactly one value. For primitive types this is
* means readers should make exactly one call to {@code nextBoolean()}, {@code nextDouble()}, {@code
* nextInt()}, {@code nextLong()}, {@code nextString()} or {@code nextNull()}. Writers should make
* exactly one call to one of <code>value()</code> or <code>nullValue()</code>. For arrays, type
* adapters should start with a call to {@code beginArray()}, convert all elements, and finish with
* a call to {@code endArray()}. For objects, they should start with {@code beginObject()}, convert
* the object, and finish with {@code endObject()}. Failing to convert a value or converting too
* many values may cause the application to crash.
* exactly one call to one of {@code value()} or {@code nullValue()}. For arrays, type adapters
* should start with a call to {@code beginArray()}, convert all elements, and finish with a call to
* {@code endArray()}. For objects, they should start with {@code beginObject()}, convert the
* object, and finish with {@code endObject()}. Failing to convert a value or converting too many
* values may cause the application to crash.
*
* <p>Type adapters should be prepared to read null from the stream and write it to the stream.
* Alternatively, they should use {@link #nullSafe()} method while registering the type adapter with

View File

@ -200,7 +200,7 @@ public class TypeToken<T> {
return rawType.isAssignableFrom($Gson$Types.getRawType(from))
&& isAssignableFrom(from, (GenericArrayType) type);
} else {
throw buildUnexpectedTypeError(
throw buildUnsupportedTypeException(
type, Class.class, ParameterizedType.class, GenericArrayType.class);
}
}
@ -309,10 +309,11 @@ public class TypeToken<T> {
return false;
}
private static AssertionError buildUnexpectedTypeError(Type token, Class<?>... expected) {
private static IllegalArgumentException buildUnsupportedTypeException(
Type token, Class<?>... expected) {
// Build exception message
StringBuilder exceptionMessage = new StringBuilder("Unexpected type. Expected one of: ");
StringBuilder exceptionMessage = new StringBuilder("Unsupported type, expected one of: ");
for (Class<?> clazz : expected) {
exceptionMessage.append(clazz.getName()).append(", ");
}
@ -320,10 +321,9 @@ public class TypeToken<T> {
.append("but got: ")
.append(token.getClass().getName())
.append(", for type token: ")
.append(token.toString())
.append('.');
.append(token.toString());
return new AssertionError(exceptionMessage.toString());
return new IllegalArgumentException(exceptionMessage.toString());
}
/**

View File

@ -1056,7 +1056,6 @@ public class JsonReader implements Closeable {
* consumes the closing quote, but does not include it in the returned string.
*
* @param quote either ' or ".
* @throws NumberFormatException if any unicode escape sequences are malformed.
*/
private String nextQuotedValue(char quote) throws IOException {
// Like nextNonWhitespace, this uses locals 'p' and 'l' to save inner-loop field access.
@ -1527,7 +1526,7 @@ public class JsonReader implements Closeable {
}
}
private void checkLenient() throws IOException {
private void checkLenient() throws MalformedJsonException {
if (strictness != Strictness.LENIENT) {
throw syntaxError(
"Use JsonReader.setStrictness(Strictness.LENIENT) to accept malformed JSON");
@ -1655,7 +1654,7 @@ public class JsonReader implements Closeable {
* backslash. The backslash '\' should have already been read. This supports both Unicode escapes
* "u000A" and two-character escapes "\n".
*
* @throws MalformedJsonException if any Unicode escape sequences are malformed.
* @throws MalformedJsonException if the escape sequence is malformed
*/
@SuppressWarnings("fallthrough")
private char readEscapeCharacter() throws IOException {
@ -1725,10 +1724,10 @@ public class JsonReader implements Closeable {
}
/**
* Throws a new IO exception with the given message and a context snippet with this reader's
* content.
* Throws a new {@link MalformedJsonException} with the given message and information about the
* current location.
*/
private IOException syntaxError(String message) throws IOException {
private MalformedJsonException syntaxError(String message) throws MalformedJsonException {
throw new MalformedJsonException(
message + locationString() + "\nSee " + TroubleshootingGuide.createUrl("malformed-json"));
}

View File

@ -24,28 +24,25 @@ package com.google.gson.stream;
*/
final class JsonScope {
/** An array with no elements requires no separators or newlines before it is closed. */
/** An array with no elements requires no separator before the next element. */
static final int EMPTY_ARRAY = 1;
/** An array with at least one value requires a comma and newline before the next element. */
/** An array with at least one value requires a separator before the next element. */
static final int NONEMPTY_ARRAY = 2;
/** An object with no name/value pairs requires no separators or newlines before it is closed. */
/** An object with no name/value pairs requires no separator before the next element. */
static final int EMPTY_OBJECT = 3;
/** An object whose most recent element is a key. The next element must be a value. */
static final int DANGLING_NAME = 4;
/**
* An object with at least one name/value pair requires a comma and newline before the next
* element.
*/
/** An object with at least one name/value pair requires a separator before the next element. */
static final int NONEMPTY_OBJECT = 5;
/** No object or array has been started. */
/** No top-level value has been started yet. */
static final int EMPTY_DOCUMENT = 6;
/** A document with at an array or object. */
/** A top-level value has already been started. */
static final int NONEMPTY_DOCUMENT = 7;
/** A document that's been closed and cannot be accessed. */

View File

@ -356,9 +356,9 @@ public class JsonWriter implements Closeable, Flushable {
/**
* Configures this writer to emit JSON that's safe for direct inclusion in HTML and XML documents.
* This escapes the HTML characters {@code <}, {@code >}, {@code &} and {@code =} before writing
* them to the stream. Without this setting, your XML/HTML encoder should replace these characters
* with the corresponding escape sequences.
* This escapes the HTML characters {@code <}, {@code >}, {@code &}, {@code =} and {@code '}
* before writing them to the stream. Without this setting, your XML/HTML encoder should replace
* these characters with the corresponding escape sequences.
*/
public final void setHtmlSafe(boolean htmlSafe) {
this.htmlSafe = htmlSafe;

View File

@ -297,7 +297,7 @@ public class JsonPrimitiveTest {
new JsonPrimitive(new BigInteger("0")), new JsonPrimitive(0));
MoreAsserts.assertEqualsAndHashCode(new JsonPrimitive(0), new JsonPrimitive(0L));
MoreAsserts.assertEqualsAndHashCode(
new JsonPrimitive(new BigInteger("0")), new JsonPrimitive(0));
new JsonPrimitive(new BigDecimal("0")), new JsonPrimitive(0));
MoreAsserts.assertEqualsAndHashCode(
new JsonPrimitive(Float.NaN), new JsonPrimitive(Double.NaN));
}

View File

@ -74,11 +74,9 @@ public final class MixedStreamTest {
JsonReader jsonReader = new JsonReader(stringReader);
jsonReader.beginArray();
// actual and expected object are inverted in the test.
// gson.fromJson(jsonReader, Car.class) as arg of assertThat() cause an ambiguous method call
assertThat(BLUE_MUSTANG).isEqualTo(gson.fromJson(jsonReader, Car.class));
assertThat(BLACK_BMW).isEqualTo(gson.fromJson(jsonReader, Car.class));
assertThat(RED_MIATA).isEqualTo(gson.fromJson(jsonReader, Car.class));
assertThat(gson.<Car>fromJson(jsonReader, Car.class)).isEqualTo(BLUE_MUSTANG);
assertThat(gson.<Car>fromJson(jsonReader, Car.class)).isEqualTo(BLACK_BMW);
assertThat(gson.<Car>fromJson(jsonReader, Car.class)).isEqualTo(RED_MIATA);
jsonReader.endArray();
}

View File

@ -1,42 +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;
/**
* This is a configurable {@link ExclusionStrategy} that can be used for unit testing.
*
* @author Joel Leitch
*/
final class MockExclusionStrategy implements ExclusionStrategy {
private final boolean skipClass;
private final boolean skipField;
public MockExclusionStrategy(boolean skipClass, boolean skipField) {
this.skipClass = skipClass;
this.skipField = skipField;
}
@Override
public boolean shouldSkipField(FieldAttributes f) {
return skipField;
}
@Override
public boolean shouldSkipClass(Class<?> clazz) {
return skipClass;
}
}

View File

@ -24,6 +24,8 @@ import java.lang.reflect.Method;
/**
* Handles type conversion from some object to some primitive (or primitive wrapper instance).
*
* <p>Used by {@link ParameterizedTypeFixtures.MyParameterizedTypeAdapter}.
*
* @author Joel Leitch
*/
final class PrimitiveTypeAdapter {

View File

@ -237,8 +237,8 @@ public class CollectionTest {
target.add(objB);
String result = gson.toJson(target);
assertThat(result.startsWith("[")).isTrue();
assertThat(result.endsWith("]")).isTrue();
assertThat(result).startsWith("[");
assertThat(result).endsWith("]");
for (BagOfPrimitives obj : target) {
assertThat(result).contains(obj.getExpectedJson());
}
@ -290,10 +290,8 @@ public class CollectionTest {
for (Object bag1 : target) {
// Gson 2.0 converts raw objects into maps
@SuppressWarnings("unchecked")
Map<String, Object> values = (Map<String, Object>) bag1;
assertThat(values.containsValue(10.0)).isTrue();
assertThat(values.containsValue(20.0)).isTrue();
assertThat(values.containsValue("stringValue")).isTrue();
Map<String, Object> map = (Map<String, Object>) bag1;
assertThat(map.values()).containsExactly(10.0, 20.0, false, "stringValue");
}
}

View File

@ -82,7 +82,7 @@ public class EscapingTest {
BagOfPrimitives target = new BagOfPrimitives(1L, 1, true, "test' / w'ith\" / \\ <script>");
String escapedJsonForm = escapeHtmlGson.toJson(target);
String nonEscapedJsonForm = noEscapeHtmlGson.toJson(target);
assertThat(escapedJsonForm.equals(nonEscapedJsonForm)).isFalse();
assertThat(escapedJsonForm).isNotEqualTo(nonEscapedJsonForm);
assertThat(noEscapeHtmlGson.fromJson(escapedJsonForm, BagOfPrimitives.class)).isEqualTo(target);
assertThat(escapeHtmlGson.fromJson(nonEscapedJsonForm, BagOfPrimitives.class))

View File

@ -74,10 +74,10 @@ public class InstanceCreatorTest {
String json = "{baseName:'Base',subName:'SubRevised'}";
Base base = gson.fromJson(json, Base.class);
assertThat(base instanceof Sub).isTrue();
assertThat(base).isInstanceOf(Sub.class);
Sub sub = (Sub) base;
assertThat("SubRevised".equals(sub.subName)).isFalse();
assertThat(sub.subName).isNotEqualTo("SubRevised");
assertThat(sub.subName).isEqualTo(Sub.SUB_NAME);
}
@ -96,7 +96,7 @@ public class InstanceCreatorTest {
.create();
String json = "{base:{baseName:'Base',subName:'SubRevised'}}";
ClassWithBaseField target = gson.fromJson(json, ClassWithBaseField.class);
assertThat(target.base instanceof Sub).isTrue();
assertThat(target.base).isInstanceOf(Sub.class);
assertThat(((Sub) target.base).subName).isEqualTo(Sub.SUB_NAME);
}

View File

@ -134,11 +134,11 @@ public class JsonParserTest {
@Test
public void testExtraCommasInArrays() {
Type type = new TypeToken<List<String>>() {}.getType();
assertThat(Arrays.asList("a", null, "b", null, null))
.isEqualTo(gson.fromJson("[a,,b,,]", type));
assertThat(Arrays.asList(null, null)).isEqualTo(gson.fromJson("[,]", type));
assertThat(Arrays.asList("a", null)).isEqualTo(gson.fromJson("[a,]", type));
TypeToken<List<String>> type = new TypeToken<>() {};
assertThat(gson.fromJson("[a,,b,,]", type))
.isEqualTo(Arrays.asList("a", null, "b", null, null));
assertThat(gson.fromJson("[,]", type)).isEqualTo(Arrays.asList(null, null));
assertThat(gson.fromJson("[a,]", type)).isEqualTo(Arrays.asList("a", null));
}
@Test

View File

@ -589,8 +589,7 @@ public class MapTest {
Map<String, String> map = new LinkedHashMap<>();
map.put("2,3", "a");
map.put("5,7", "b");
assertThat(map)
.isEqualTo(gson.fromJson(json, new TypeToken<Map<String, String>>() {}.getType()));
assertThat(gson.fromJson(json, new TypeToken<Map<String, String>>() {})).isEqualTo(map);
}
@Test
@ -599,8 +598,7 @@ public class MapTest {
Map<Double, String> map = new LinkedHashMap<>();
map.put(2.3, "a");
map.put(5.7, "b");
assertThat(map)
.isEqualTo(gson.fromJson(json, new TypeToken<Map<Double, String>>() {}.getType()));
assertThat(gson.fromJson(json, new TypeToken<Map<Double, String>>() {})).isEqualTo(map);
}
@Test
@ -609,8 +607,7 @@ public class MapTest {
Map<Boolean, String> map = new LinkedHashMap<>();
map.put(true, "a");
map.put(false, "b");
assertThat(map)
.isEqualTo(gson.fromJson(json, new TypeToken<Map<Boolean, String>>() {}.getType()));
assertThat(gson.fromJson(json, new TypeToken<Map<Boolean, String>>() {})).isEqualTo(map);
}
@Test
@ -634,14 +631,14 @@ public class MapTest {
}
@Test
public void testDeerializeMapOfMaps() {
Type type = new TypeToken<Map<String, Map<String, String>>>() {}.getType();
public void testDeserializeMapOfMaps() {
TypeToken<Map<String, Map<String, String>>> type = new TypeToken<>() {};
Map<String, Map<String, String>> map =
newMap(
"a", newMap("ka1", "va1", "ka2", "va2"),
"b", newMap("kb1", "vb1", "kb2", "vb2"));
String json = "{'a':{'ka1':'va1','ka2':'va2'},'b':{'kb1':'vb1','kb2':'vb2'}}";
assertThat(map).isEqualTo(gson.fromJson(json, type));
assertThat(gson.fromJson(json, type)).isEqualTo(map);
}
private <K, V> Map<K, V> newMap(K key1, V value1, K key2, V value2) {
@ -657,8 +654,7 @@ public class MapTest {
Map<Double, String> map = new LinkedHashMap<>();
map.put(2.3, "a");
JsonElement tree = JsonParser.parseString(json);
assertThat(map)
.isEqualTo(gson.fromJson(tree, new TypeToken<Map<Double, String>>() {}.getType()));
assertThat(gson.fromJson(tree, new TypeToken<Map<Double, String>>() {})).isEqualTo(map);
}
static class Point {

View File

@ -243,7 +243,7 @@ public class NullObjectAndFieldTest {
}
@Test
public void testCustomTypeAdapterPassesNullDesrialization() {
public void testCustomTypeAdapterPassesNullDeserialization() {
Gson gson =
new GsonBuilder()
.registerTypeAdapter(

View File

@ -39,7 +39,8 @@ public class NumberLimitsTest {
* large or small numbers (it rounds to 0 or Infinity) (to be verified?; if it had
* performance problems with certain numbers, then it would affect other parts of Gson which
* parse as float or double as well)
* <li>Enforcing limits only when a JSON number is encountered would be ineffective unless users
* <li>Enforcing limits only when a JSON number is encountered would be ineffective when users
* want to consume a JSON number as string using {@link JsonReader#nextString()} unless they
* explicitly call {@link JsonReader#peek()} and check if the value is a JSON number.
* Otherwise the limits could be circumvented because {@link JsonReader#nextString()} reads
* both strings and numbers, and for JSON strings no restrictions are enforced.

View File

@ -141,9 +141,9 @@ public class ObjectTest {
@Test
public void testClassWithTransientFieldsDeserializationTransientFieldsPassedInJsonAreIgnored() {
String json = "{\"transientLongValue\":1,\"longValue\":[1]}";
String json = "{\"transientLongValue\":5,\"longValue\":[1]}";
ClassWithTransientFields<?> target = gson.fromJson(json, ClassWithTransientFields.class);
assertThat(target.transientLongValue != 1).isFalse();
assertThat(target.transientLongValue).isEqualTo(1);
}
@Test

View File

@ -555,8 +555,8 @@ public class PrimitiveTest {
@Test
public void testDoubleNaNDeserialization() {
assertThat(Double.isNaN(gson.fromJson("NaN", Double.class))).isTrue();
assertThat(Double.isNaN(gson.fromJson("NaN", double.class))).isTrue();
assertThat(gson.fromJson("NaN", Double.class)).isNaN();
assertThat(gson.fromJson("NaN", double.class)).isNaN();
}
@Test
@ -584,8 +584,8 @@ public class PrimitiveTest {
@Test
public void testFloatNaNDeserialization() {
assertThat(Float.isNaN(gson.fromJson("NaN", Float.class))).isTrue();
assertThat(Float.isNaN(gson.fromJson("NaN", float.class))).isTrue();
assertThat(gson.fromJson("NaN", Float.class)).isNaN();
assertThat(gson.fromJson("NaN", float.class)).isNaN();
}
@Test
@ -622,8 +622,8 @@ public class PrimitiveTest {
@Test
public void testDoubleInfinityDeserialization() {
assertThat(Double.isInfinite(gson.fromJson("Infinity", Double.class))).isTrue();
assertThat(Double.isInfinite(gson.fromJson("Infinity", double.class))).isTrue();
assertThat(gson.fromJson("Infinity", Double.class)).isPositiveInfinity();
assertThat(gson.fromJson("Infinity", double.class)).isPositiveInfinity();
}
@Test
@ -651,8 +651,8 @@ public class PrimitiveTest {
@Test
public void testFloatInfinityDeserialization() {
assertThat(Float.isInfinite(gson.fromJson("Infinity", Float.class))).isTrue();
assertThat(Float.isInfinite(gson.fromJson("Infinity", float.class))).isTrue();
assertThat(gson.fromJson("Infinity", Float.class)).isPositiveInfinity();
assertThat(gson.fromJson("Infinity", float.class)).isPositiveInfinity();
}
@Test
@ -689,8 +689,8 @@ public class PrimitiveTest {
@Test
public void testNegativeInfinityDeserialization() {
assertThat(Double.isInfinite(gson.fromJson("-Infinity", double.class))).isTrue();
assertThat(Double.isInfinite(gson.fromJson("-Infinity", Double.class))).isTrue();
assertThat(gson.fromJson("-Infinity", double.class)).isNegativeInfinity();
assertThat(gson.fromJson("-Infinity", Double.class)).isNegativeInfinity();
}
@Test
@ -718,8 +718,8 @@ public class PrimitiveTest {
@Test
public void testNegativeInfinityFloatDeserialization() {
assertThat(Float.isInfinite(gson.fromJson("-Infinity", float.class))).isTrue();
assertThat(Float.isInfinite(gson.fromJson("-Infinity", Float.class))).isTrue();
assertThat(gson.fromJson("-Infinity", float.class)).isNegativeInfinity();
assertThat(gson.fromJson("-Infinity", Float.class)).isNegativeInfinity();
}
@Test

View File

@ -192,7 +192,7 @@ public class ReadersWritersTest {
gson.toJson(Arrays.asList("test", 123, true), appendable);
// Make sure CharSequence.toString() was called at least two times to verify that
// CurrentWrite.cachedString is properly overwritten when char array changes
assertThat(appendable.toStringCallCount >= 2).isTrue();
assertThat(appendable.toStringCallCount).isAtLeast(2);
assertThat(appendable.stringBuilder.toString()).isEqualTo("[\"test\",123,true]");
}
}

View File

@ -38,7 +38,9 @@ import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import org.junit.Test;
@ -514,4 +516,27 @@ public class ReflectionAccessFilterTest {
+ " this type. Interface name: java.lang.Runnable");
}
}
/**
* Verifies that the predefined filter constants have meaningful {@code toString()} output to make
* debugging easier.
*/
@Test
public void testConstantsToString() throws Exception {
List<Field> constantFields = new ArrayList<>();
for (Field f : ReflectionAccessFilter.class.getFields()) {
// Only include ReflectionAccessFilter constants (in case any other fields are added in the
// future)
if (f.getType() == ReflectionAccessFilter.class) {
constantFields.add(f);
}
}
assertThat(constantFields).isNotEmpty();
for (Field f : constantFields) {
Object constant = f.get(null);
assertThat(constant.toString()).isEqualTo("ReflectionAccessFilter#" + f.getName());
}
}
}

View File

@ -114,8 +114,8 @@ public final class RuntimeTypeAdapterFactoryFunctionalTest {
}
/**
* Creates a new runtime type adapter using for {@code baseType} using {@code typeFieldName} as
* the type field name. Type field names are case sensitive.
* Creates a new runtime type adapter for {@code baseType} using {@code typeFieldName} as the
* type field name. Type field names are case sensitive.
*/
public static <T> RuntimeTypeAdapterFactory<T> of(Class<T> baseType, String typeFieldName) {
return new RuntimeTypeAdapterFactory<>(baseType, typeFieldName);

View File

@ -44,7 +44,7 @@ public class SecurityTest {
public void testNonExecutableJsonSerialization() {
Gson gson = gsonBuilder.generateNonExecutableJson().create();
String json = gson.toJson(new BagOfPrimitives());
assertThat(json.startsWith(JSON_NON_EXECUTABLE_PREFIX)).isTrue();
assertThat(json).startsWith(JSON_NON_EXECUTABLE_PREFIX);
}
@Test

View File

@ -83,7 +83,7 @@ public final class GsonTypesTest {
private final class NonStaticInner<T> {}
/**
* Given a parameterized type A&lt;B,C&gt;, returns B. If the specified type is not a generic
* Given a parameterized type {@code A<B, C>}, returns B. If the specified type is not a generic
* type, returns null.
*/
public static Type getFirstTypeArgument(Type type) throws Exception {

View File

@ -31,7 +31,7 @@ public class JavaVersionTest {
@Test
public void testGetMajorJavaVersion() {
// Gson currently requires at least Java 7
assertThat(JavaVersion.getMajorJavaVersion() >= 7).isTrue();
assertThat(JavaVersion.getMajorJavaVersion()).isAtLeast(7);
}
@Test

View File

@ -48,7 +48,7 @@ public final class JsonElementReaderTest {
JsonTreeReader reader = new JsonTreeReader(element);
reader.setStrictness(Strictness.LENIENT);
reader.beginArray();
assertThat(Double.isNaN(reader.nextDouble())).isTrue();
assertThat(reader.nextDouble()).isNaN();
assertThat(reader.nextDouble()).isEqualTo(Double.NEGATIVE_INFINITY);
assertThat(reader.nextDouble()).isEqualTo(Double.POSITIVE_INFINITY);
reader.endArray();

View File

@ -28,7 +28,6 @@ import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
import org.junit.Test;
import org.junit.function.ThrowingRunnable;
public class ISO8601UtilsTest {
@ -130,13 +129,6 @@ public class ISO8601UtilsTest {
@Test
public void testDateParseInvalidTime() {
final String dateStr = "2018-06-25T61:60:62-03:00";
assertThrows(
ParseException.class,
new ThrowingRunnable() {
@Override
public void run() throws Throwable {
ISO8601Utils.parse(dateStr, new ParsePosition(0));
}
});
assertThrows(ParseException.class, () -> ISO8601Utils.parse(dateStr, new ParsePosition(0)));
}
}

View File

@ -54,7 +54,7 @@ public class Java17ReflectionHelperTest {
.newInstance(new PrincipalImpl("user"), new PrincipalImpl("group"));
String[] componentNames = ReflectionHelper.getRecordComponentNames(unixDomainPrincipalClass);
assertThat(componentNames.length > 0).isTrue();
assertThat(componentNames).isNotEmpty();
for (String componentName : componentNames) {
Field componentField = unixDomainPrincipalClass.getDeclaredField(componentName);

View File

@ -24,6 +24,7 @@ import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@ -81,6 +82,18 @@ public final class TypeTokenTest {
listOfUnknown = listOfString; // compiles; must be true
// The following assertion is too difficult to support reliably, so disabling
// assertThat(TypeToken.get(b).isAssignableFrom(a)).isTrue();
WildcardType wildcardType = (WildcardType) ((ParameterizedType) b).getActualTypeArguments()[0];
TypeToken<?> wildcardTypeToken = TypeToken.get(wildcardType);
IllegalArgumentException e =
assertThrows(IllegalArgumentException.class, () -> wildcardTypeToken.isAssignableFrom(b));
assertThat(e)
.hasMessageThat()
.isEqualTo(
"Unsupported type, expected one of: java.lang.Class,"
+ " java.lang.reflect.ParameterizedType, java.lang.reflect.GenericArrayType, but"
+ " got: com.google.gson.internal.$Gson$Types$WildcardTypeImpl, for type token: "
+ wildcardTypeToken);
}
@SuppressWarnings({"deprecation"})

View File

@ -714,7 +714,7 @@ public final class JsonReaderTest {
JsonReader reader = new JsonReader(reader(json));
reader.setStrictness(Strictness.LENIENT);
reader.beginArray();
assertThat(Double.isNaN(reader.nextDouble())).isTrue();
assertThat(reader.nextDouble()).isNaN();
assertThat(reader.nextDouble()).isEqualTo(Double.NEGATIVE_INFINITY);
assertThat(reader.nextDouble()).isEqualTo(Double.POSITIVE_INFINITY);
reader.endArray();
@ -726,7 +726,7 @@ public final class JsonReaderTest {
JsonReader reader = new JsonReader(reader(json));
reader.setStrictness(Strictness.LENIENT);
reader.beginArray();
assertThat(Double.isNaN(reader.nextDouble())).isTrue();
assertThat(reader.nextDouble()).isNaN();
assertThat(reader.nextDouble()).isEqualTo(Double.NEGATIVE_INFINITY);
assertThat(reader.nextDouble()).isEqualTo(Double.POSITIVE_INFINITY);
reader.endArray();

View File

@ -286,10 +286,7 @@ public final class JsonWriterTest {
assertThat(stringWriter.toString()).isEqualTo("{\"a\":{\"b\":true},\"c\":1}");
}
@Test
public void testNonFiniteFloats() throws IOException {
StringWriter stringWriter = new StringWriter();
JsonWriter jsonWriter = new JsonWriter(stringWriter);
private static void assertNonFiniteFloatsExceptions(JsonWriter jsonWriter) throws IOException {
jsonWriter.beginArray();
IllegalArgumentException expected =
@ -311,27 +308,38 @@ public final class JsonWriterTest {
.isEqualTo("Numeric values must be finite, but was Infinity");
}
@Test
public void testNonFiniteFloats() throws IOException {
StringWriter stringWriter = new StringWriter();
JsonWriter jsonWriter = new JsonWriter(stringWriter);
assertNonFiniteFloatsExceptions(jsonWriter);
}
@Test
public void testNonFiniteFloatsWhenStrict() throws IOException {
StringWriter stringWriter = new StringWriter();
JsonWriter jsonWriter = new JsonWriter(stringWriter);
jsonWriter.setStrictness(Strictness.STRICT);
assertNonFiniteFloatsExceptions(jsonWriter);
}
private static void assertNonFiniteDoublesExceptions(JsonWriter jsonWriter) throws IOException {
jsonWriter.beginArray();
IllegalArgumentException expected =
assertThrows(IllegalArgumentException.class, () -> jsonWriter.value(Float.NaN));
assertThrows(IllegalArgumentException.class, () -> jsonWriter.value(Double.NaN));
assertThat(expected).hasMessageThat().isEqualTo("Numeric values must be finite, but was NaN");
expected =
assertThrows(
IllegalArgumentException.class, () -> jsonWriter.value(Float.NEGATIVE_INFINITY));
IllegalArgumentException.class, () -> jsonWriter.value(Double.NEGATIVE_INFINITY));
assertThat(expected)
.hasMessageThat()
.isEqualTo("Numeric values must be finite, but was -Infinity");
expected =
assertThrows(
IllegalArgumentException.class, () -> jsonWriter.value(Float.POSITIVE_INFINITY));
IllegalArgumentException.class, () -> jsonWriter.value(Double.POSITIVE_INFINITY));
assertThat(expected)
.hasMessageThat()
.isEqualTo("Numeric values must be finite, but was Infinity");
@ -341,25 +349,7 @@ public final class JsonWriterTest {
public void testNonFiniteDoubles() throws IOException {
StringWriter stringWriter = new StringWriter();
JsonWriter jsonWriter = new JsonWriter(stringWriter);
jsonWriter.beginArray();
IllegalArgumentException expected =
assertThrows(IllegalArgumentException.class, () -> jsonWriter.value(Double.NaN));
assertThat(expected).hasMessageThat().isEqualTo("Numeric values must be finite, but was NaN");
expected =
assertThrows(
IllegalArgumentException.class, () -> jsonWriter.value(Double.NEGATIVE_INFINITY));
assertThat(expected)
.hasMessageThat()
.isEqualTo("Numeric values must be finite, but was -Infinity");
expected =
assertThrows(
IllegalArgumentException.class, () -> jsonWriter.value(Double.POSITIVE_INFINITY));
assertThat(expected)
.hasMessageThat()
.isEqualTo("Numeric values must be finite, but was Infinity");
assertNonFiniteDoublesExceptions(jsonWriter);
}
@Test
@ -367,22 +357,37 @@ public final class JsonWriterTest {
StringWriter stringWriter = new StringWriter();
JsonWriter jsonWriter = new JsonWriter(stringWriter);
jsonWriter.setStrictness(Strictness.STRICT);
assertNonFiniteDoublesExceptions(jsonWriter);
}
private static void assertNonFiniteNumbersExceptions(JsonWriter jsonWriter) throws IOException {
jsonWriter.beginArray();
IllegalArgumentException expected =
assertThrows(IllegalArgumentException.class, () -> jsonWriter.value(Double.NaN));
assertThrows(
IllegalArgumentException.class, () -> jsonWriter.value(Double.valueOf(Double.NaN)));
assertThat(expected).hasMessageThat().isEqualTo("Numeric values must be finite, but was NaN");
expected =
assertThrows(
IllegalArgumentException.class, () -> jsonWriter.value(Double.NEGATIVE_INFINITY));
IllegalArgumentException.class,
() -> jsonWriter.value(Double.valueOf(Double.NEGATIVE_INFINITY)));
assertThat(expected)
.hasMessageThat()
.isEqualTo("Numeric values must be finite, but was -Infinity");
expected =
assertThrows(
IllegalArgumentException.class, () -> jsonWriter.value(Double.POSITIVE_INFINITY));
IllegalArgumentException.class,
() -> jsonWriter.value(Double.valueOf(Double.POSITIVE_INFINITY)));
assertThat(expected)
.hasMessageThat()
.isEqualTo("Numeric values must be finite, but was Infinity");
expected =
assertThrows(
IllegalArgumentException.class,
() -> jsonWriter.value(new LazilyParsedNumber("Infinity")));
assertThat(expected)
.hasMessageThat()
.isEqualTo("Numeric values must be finite, but was Infinity");
@ -392,36 +397,7 @@ public final class JsonWriterTest {
public void testNonFiniteNumbers() throws IOException {
StringWriter stringWriter = new StringWriter();
JsonWriter jsonWriter = new JsonWriter(stringWriter);
jsonWriter.beginArray();
IllegalArgumentException expected =
assertThrows(
IllegalArgumentException.class, () -> jsonWriter.value(Double.valueOf(Double.NaN)));
assertThat(expected).hasMessageThat().isEqualTo("Numeric values must be finite, but was NaN");
expected =
assertThrows(
IllegalArgumentException.class,
() -> jsonWriter.value(Double.valueOf(Double.NEGATIVE_INFINITY)));
assertThat(expected)
.hasMessageThat()
.isEqualTo("Numeric values must be finite, but was -Infinity");
expected =
assertThrows(
IllegalArgumentException.class,
() -> jsonWriter.value(Double.valueOf(Double.POSITIVE_INFINITY)));
assertThat(expected)
.hasMessageThat()
.isEqualTo("Numeric values must be finite, but was Infinity");
expected =
assertThrows(
IllegalArgumentException.class,
() -> jsonWriter.value(new LazilyParsedNumber("Infinity")));
assertThat(expected)
.hasMessageThat()
.isEqualTo("Numeric values must be finite, but was Infinity");
assertNonFiniteNumbersExceptions(jsonWriter);
}
@Test
@ -429,36 +405,7 @@ public final class JsonWriterTest {
StringWriter stringWriter = new StringWriter();
JsonWriter jsonWriter = new JsonWriter(stringWriter);
jsonWriter.setStrictness(Strictness.STRICT);
jsonWriter.beginArray();
IllegalArgumentException expected =
assertThrows(
IllegalArgumentException.class, () -> jsonWriter.value(Double.valueOf(Double.NaN)));
assertThat(expected).hasMessageThat().isEqualTo("Numeric values must be finite, but was NaN");
expected =
assertThrows(
IllegalArgumentException.class,
() -> jsonWriter.value(Double.valueOf(Double.NEGATIVE_INFINITY)));
assertThat(expected)
.hasMessageThat()
.isEqualTo("Numeric values must be finite, but was -Infinity");
expected =
assertThrows(
IllegalArgumentException.class,
() -> jsonWriter.value(Double.valueOf(Double.POSITIVE_INFINITY)));
assertThat(expected)
.hasMessageThat()
.isEqualTo("Numeric values must be finite, but was Infinity");
expected =
assertThrows(
IllegalArgumentException.class,
() -> jsonWriter.value(new LazilyParsedNumber("Infinity")));
assertThat(expected)
.hasMessageThat()
.isEqualTo("Numeric values must be finite, but was Infinity");
assertNonFiniteNumbersExceptions(jsonWriter);
}
@Test

View File

@ -392,13 +392,13 @@ public final class ParseBenchmark {
StringBuilder result =
new StringBuilder()
.append(id)
.append("\n")
.append('\n')
.append(title)
.append("\n")
.append('\n')
.append(description)
.append("\n")
.append('\n')
.append(alternates)
.append("\n")
.append('\n')
.append(updated);
int i = 1;
for (Item item : items) {

View File

@ -196,6 +196,9 @@
<executions>
<execution>
<goals>
<!-- This logs a warning about `source.scm.tag=HEAD`, but this can be ignored;
during release Maven Release Plugin temporarily changes the `source.scm.tag`
value to the actual Git tag, which will then not cause a warning -->
<goal>buildinfo</goal>
</goals>
</execution>