From 7821b73202a878bea091d4bc97195fdd87d76382 Mon Sep 17 00:00:00 2001 From: Inderjeet Singh Date: Thu, 5 Nov 2015 10:45:23 -0800 Subject: [PATCH] Added support for AtomicInteger, AtomicBoolean, AtomicLong and AtomicIntegerArray. --- gson/src/main/java/com/google/gson/Gson.java | 23 ++++- .../gson/internal/bind/TypeAdapters.java | 92 +++++++++++++++---- .../JavaUtilConcurrentLocksTest.java | 70 ++++++++++++++ 3 files changed, 165 insertions(+), 20 deletions(-) create mode 100644 gson/src/test/java/com/google/gson/functional/JavaUtilConcurrentLocksTest.java diff --git a/gson/src/main/java/com/google/gson/Gson.java b/gson/src/main/java/com/google/gson/Gson.java index ad17db96..b1b87455 100644 --- a/gson/src/main/java/com/google/gson/Gson.java +++ b/gson/src/main/java/com/google/gson/Gson.java @@ -30,6 +30,10 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicIntegerArray; +import java.util.concurrent.atomic.AtomicLong; import com.google.gson.internal.ConstructorConstructor; import com.google.gson.internal.Excluder; @@ -210,13 +214,17 @@ public final class Gson { factories.add(TypeAdapters.BOOLEAN_FACTORY); factories.add(TypeAdapters.BYTE_FACTORY); factories.add(TypeAdapters.SHORT_FACTORY); - factories.add(TypeAdapters.newFactory(long.class, Long.class, - longAdapter(longSerializationPolicy))); + TypeAdapter longAdapter = longAdapter(longSerializationPolicy); + factories.add(TypeAdapters.newFactory(long.class, Long.class, longAdapter)); factories.add(TypeAdapters.newFactory(double.class, Double.class, doubleAdapter(serializeSpecialFloatingPointValues))); factories.add(TypeAdapters.newFactory(float.class, Float.class, floatAdapter(serializeSpecialFloatingPointValues))); factories.add(TypeAdapters.NUMBER_FACTORY); + factories.add(TypeAdapters.newFactory(AtomicInteger.class, TypeAdapters.ATOMIC_INTEGER)); + factories.add(TypeAdapters.newFactory(AtomicBoolean.class, TypeAdapters.ATOMIC_BOOLEAN)); + factories.add(TypeAdapters.newFactory(AtomicLong.class, atomicLongAdapter(longAdapter))); + factories.add(TypeAdapters.newFactory(AtomicIntegerArray.class, TypeAdapters.ATOMIC_INTEGER_ARRAY)); factories.add(TypeAdapters.CHARACTER_FACTORY); factories.add(TypeAdapters.STRING_BUILDER_FACTORY); factories.add(TypeAdapters.STRING_BUFFER_FACTORY); @@ -325,6 +333,17 @@ public final class Gson { }; } + private TypeAdapter atomicLongAdapter(final TypeAdapter longAdapter) { + return new TypeAdapter() { + @Override public void write(JsonWriter out, AtomicLong value) throws IOException { + longAdapter.write(out, value.get()); + } + @Override public AtomicLong read(JsonReader in) throws IOException { + Number value = longAdapter.read(in); + return new AtomicLong(value.longValue()); + } + }.nullSafe(); + } /** * Returns the type adapter for {@code} type. * diff --git a/gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java b/gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java index 170a4b51..a7c7182d 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java +++ b/gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java @@ -16,6 +16,29 @@ package com.google.gson.internal.bind; +import java.io.IOException; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.net.InetAddress; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.BitSet; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.StringTokenizer; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicIntegerArray; + import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonElement; @@ -32,23 +55,6 @@ import com.google.gson.reflect.TypeToken; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; import com.google.gson.stream.JsonWriter; -import java.io.IOException; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.net.InetAddress; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.sql.Timestamp; -import java.util.BitSet; -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; -import java.util.StringTokenizer; -import java.util.UUID; /** * Type adapters for basic types. @@ -247,10 +253,60 @@ public final class TypeAdapters { out.value(value); } }; - public static final TypeAdapterFactory INTEGER_FACTORY = newFactory(int.class, Integer.class, INTEGER); + public static final TypeAdapter ATOMIC_INTEGER = new TypeAdapter() { + @Override public AtomicInteger read(JsonReader in) throws IOException { + try { + return new AtomicInteger(in.nextInt()); + } catch (NumberFormatException e) { + throw new JsonSyntaxException(e); + } + } + @Override public void write(JsonWriter out, AtomicInteger value) throws IOException { + out.value(value.get()); + } + }.nullSafe(); + + public static final TypeAdapter ATOMIC_BOOLEAN = new TypeAdapter() { + @Override public AtomicBoolean read(JsonReader in) throws IOException { + return new AtomicBoolean(in.nextBoolean()); + } + @Override public void write(JsonWriter out, AtomicBoolean value) throws IOException { + out.value(value.get()); + } + }.nullSafe(); + + public static final TypeAdapter ATOMIC_INTEGER_ARRAY = new TypeAdapter() { + @Override public AtomicIntegerArray read(JsonReader in) throws IOException { + List list = new ArrayList(); + in.beginArray(); + while (in.hasNext()) { + try { + int integer = in.nextInt(); + list.add(integer); + } catch (NumberFormatException e) { + throw new JsonSyntaxException(e); + } + } + in.endArray(); + int length = list.size(); + AtomicIntegerArray array = new AtomicIntegerArray(length); + for (int i = 0; i < length; ++i) { + array.set(i, list.get(i)); + } + return array; + } + @Override public void write(JsonWriter out, AtomicIntegerArray value) throws IOException { + out.beginArray(); + for (int i = 0, length = value.length(); i < length; i++) { + out.value(value.get(i)); + } + out.endArray(); + } + }.nullSafe(); + public static final TypeAdapter LONG = new TypeAdapter() { @Override public Number read(JsonReader in) throws IOException { diff --git a/gson/src/test/java/com/google/gson/functional/JavaUtilConcurrentLocksTest.java b/gson/src/test/java/com/google/gson/functional/JavaUtilConcurrentLocksTest.java new file mode 100644 index 00000000..0604b4dd --- /dev/null +++ b/gson/src/test/java/com/google/gson/functional/JavaUtilConcurrentLocksTest.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2015 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 java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicIntegerArray; +import java.util.concurrent.atomic.AtomicLong; + +import com.google.gson.Gson; + +import junit.framework.TestCase; + +/** + * Functional test for Json serialization and deserialization for java.util.concurrent.locks classes + */ +public class JavaUtilConcurrentLocksTest extends TestCase { + private Gson gson; + + @Override + protected void setUp() throws Exception { + super.setUp(); + gson = new Gson(); + } + + public void testAtomicBoolean() throws Exception { + AtomicBoolean target = gson.fromJson("true", AtomicBoolean.class); + assertTrue(target.get()); + String json = gson.toJson(target); + assertEquals("true", json); + } + + public void testAtomicInteger() throws Exception { + AtomicInteger target = gson.fromJson("10", AtomicInteger.class); + assertEquals(10, target.get()); + String json = gson.toJson(target); + assertEquals("10", json); + } + + public void testAtomicLong() throws Exception { + AtomicLong target = gson.fromJson("10", AtomicLong.class); + assertEquals(10, target.get()); + String json = gson.toJson(target); + assertEquals("10", json); + } + + public void testAtomicIntegerArray() throws Exception { + AtomicIntegerArray target = gson.fromJson("[10, 13, 14]", AtomicIntegerArray.class); + assertEquals(3, target.length()); + assertEquals(10, target.get(0)); + assertEquals(13, target.get(1)); + assertEquals(14, target.get(2)); + String json = gson.toJson(target); + assertEquals("[10,13,14]", json); + } +}