Skip to content

Commit c904b29

Browse files
committed
Add additional safe serializers for commonly used JDK classes
1 parent 9947cdb commit c904b29

File tree

2 files changed

+193
-5
lines changed

2 files changed

+193
-5
lines changed

src/com/esotericsoftware/kryo/serializers/DefaultSerializers.java

+112-2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
import java.math.BigDecimal;
3535
import java.math.BigInteger;
3636
import java.net.MalformedURLException;
37+
import java.net.URI;
38+
import java.net.URISyntaxException;
3739
import java.net.URL;
3840
import java.nio.charset.Charset;
3941
import java.sql.Time;
@@ -58,7 +60,13 @@
5860
import java.util.TimeZone;
5961
import java.util.TreeMap;
6062
import java.util.TreeSet;
63+
import java.util.UUID;
6164
import java.util.concurrent.ConcurrentSkipListMap;
65+
import java.util.concurrent.atomic.AtomicBoolean;
66+
import java.util.concurrent.atomic.AtomicInteger;
67+
import java.util.concurrent.atomic.AtomicLong;
68+
import java.util.concurrent.atomic.AtomicReference;
69+
import java.util.regex.Pattern;
6270

6371
/** Contains many serializer classes that are provided by {@link Kryo#addDefaultSerializer(Class, Class) default}.
6472
* @author Nathan Sweet */
@@ -900,6 +908,7 @@ public List copy (Kryo kryo, List original) {
900908
}
901909
}
902910

