1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-12-28 19:45:50 +01:00

RuntimeTypeAdapterFactory: Allow null labels

This commit is contained in:
José Rebelo 2024-09-29 21:33:04 +01:00 committed by José Rebelo
parent 9d03d0d98e
commit 5192304d29
2 changed files with 77 additions and 4 deletions

View File

@ -12,6 +12,8 @@
* 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.
*
* From 0eb681b, adapted for Gadgetbridge to support null labels.
*/
package com.google.gson.typeadapters;
@ -19,6 +21,7 @@ package com.google.gson.typeadapters;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
@ -217,7 +220,7 @@ public final class RuntimeTypeAdapterFactory<T> implements TypeAdapterFactory {
*/
@CanIgnoreReturnValue
public RuntimeTypeAdapterFactory<T> registerSubtype(Class<? extends T> type, String label) {
if (type == null || label == null) {
if (type == null) {
throw new NullPointerException();
}
if (subtypeToLabel.containsKey(type) || labelToSubtype.containsKey(label)) {
@ -272,14 +275,14 @@ public final class RuntimeTypeAdapterFactory<T> implements TypeAdapterFactory {
labelJsonElement = jsonElement.getAsJsonObject().remove(typeFieldName);
}
if (labelJsonElement == null) {
if (labelJsonElement == null && !labelToDelegate.containsKey(null)) {
throw new JsonParseException(
"cannot deserialize "
+ baseType
+ " because it does not define a field named "
+ typeFieldName);
}
String label = labelJsonElement.getAsString();
String label = labelJsonElement != null ? labelJsonElement.getAsString() : null;
@SuppressWarnings("unchecked") // registration requires that subtype extends T
TypeAdapter<R> delegate = (TypeAdapter<R>) labelToDelegate.get(label);
if (delegate == null) {
@ -319,7 +322,11 @@ public final class RuntimeTypeAdapterFactory<T> implements TypeAdapterFactory {
+ " because it already defines a field named "
+ typeFieldName);
}
clone.add(typeFieldName, new JsonPrimitive(label));
if (label != null) {
clone.add(typeFieldName, new JsonPrimitive(label));
} else {
clone.add(typeFieldName, JsonNull.INSTANCE);
}
for (Map.Entry<String, JsonElement> e : jsonObject.entrySet()) {
clone.add(e.getKey(), e.getValue());

View File

@ -0,0 +1,66 @@
package com.google.gson.typeadapters;
import static org.junit.Assert.*;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.junit.Test;
public class RuntimeTypeAdapterFactoryTest {
private static final Gson GSON = new GsonBuilder()
.registerTypeAdapterFactory(RuntimeTypeAdapterFactory
.of(Parent.class, "type")
.registerSubtype(Child1.class, null)
.registerSubtype(Child2.class, "child2")
)
.create();
@Test
public void testNullLabelSerialize() {
final Child1 child1 = new Child1("hello1");
final Child2 child2 = new Child2("hello2");
assertEquals("{\"field1\":\"hello1\",\"fieldParent\":\"fromChild1\"}", GSON.toJson(child1, Parent.class));
assertEquals("{\"type\":\"child2\",\"field2\":\"hello2\",\"fieldParent\":\"fromChild2\"}", GSON.toJson(child2, Parent.class));
}
@Test
public void testNullLabelDeserialize() {
final Parent child1 = GSON.fromJson("{\"field1\":\"hello1\",\"fieldParent\":\"fromChild1\"}", Parent.class);
assertTrue(child1 instanceof Child1);
assertEquals("fromChild1", child1.fieldParent);
assertEquals("hello1", ((Child1) child1).field1);
final Parent child2 = GSON.fromJson("{\"type\":\"child2\",\"field2\":\"hello2\",\"fieldParent\":\"fromChild2\"}", Parent.class);
assertTrue(child2 instanceof Child2);
assertEquals("fromChild2", child2.fieldParent);
assertEquals("hello2", ((Child2) child2).field2);
}
private static class Parent {
private final String fieldParent;
private Parent(final String fieldParent) {
this.fieldParent = fieldParent;
}
}
private static class Child1 extends Parent {
private final String field1;
private Child1(final String field1) {
super("fromChild1");
this.field1 = field1;
}
}
private static class Child2 extends Parent {
private final String field2;
private Child2(final String field2) {
super("fromChild2");
this.field2 = field2;
}
}
}