Skip to content

Commit

Permalink
Fix ProtoTypeAdapter being unable to deserialize certain repeated f…
Browse files Browse the repository at this point in the history
…ields

For example a `List<Long>` Protobuf field might internally have the
Protobuf-internal `LongList` interface type.
Previously Gson's ConstructorConstructor was nonetheless creating an
ArrayList for this, which is wrong but worked. Now with the changes in
ConstructorConstructor Gson will fail to create an instance, so this commit
tries to solve this properly in ProtoTypeAdapter.
  • Loading branch information
Marcono1234 committed Sep 6, 2024
1 parent 9952bda commit 1f496d7
Showing 1 changed file with 11 additions and 2 deletions.
13 changes: 11 additions & 2 deletions proto/src/main/java/com/google/gson/protobuf/ProtoTypeAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import com.google.common.base.CaseFormat;
import com.google.common.collect.MapMaker;
import com.google.common.reflect.TypeToken;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
Expand All @@ -44,6 +45,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
Expand Down Expand Up @@ -331,8 +333,15 @@ public Message deserialize(JsonElement json, Type typeOfT, JsonDeserializationCo
String protoArrayFieldName =
protoFormat.to(CaseFormat.LOWER_CAMEL, fieldDescriptor.getName()) + "_";
Field protoArrayField = protoClass.getDeclaredField(protoArrayFieldName);
Type protoArrayFieldType = protoArrayField.getGenericType();
fieldValue = context.deserialize(jsonElement, protoArrayFieldType);

@SuppressWarnings("unchecked")
TypeToken<? extends List<?>> protoArrayFieldType =
(TypeToken<? extends List<?>>) TypeToken.of(protoArrayField.getGenericType());
// Get the type as `List<E>`, otherwise type might be Protobuf internal interface for
// which no instance can be created
Type protoArrayResolvedFieldType =
protoArrayFieldType.getSupertype(List.class).getType();
fieldValue = context.deserialize(jsonElement, protoArrayResolvedFieldType);
protoBuilder.setField(fieldDescriptor, fieldValue);
} else {
Object field = defaultInstance.getField(fieldDescriptor);
Expand Down

0 comments on commit 1f496d7

Please sign in to comment.