911+
/** Serializer for {@link BitSet} */
903912
public static class BitSetSerializer extends Serializer<BitSet> {
904913
public void write (Kryo kryo, Output output, BitSet set) {
905914
long[] values = set.toLongArray();
@@ -910,12 +919,113 @@ public void write (Kryo kryo, Output output, BitSet set) {
910919
public BitSet read (Kryo kryo, Input input, Class type) {
911920
int length = input.readVarInt(true);
912921
long[] values = input.readLongs(length);
913-
BitSet set = BitSet.valueOf(values);
914-
return set;
922+
return BitSet.valueOf(values);
915923
}
916924

917925
public BitSet copy (Kryo kryo, BitSet original) {
918926
return BitSet.valueOf(original.toLongArray());
919927
}
920928
}
929+
930+
/** Serializer for {@link Pattern} */
931+
public static class PatternSerializer extends ImmutableSerializer<Pattern> {
932+
public void write (final Kryo kryo, final Output output, final Pattern pattern) {
933+
output.writeString(pattern.pattern());
934+
output.writeInt(pattern.flags(), true);
935+
}
936+
937+
public Pattern read (final Kryo kryo, final Input input, final Class<? extends Pattern> patternClass) {
938+
String regex = input.readString();
939+
int flags = input.readInt(true);
940+
return Pattern.compile(regex, flags);
941+
}
942+
}
943+
944+
/** Serializer for {@link URI} */
945+
public static class URISerializer extends ImmutableSerializer<java.net.URI> {
946+
public void write (Kryo kryo, Output output, URI uri) {
947+
output.writeString(uri.toString());
948+
}
949+
950+
public URI read (Kryo kryo, Input input, Class<? extends URI> uriClass) {
951+
try {
952+
return new URI(input.readString());
953+
} catch (URISyntaxException ex) {
954+
throw new KryoException(ex);
955+
}
956+
}
957+
}
958+
959+
/** Serializer for {@link UUID} */
960+
public static class UUIDSerializer extends ImmutableSerializer<UUID> {
961+
public void write (Kryo kryo, Output output, UUID uuid) {
962+
output.writeLong(uuid.getMostSignificantBits());
963+
output.writeLong(uuid.getLeastSignificantBits());
964+
}
965+
966+
public UUID read (final Kryo kryo, final Input input, final Class<? extends UUID> uuidClass) {
967+
return new UUID(input.readLong(), input.readLong());
968+
}
969+
}
970+
971+
/** Serializer for {@link AtomicBoolean} */
972+
public static class AtomicBooleanSerializer extends Serializer<AtomicBoolean> {
973+
public void write (Kryo kryo, Output output, AtomicBoolean object) {
974+
output.writeBoolean(object.get());
975+
}
976+
977+
public AtomicBoolean read (Kryo kryo, Input input, Class<? extends AtomicBoolean> type) {
978+
return new AtomicBoolean(input.readBoolean());
979+
}
980+
981+
public AtomicBoolean copy (Kryo kryo, AtomicBoolean original) {
982+
return new AtomicBoolean(original.get());
983+
}
984+
}
985+
986+
/** Serializer for {@link AtomicInteger} */
987+
public static class AtomicIntegerSerializer extends Serializer<AtomicInteger> {
988+
public void write (Kryo kryo, Output output, AtomicInteger object) {
989+
output.writeInt(object.get());
990+
}
991+
992+
public AtomicInteger read (Kryo kryo, Input input, Class<? extends AtomicInteger> type) {
993+
return new AtomicInteger(input.readInt());
994+
}
995+
996+
public AtomicInteger copy (Kryo kryo, AtomicInteger original) {
997+
return new AtomicInteger(original.get());
998+
}
999+
}
1000+
1001+
/** Serializer for {@link AtomicLong} */
1002+
public static class AtomicLongSerializer extends Serializer<AtomicLong> {
1003+
public void write (Kryo kryo, Output output, AtomicLong object) {
1004+
output.writeLong(object.get());
1005+
}
1006+
1007+
public AtomicLong read (Kryo kryo, Input input, Class<? extends AtomicLong> type) {
1008+
return new AtomicLong(input.readLong());
1009+
}
1010+
1011+
public AtomicLong copy (Kryo kryo, AtomicLong original) {
1012+
return new AtomicLong(original.get());
1013+
}
1014+
}
1015+
1016+
/** Serializer for {@link AtomicReference} */
1017+
public static class AtomicReferenceSerializer extends Serializer<AtomicReference> {
1018+
public void write (Kryo kryo, Output output, AtomicReference object) {
1019+
kryo.writeClassAndObject(output, object.get());
1020+
}
1021+
1022+
public AtomicReference read (Kryo kryo, Input input, Class<? extends AtomicReference> type) {
1023+
final Object value = kryo.readClassAndObject(input);
1024+
return new AtomicReference(value);
1025+
}
1026+
1027+
public AtomicReference copy (Kryo kryo, AtomicReference original) {
1028+
return new AtomicReference<>(kryo.copy(original.get()));
1029+
}
1030+
}
9211031
}

test/com/esotericsoftware/kryo/serializers/DefaultSerializersTest.java

+81-3
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
import java.math.BigDecimal;
3131
import java.math.BigInteger;
32+
import java.net.URI;
3233
import java.net.URL;
3334
import java.nio.charset.Charset;
3435
import java.util.ArrayList;
@@ -43,6 +44,12 @@
4344
import java.util.Locale;
4445
import java.util.PriorityQueue;
4546
import java.util.TimeZone;
47+
import java.util.UUID;
48+
import java.util.concurrent.atomic.AtomicBoolean;
49+
import java.util.concurrent.atomic.AtomicInteger;
50+
import java.util.concurrent.atomic.AtomicLong;
51+
import java.util.concurrent.atomic.AtomicReference;
52+
import java.util.regex.Pattern;
4653

4754
import org.junit.jupiter.api.Test;
4855
import org.objenesis.strategy.StdInstantiatorStrategy;
@@ -518,19 +525,90 @@ void testArraysAsListDeepCopy () throws Exception {
518525

519526
@Test
520527
void testURLSerializer () throws Exception {
521-
kryo.setInstantiatorStrategy(new DefaultInstantiatorStrategy(new StdInstantiatorStrategy()));
522528
kryo.register(URL.class);
523529

524530
roundTrip(42, new URL("https://github.com/EsotericSoftware/kryo"));
525531
roundTrip(78, new URL("https://github.com:443/EsotericSoftware/kryo/pulls?utf8=%E2%9C%93&q=is%3Apr"));
526532
}
527533

534+
@Test
535+
void testURISerializer () throws Exception {
536+
kryo.register(URI.class, new DefaultSerializers.URISerializer());
537+
538+
roundTrip(42, new URI("https://github.com/EsotericSoftware/kryo"));
539+
roundTrip(78, new URI("https://github.com:443/EsotericSoftware/kryo/pulls?utf8=%E2%9C%93&q=is%3Apr"));
540+
}
541+
542+
@Test
543+
void testUUIDSerializer () {
544+
kryo.register(UUID.class, new DefaultSerializers.UUIDSerializer());
545+
546+
roundTrip(17, UUID.fromString("e58ed763-928c-4155-bee9-fdbaaadc15f3"));
547+
}
548+
549+
@Test
550+
void testPatternSerializer () {
551+
kryo.register(Pattern.class, new DefaultSerializers.PatternSerializer());
552+
553+
roundTrip(4, Pattern.compile(".", Pattern.DOTALL));
554+
roundTrip(4, Pattern.compile("."));
555+
}
556+
557+
@Test
558+
void testAtomicBooleanSerializer () {
559+
kryo.register(AtomicBoolean.class, new DefaultSerializers.AtomicBooleanSerializer());
560+
561+
roundTrip(2, new AtomicBoolean(true));
562+
roundTrip(2, new AtomicBoolean(false));
563+
}
564+
565+
@Test
566+
void testAtomicIntegerSerializer () {
567+
kryo.register(AtomicInteger.class, new DefaultSerializers.AtomicIntegerSerializer());
568+
569+
roundTrip(5, new AtomicInteger());
570+
roundTrip(5, new AtomicInteger(0));
571+
roundTrip(5, new AtomicInteger(1));
572+
roundTrip(5, new AtomicInteger(-1));
573+
}
574+
575+
@Test
576+
void testAtomicLongSerializer () {
577+
kryo.register(AtomicLong.class, new DefaultSerializers.AtomicLongSerializer());
578+
579+
roundTrip(9, new AtomicLong());
580+
roundTrip(9, new AtomicLong(0));
581+
roundTrip(9, new AtomicLong(1));
582+
roundTrip(9, new AtomicLong(-1));
583+
}
584+
585+
@Test
586+
void testAtomicReferenceSerializer () {
587+
kryo.register(AtomicReference.class, new DefaultSerializers.AtomicReferenceSerializer());
588+
589+
roundTrip(2, new AtomicReference<>());
590+
roundTrip(3, new AtomicReference<>(1L));
591+
}
592+
528593
protected void doAssertEquals(Object object1, Object object2) {
529594
if (object1 instanceof PriorityQueue && object2 instanceof PriorityQueue) {
530595
final PriorityQueue q1 = (PriorityQueue) object1;
531596
final PriorityQueue q2 = (PriorityQueue) object2;
532-
super.doAssertEquals(q1.peek(), q2.peek());
533-
super.doAssertEquals(q1.toArray(), q2.toArray());
597+
super.doAssertEquals(q1.peek(), q2.peek());
598+
super.doAssertEquals(q1.toArray(), q2.toArray());
599+
} else if (object1 instanceof Pattern && object2 instanceof Pattern) {
600+
final Pattern q1 = (Pattern)object1;
601+
final Pattern q2 = (Pattern)object2;
602+
super.doAssertEquals(q1.pattern(), q2.pattern());
603+
super.doAssertEquals(q1.flags(), q2.flags());
604+
} else if (object1 instanceof AtomicBoolean && object2 instanceof AtomicBoolean) {
605+
super.doAssertEquals(((AtomicBoolean)object1).get(), ((AtomicBoolean)object2).get());
606+
} else if (object1 instanceof AtomicInteger && object2 instanceof AtomicInteger) {
607+
super.doAssertEquals(((AtomicInteger)object1).get(), ((AtomicInteger)object2).get());
608+
} else if (object1 instanceof AtomicLong && object2 instanceof AtomicLong) {
609+
super.doAssertEquals(((AtomicLong)object1).get(), ((AtomicLong)object2).get());
610+
} else if (object1 instanceof AtomicReference && object2 instanceof AtomicReference) {
611+
super.doAssertEquals(((AtomicReference)object1).get(), ((AtomicReference)object2).get());
534612
} else {
535613
super.doAssertEquals(object1, object2);
536614
}

0 commit comments

Comments
 (0)