From b0ca5edd4d01942552a789e839064c9838494611 Mon Sep 17 00:00:00 2001 From: Evan Galpin Date: Thu, 9 Jun 2022 10:41:19 -0400 Subject: [PATCH 1/5] Propose that JsonPointer be Serializable Noting that `Instances [of JsonPointer] are fully immutable and can be cached, shared between threads` it would be nice to be able to pass these between workers that require object serialization to pass instances around. --- src/main/java/com/fasterxml/jackson/core/JsonPointer.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/fasterxml/jackson/core/JsonPointer.java b/src/main/java/com/fasterxml/jackson/core/JsonPointer.java index 4b892981b7..7e77c0273d 100644 --- a/src/main/java/com/fasterxml/jackson/core/JsonPointer.java +++ b/src/main/java/com/fasterxml/jackson/core/JsonPointer.java @@ -17,8 +17,9 @@ * * @since 2.3 */ -public class JsonPointer +public class JsonPointer extends Serializable { + private static final long serialVersionUID = 1L; /** * Character used to separate segments. * From f53ef8457bee830a52ac7ebaafcf95dfcc6c97a8 Mon Sep 17 00:00:00 2001 From: egalpin Date: Fri, 10 Jun 2022 11:11:53 -0400 Subject: [PATCH 2/5] Adds _serialized String and Externalizable methods --- .../fasterxml/jackson/core/JsonPointer.java | 31 ++++++++++++++--- .../jackson/core/TestJsonPointer.java | 34 +++++++++++++++++++ 2 files changed, 61 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/core/JsonPointer.java b/src/main/java/com/fasterxml/jackson/core/JsonPointer.java index 7e77c0273d..9f2f95be7c 100644 --- a/src/main/java/com/fasterxml/jackson/core/JsonPointer.java +++ b/src/main/java/com/fasterxml/jackson/core/JsonPointer.java @@ -1,6 +1,11 @@ package com.fasterxml.jackson.core; import com.fasterxml.jackson.core.io.NumberInput; +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.io.ObjectStreamException; /** * Implementation of @@ -17,7 +22,7 @@ * * @since 2.3 */ -public class JsonPointer extends Serializable +public class JsonPointer implements Externalizable { private static final long serialVersionUID = 1L; /** @@ -60,7 +65,11 @@ public class JsonPointer extends Serializable * so that {@link #toString} should be as efficient as possible. */ protected final String _asString; - + /** + * Strictly used by serialization as an intermediate placeholder. + */ + private String _serialized; + protected final String _matchingPropertyName; protected final int _matchingElementIndex; @@ -73,9 +82,10 @@ public class JsonPointer extends Serializable /** * Constructor used for creating "empty" instance, used to represent - * state that matches current node. + * state that matches current node. Note that this constructor must be public for + * implementing {@link Externalizable}. */ - protected JsonPointer() { + public JsonPointer() { _nextSegment = null; _matchingPropertyName = ""; _matchingElementIndex = -1; @@ -644,4 +654,17 @@ private static void _appendEscape(StringBuilder sb, char c) { } sb.append(c); } + + @Override + public void writeExternal(ObjectOutput out) throws IOException { + out.writeUTF(_asString); + } + private Object readResolve() throws ObjectStreamException { + return compile(_serialized); + } + + @Override + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + _serialized = in.readUTF(); + } } diff --git a/src/test/java/com/fasterxml/jackson/core/TestJsonPointer.java b/src/test/java/com/fasterxml/jackson/core/TestJsonPointer.java index af8bafeee1..cd97792723 100644 --- a/src/test/java/com/fasterxml/jackson/core/TestJsonPointer.java +++ b/src/test/java/com/fasterxml/jackson/core/TestJsonPointer.java @@ -1,5 +1,12 @@ package com.fasterxml.jackson.core; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; + public class TestJsonPointer extends BaseTest { public void testSimplePath() throws Exception @@ -228,4 +235,31 @@ public void testLongNumbers() throws Exception assertTrue(ptr.matches()); assertNull(ptr.tail()); } + + private static byte[] pickle(T obj) + throws IOException + { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(obj); + oos.close(); + return baos.toByteArray(); + } + + private static T unpickle(byte[] b, Class cl) + throws IOException, ClassNotFoundException + { + ByteArrayInputStream bais = new ByteArrayInputStream(b); + ObjectInputStream ois = new ObjectInputStream(bais); + Object o = ois.readObject(); + return cl.cast(o); + } + public void testPointerSerialization() throws Exception { + + final String INPUT = "/Image/15/name"; + JsonPointer original = JsonPointer.compile(INPUT); + JsonPointer copy = unpickle(pickle(original), JsonPointer.class); + assertEquals(original, copy); + + } } From 8a81e9233182ba66bd9a08e41f6a6715692701d1 Mon Sep 17 00:00:00 2001 From: egalpin Date: Fri, 10 Jun 2022 11:21:16 -0400 Subject: [PATCH 3/5] Adds SerializableJsonPointer as alternative to maintain usage of final --- .../fasterxml/jackson/core/JsonPointer.java | 44 +++++++++++++------ 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/core/JsonPointer.java b/src/main/java/com/fasterxml/jackson/core/JsonPointer.java index 9f2f95be7c..e0292f7657 100644 --- a/src/main/java/com/fasterxml/jackson/core/JsonPointer.java +++ b/src/main/java/com/fasterxml/jackson/core/JsonPointer.java @@ -6,6 +6,7 @@ import java.io.ObjectInput; import java.io.ObjectOutput; import java.io.ObjectStreamException; +import java.io.Serializable; /** * Implementation of @@ -22,7 +23,7 @@ * * @since 2.3 */ -public class JsonPointer implements Externalizable +public class JsonPointer implements Serializable { private static final long serialVersionUID = 1L; /** @@ -65,10 +66,6 @@ public class JsonPointer implements Externalizable * so that {@link #toString} should be as efficient as possible. */ protected final String _asString; - /** - * Strictly used by serialization as an intermediate placeholder. - */ - private String _serialized; protected final String _matchingPropertyName; @@ -655,16 +652,35 @@ private static void _appendEscape(StringBuilder sb, char c) { sb.append(c); } - @Override - public void writeExternal(ObjectOutput out) throws IOException { - out.writeUTF(_asString); - } - private Object readResolve() throws ObjectStreamException { - return compile(_serialized); + private Object writeReplace() { + return new SerializableJsonPointer(_asString); } - @Override - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - _serialized = in.readUTF(); + /** + * This must only exist to allow both final properties and implementation of + * Externalizable/Serializable for JsonPointer + */ + private static class SerializableJsonPointer implements Externalizable { + private String _asString; + + public SerializableJsonPointer() { + } + + public SerializableJsonPointer(String asString) { + _asString = asString; + } + + @Override + public void writeExternal(ObjectOutput out) throws IOException { + out.writeUTF(_asString); + } + + @Override + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + _asString = in.readUTF(); + } + private Object readResolve() throws ObjectStreamException { + return compile(_asString); + } } } From 2dccb17c6f99aa5c9137aa2443c15eaa0e03bc1a Mon Sep 17 00:00:00 2001 From: egalpin Date: Fri, 10 Jun 2022 11:27:40 -0400 Subject: [PATCH 4/5] Adds assertion to verify that pickle/unpickle produces a new object --- src/test/java/com/fasterxml/jackson/core/TestJsonPointer.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/com/fasterxml/jackson/core/TestJsonPointer.java b/src/test/java/com/fasterxml/jackson/core/TestJsonPointer.java index cd97792723..5b6bd0cf42 100644 --- a/src/test/java/com/fasterxml/jackson/core/TestJsonPointer.java +++ b/src/test/java/com/fasterxml/jackson/core/TestJsonPointer.java @@ -259,6 +259,7 @@ public void testPointerSerialization() throws Exception { final String INPUT = "/Image/15/name"; JsonPointer original = JsonPointer.compile(INPUT); JsonPointer copy = unpickle(pickle(original), JsonPointer.class); + assertNotSame(copy, original); assertEquals(original, copy); } From d88aa75386468f332fd594d26a37fa69b550f0bf Mon Sep 17 00:00:00 2001 From: egalpin Date: Fri, 10 Jun 2022 14:37:11 -0400 Subject: [PATCH 5/5] Reverts access modifier change --- src/main/java/com/fasterxml/jackson/core/JsonPointer.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/core/JsonPointer.java b/src/main/java/com/fasterxml/jackson/core/JsonPointer.java index e0292f7657..f3cf93d954 100644 --- a/src/main/java/com/fasterxml/jackson/core/JsonPointer.java +++ b/src/main/java/com/fasterxml/jackson/core/JsonPointer.java @@ -76,13 +76,12 @@ public class JsonPointer implements Serializable /* Construction /********************************************************** */ - + /** * Constructor used for creating "empty" instance, used to represent - * state that matches current node. Note that this constructor must be public for - * implementing {@link Externalizable}. + * state that matches current node. */ - public JsonPointer() { + protected JsonPointer() { _nextSegment = null; _matchingPropertyName = ""; _matchingElementIndex = -1;