Skip to content

Commit

Permalink
Merge pull request #213 from LachlanMcKee/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
LachlanMcKee authored Jun 26, 2019
2 parents 7462869 + a5c6954 commit 43c5234
Show file tree
Hide file tree
Showing 35 changed files with 490 additions and 101 deletions.
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,25 @@
Change Log
===========

Version 3.4.0 *(2019-06-19)*
----------------------------

* Improvement: `@GsonSubType` now supports null values. ([#210](../../issues/210))

This is change in behaviour, as previously a null or missing value for a `subTypeKey` would have thrown an exception saying this was not allowed. Now that it is allowed, it is possible that elements may leak into an array/list.

The main benefit is that it is now possible for `stringValueSubtypes` to handle situations where the `subTypeKey` value is null, such as:

```java
@GsonSubtype(
subTypeKey = "type",
defaultType = Type1.class,
stringValueSubtypes = {
@GsonSubtype.StringValueSubtype(value = GsonSubtype.StringValueSubtype.NULL_STRING, subtype = TypeNull.class)
}
)
```

Version 3.3.0 *(2019-04-07)*
----------------------------

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,6 @@ To use proguard within your project, you must add the generated type adapter fac
This library is available on Maven, you can add it to your project using the following gradle dependencies:

```gradle
compile 'net.lachlanmckee:gsonpath:3.3.0'
apt 'net.lachlanmckee:gsonpath-compiler:3.3.0'
compile 'net.lachlanmckee:gsonpath:3.4.0'
apt 'net.lachlanmckee:gsonpath-compiler:3.4.0'
```
2 changes: 1 addition & 1 deletion compiler/standard/gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
POM_ARTIFACT_ID=gsonpath-compiler
POM_NAME=gsonpath-compiler
VERSION_NAME=3.3.0
VERSION_NAME=3.4.0
POM_PACKAGING=jar
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
package gsonpath.adapter.common

import com.google.gson.JsonElement
import com.google.gson.JsonParseException
import com.google.gson.TypeAdapter
import com.google.gson.internal.Streams
import com.squareup.javapoet.*
import gsonpath.GsonSubTypeFailureException
import gsonpath.GsonSubTypeFailureOutcome
import gsonpath.adapter.Constants
import gsonpath.adapter.AdapterMethodBuilder
import gsonpath.adapter.Constants
import gsonpath.util.*
import javax.lang.model.element.Modifier

Expand Down Expand Up @@ -92,22 +91,26 @@ object GsonSubTypeFactory {
TYPE_VALUE_JSON_ELEMENT,
"$JSON_ELEMENT.getAsJsonObject().get(\"$fieldName\")")

`if`("$TYPE_VALUE_JSON_ELEMENT == ${Constants.NULL} || $TYPE_VALUE_JSON_ELEMENT.isJsonNull()") {
addStatement("throw new \$T(\"cannot deserialize $rawTypeName because the subtype field " +
"'$fieldName' is either null or does not exist.\")",
JsonParseException::class.java)
with(when (subTypeMetadata.keyType) {
SubTypeKeyType.STRING -> "java.lang.String"
SubTypeKeyType.INTEGER -> "Integer"
SubTypeKeyType.BOOLEAN -> "Boolean"
}) {
addStatement("final $this ${Constants.VALUE}")
}

// Obtain the value using the correct type.
when (subTypeMetadata.keyType) {
SubTypeKeyType.STRING ->
createVariable("java.lang.String", Constants.VALUE, "$TYPE_VALUE_JSON_ELEMENT.getAsString()")

SubTypeKeyType.INTEGER ->
createVariable("int", Constants.VALUE, "$TYPE_VALUE_JSON_ELEMENT.getAsInt()")

SubTypeKeyType.BOOLEAN ->
createVariable("boolean", Constants.VALUE, "$TYPE_VALUE_JSON_ELEMENT.getAsBoolean()")
ifWithoutClose("$TYPE_VALUE_JSON_ELEMENT == ${Constants.NULL} || $TYPE_VALUE_JSON_ELEMENT.isJsonNull()") {
assign(Constants.VALUE, "null")
}
`else` {
// Obtain the value using the correct type.
with(when (subTypeMetadata.keyType) {
SubTypeKeyType.STRING -> "getAsString"
SubTypeKeyType.INTEGER -> "getAsInt"
SubTypeKeyType.BOOLEAN -> "getAsBoolean"
}) {
assign(Constants.VALUE, "$TYPE_VALUE_JSON_ELEMENT.$this()")
}
}

createVariable(ParameterizedTypeName.get(ClassName.get(TypeAdapter::class.java), WildcardTypeName.subtypeOf(rawTypeName)),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,12 @@ class SubTypeMetadataFactoryImpl(private val typeHandler: TypeHandler) : SubType
val genericGsonSubTypeKeys: List<GsonSubTypeKeyAndClass> =
when (keyType) {
SubTypeKeyType.STRING -> gsonSubType.stringValueSubtypes.map {
getGsonSubTypeKeyAndClass("\"${it.value}\"", element) { it.subtype }
val value = if (it.value == GsonSubtype.StringValueSubtype.NULL_STRING) {
"null"
} else {
"\"${it.value}\""
}
getGsonSubTypeKeyAndClass(value, element) { it.subtype }
}

SubTypeKeyType.INTEGER -> gsonSubType.integerValueSubtypes.map {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ class GsonSubTypeExtensionTest {
test("string_keys", "TypesPojo")
}

@Test
fun givenStringKeysWithNull_whenProcessorExecuted_expectValidGsonTypeAdapter() {
test("null_string_key", "TypesList")
test("null_string_key", "TypesPojo")
}

@Test
fun givenIntegerKeys_whenProcessorExecuted_expectValidGsonTypeAdapter() {
test("integer_keys", "TypesList")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.TypeAdapter;
import com.google.gson.internal.Streams;
import com.google.gson.stream.JsonReader;
Expand Down Expand Up @@ -119,10 +118,12 @@ private ItemsGsonSubtype(Gson gson) {
public Type read(JsonReader in) throws IOException {
JsonElement jsonElement = Streams.parse(in);
JsonElement typeValueJsonElement = jsonElement.getAsJsonObject().get("type");
final Boolean value;
if (typeValueJsonElement == null || typeValueJsonElement.isJsonNull()) {
throw new JsonParseException("cannot deserialize generator.extension.gson_sub_type.Type because the subtype field 'type' is either null or does not exist.");
value = null;
} else {
value = typeValueJsonElement.getAsBoolean();
}
boolean value = typeValueJsonElement.getAsBoolean();
TypeAdapter<? extends Type> delegate = typeAdaptersDelegatedByValueMap.get(value);
if (delegate == null) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.TypeAdapter;
import com.google.gson.internal.Streams;
import com.google.gson.stream.JsonReader;
Expand Down Expand Up @@ -118,10 +117,12 @@ private ItemsGsonSubtype(Gson gson) {
public Type read(JsonReader in) throws IOException {
JsonElement jsonElement = Streams.parse(in);
JsonElement typeValueJsonElement = jsonElement.getAsJsonObject().get("type");
final Boolean value;
if (typeValueJsonElement == null || typeValueJsonElement.isJsonNull()) {
throw new JsonParseException("cannot deserialize generator.extension.gson_sub_type.Type because the subtype field 'type' is either null or does not exist.");
value = null;
} else {
value = typeValueJsonElement.getAsBoolean();
}
boolean value = typeValueJsonElement.getAsBoolean();
TypeAdapter<? extends Type> delegate = typeAdaptersDelegatedByValueMap.get(value);
if (delegate == null) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.TypeAdapter;
import com.google.gson.internal.Streams;
import com.google.gson.stream.JsonReader;
Expand Down Expand Up @@ -119,10 +118,12 @@ private ItemsGsonSubtype(Gson gson) {
public Type read(JsonReader in) throws IOException {
JsonElement jsonElement = Streams.parse(in);
JsonElement typeValueJsonElement = jsonElement.getAsJsonObject().get("type");
final java.lang.String value;
if (typeValueJsonElement == null || typeValueJsonElement.isJsonNull()) {
throw new JsonParseException("cannot deserialize generator.extension.gson_sub_type.Type because the subtype field 'type' is either null or does not exist.");
value = null;
} else {
value = typeValueJsonElement.getAsString();
}
java.lang.String value = typeValueJsonElement.getAsString();
TypeAdapter<? extends Type> delegate = typeAdaptersDelegatedByValueMap.get(value);
if (delegate == null) {
// Use the default type adapter if the type is unknown.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.TypeAdapter;
import com.google.gson.internal.Streams;
import com.google.gson.stream.JsonReader;
Expand Down Expand Up @@ -118,10 +117,12 @@ private ItemsGsonSubtype(Gson gson) {
public Type read(JsonReader in) throws IOException {
JsonElement jsonElement = Streams.parse(in);
JsonElement typeValueJsonElement = jsonElement.getAsJsonObject().get("type");
final java.lang.String value;
if (typeValueJsonElement == null || typeValueJsonElement.isJsonNull()) {
throw new JsonParseException("cannot deserialize generator.extension.gson_sub_type.Type because the subtype field 'type' is either null or does not exist.");
value = null;
} else {
value = typeValueJsonElement.getAsString();
}
java.lang.String value = typeValueJsonElement.getAsString();
TypeAdapter<? extends Type> delegate = typeAdaptersDelegatedByValueMap.get(value);
if (delegate == null) {
// Use the default type adapter if the type is unknown.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.TypeAdapter;
import com.google.gson.internal.Streams;
import com.google.gson.stream.JsonReader;
Expand Down Expand Up @@ -121,10 +120,12 @@ private ItemsGsonSubtype(Gson gson) {
public Type read(JsonReader in) throws IOException {
JsonElement jsonElement = Streams.parse(in);
JsonElement typeValueJsonElement = jsonElement.getAsJsonObject().get("type");
final java.lang.String value;
if (typeValueJsonElement == null || typeValueJsonElement.isJsonNull()) {
throw new JsonParseException("cannot deserialize generator.extension.gson_sub_type.Type because the subtype field 'type' is either null or does not exist.");
value = null;
} else {
value = typeValueJsonElement.getAsString();
}
java.lang.String value = typeValueJsonElement.getAsString();
TypeAdapter<? extends Type> delegate = typeAdaptersDelegatedByValueMap.get(value);
if (delegate == null) {
throw new GsonSubTypeFailureException("Failed to find subtype for value: " + value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.TypeAdapter;
import com.google.gson.internal.Streams;
import com.google.gson.stream.JsonReader;
Expand Down Expand Up @@ -120,10 +119,12 @@ private ItemsGsonSubtype(Gson gson) {
public Type read(JsonReader in) throws IOException {
JsonElement jsonElement = Streams.parse(in);
JsonElement typeValueJsonElement = jsonElement.getAsJsonObject().get("type");
final java.lang.String value;
if (typeValueJsonElement == null || typeValueJsonElement.isJsonNull()) {
throw new JsonParseException("cannot deserialize generator.extension.gson_sub_type.Type because the subtype field 'type' is either null or does not exist.");
value = null;
} else {
value = typeValueJsonElement.getAsString();
}
java.lang.String value = typeValueJsonElement.getAsString();
TypeAdapter<? extends Type> delegate = typeAdaptersDelegatedByValueMap.get(value);
if (delegate == null) {
throw new GsonSubTypeFailureException("Failed to find subtype for value: " + value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.TypeAdapter;
import com.google.gson.internal.Streams;
import com.google.gson.stream.JsonReader;
Expand Down Expand Up @@ -119,10 +118,12 @@ private ItemsGsonSubtype(Gson gson) {
public Type read(JsonReader in) throws IOException {
JsonElement jsonElement = Streams.parse(in);
JsonElement typeValueJsonElement = jsonElement.getAsJsonObject().get("type");
final java.lang.String value;
if (typeValueJsonElement == null || typeValueJsonElement.isJsonNull()) {
throw new JsonParseException("cannot deserialize generator.extension.gson_sub_type.Type because the subtype field 'type' is either null or does not exist.");
value = null;
} else {
value = typeValueJsonElement.getAsString();
}
java.lang.String value = typeValueJsonElement.getAsString();
TypeAdapter<? extends Type> delegate = typeAdaptersDelegatedByValueMap.get(value);
if (delegate == null) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.TypeAdapter;
import com.google.gson.internal.Streams;
import com.google.gson.stream.JsonReader;
Expand Down Expand Up @@ -119,10 +118,12 @@ private ItemsGsonSubtype(Gson gson) {
public Type read(JsonReader in) throws IOException {
JsonElement jsonElement = Streams.parse(in);
JsonElement typeValueJsonElement = jsonElement.getAsJsonObject().get("type");
final Integer value;
if (typeValueJsonElement == null || typeValueJsonElement.isJsonNull()) {
throw new JsonParseException("cannot deserialize generator.extension.gson_sub_type.Type because the subtype field 'type' is either null or does not exist.");
value = null;
} else {
value = typeValueJsonElement.getAsInt();
}
int value = typeValueJsonElement.getAsInt();
TypeAdapter<? extends Type> delegate = typeAdaptersDelegatedByValueMap.get(value);
if (delegate == null) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.TypeAdapter;
import com.google.gson.internal.Streams;
import com.google.gson.stream.JsonReader;
Expand Down Expand Up @@ -118,10 +117,12 @@ private ItemsGsonSubtype(Gson gson) {
public Type read(JsonReader in) throws IOException {
JsonElement jsonElement = Streams.parse(in);
JsonElement typeValueJsonElement = jsonElement.getAsJsonObject().get("type");
final Integer value;
if (typeValueJsonElement == null || typeValueJsonElement.isJsonNull()) {
throw new JsonParseException("cannot deserialize generator.extension.gson_sub_type.Type because the subtype field 'type' is either null or does not exist.");
value = null;
} else {
value = typeValueJsonElement.getAsInt();
}
int value = typeValueJsonElement.getAsInt();
TypeAdapter<? extends Type> delegate = typeAdaptersDelegatedByValueMap.get(value);
if (delegate == null) {
return null;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package generator.extension.gson_sub_type.null_string_key;

import generator.extension.gson_sub_type.Type1;
import generator.extension.gson_sub_type.Type2;
import gsonpath.GsonSubTypeFailureOutcome;
import gsonpath.GsonSubtype;

@GsonSubtype(
subTypeKey = "type",
defaultType = Type1.class,
stringValueSubtypes = {
@GsonSubtype.StringValueSubtype(value = GsonSubtype.StringValueSubtype.NULL_STRING, subtype = Type2.class)
}
)
public @interface TypeGsonSubType {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package generator.extension.gson_sub_type.null_string_key;

import gsonpath.AutoGsonAdapter;
import gsonpath.GsonSubtype;

import generator.extension.gson_sub_type.Type;
import generator.extension.gson_sub_type.Type1;
import generator.extension.gson_sub_type.Type2;

@AutoGsonAdapter
class TypesList {
@TypeGsonSubType
Type[] items;
}
Loading

0 comments on commit 43c5234

Please sign in to comment.