diff --git a/jakarta-jsonp/src/main/java/com/fasterxml/jackson/datatype/jsonp/JSONPModule.java b/jakarta-jsonp/src/main/java/com/fasterxml/jackson/datatype/jsonp/JSONPModule.java index d16db90..4e3f2a4 100644 --- a/jakarta-jsonp/src/main/java/com/fasterxml/jackson/datatype/jsonp/JSONPModule.java +++ b/jakarta-jsonp/src/main/java/com/fasterxml/jackson/datatype/jsonp/JSONPModule.java @@ -6,8 +6,11 @@ import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.module.SimpleDeserializers; import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.databind.ser.std.StdDelegatingSerializer; import com.fasterxml.jackson.databind.type.CollectionType; import com.fasterxml.jackson.databind.type.MapType; +import com.fasterxml.jackson.databind.util.Converter; +import com.fasterxml.jackson.databind.util.StdConverter; import jakarta.json.*; import jakarta.json.spi.JsonProvider; @@ -34,6 +37,10 @@ public JSONPModule(JsonProvider jsonProvider) { final JsonMergePatchDeserializer jsonMergePatchDeser = new JsonMergePatchDeserializer(jsonValueDeser); addSerializer(JsonValue.class, new JsonValueSerializer()); + // Since 2.14.2 + addSerializer(JsonPatch.class, new JsonPatchSerializer()); + addSerializer(JsonMergePatch.class, new JsonMergePatchSerializer()); + setDeserializers(new SimpleDeserializers() { @Override public JsonDeserializer findBeanDeserializer( @@ -93,4 +100,68 @@ public boolean hasDeserializerFor(DeserializationConfig config, Class valueTy } }); } + + /** + * @since 2.14.2 + */ + static class JsonPatchSerializer extends StdDelegatingSerializer + { + private static final long serialVersionUID = 1L; + + public JsonPatchSerializer() { + super(new PatchConverter()); + } + + protected JsonPatchSerializer(Converter converter, + JavaType delegateType, JsonSerializer delegateSerialize) { + super(converter, delegateType, delegateSerialize); + } + + @Override + protected StdDelegatingSerializer withDelegate(Converter converter, + JavaType delegateType, JsonSerializer delegateSerializer) { + return new JsonPatchSerializer(converter, delegateType, delegateSerializer); + } + + static class PatchConverter + extends StdConverter + { + @Override + public JsonArray convert(JsonPatch value) { + return value.toJsonArray(); + } + } + } + + /** + * @since 2.14.2 + */ + static class JsonMergePatchSerializer extends StdDelegatingSerializer + { + private static final long serialVersionUID = 1L; + + public JsonMergePatchSerializer() { + super(new PatchConverter()); + } + + protected JsonMergePatchSerializer(Converter converter, + JavaType delegateType, JsonSerializer delegateSerialize) { + super(converter, delegateType, delegateSerialize); + } + + @Override + protected StdDelegatingSerializer withDelegate(Converter converter, + JavaType delegateType, JsonSerializer delegateSerializer) { + return new JsonMergePatchSerializer(converter, delegateType, delegateSerializer); + } + + static class PatchConverter + extends StdConverter + { + @Override + public JsonValue convert(JsonMergePatch value) { + return value.toJsonValue(); + } + } + } } diff --git a/jakarta-jsonp/src/test/java/com/fasterxml/jackson/datatype/jsonp/JsonMergePatchSerializationTest.java b/jakarta-jsonp/src/test/java/com/fasterxml/jackson/datatype/jsonp/JsonMergePatchSerializationTest.java new file mode 100644 index 0000000..06ccfa8 --- /dev/null +++ b/jakarta-jsonp/src/test/java/com/fasterxml/jackson/datatype/jsonp/JsonMergePatchSerializationTest.java @@ -0,0 +1,24 @@ +package com.fasterxml.jackson.datatype.jsonp; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import jakarta.json.JsonMergePatch; + +public class JsonMergePatchSerializationTest extends TestBase +{ + private static final ObjectMapper MAPPER = newMapper(); + + public void testSimpleSerialization() throws Exception + { + // First need a patch so deserialization must work + final String input = "{" + + "\"name\":\"Json\"" + + "}"; + final JsonMergePatch patch1 = MAPPER.readValue(input, JsonMergePatch.class); + final String output = MAPPER.writeValueAsString(patch1); + + // and read back + final JsonMergePatch patch2 = MAPPER.readValue(output, JsonMergePatch.class); + assertEquals(patch1.toJsonValue(), patch2.toJsonValue()); + } +} diff --git a/jakarta-jsonp/src/test/java/com/fasterxml/jackson/datatype/jsonp/JsonPatchSerializationTest.java b/jakarta-jsonp/src/test/java/com/fasterxml/jackson/datatype/jsonp/JsonPatchSerializationTest.java new file mode 100644 index 0000000..13c6763 --- /dev/null +++ b/jakarta-jsonp/src/test/java/com/fasterxml/jackson/datatype/jsonp/JsonPatchSerializationTest.java @@ -0,0 +1,28 @@ +package com.fasterxml.jackson.datatype.jsonp; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import jakarta.json.JsonPatch; + +public class JsonPatchSerializationTest extends TestBase +{ + private static final ObjectMapper MAPPER = newMapper(); + + public void testSimpleSerialization() throws Exception + { + // First need a patch so deserialization must work + final String input = "[" + + "{" + + "\"op\":\"replace\"," + + "\"path\":\"/name\"," + + "\"value\":\"Json\"" + + "}" + + "]"; + final JsonPatch jsonPatch = MAPPER.readValue(input, JsonPatch.class); + final String output = MAPPER.writeValueAsString(jsonPatch); + + // and read back + final JsonPatch jsonPatch2 = MAPPER.readValue(output, JsonPatch.class); + assertEquals(jsonPatch, jsonPatch2); + } +} diff --git a/jsr-353/src/main/java/com/fasterxml/jackson/datatype/jsr353/JSR353Module.java b/jsr-353/src/main/java/com/fasterxml/jackson/datatype/jsr353/JSR353Module.java index c9cc1b8..c89b754 100644 --- a/jsr-353/src/main/java/com/fasterxml/jackson/datatype/jsr353/JSR353Module.java +++ b/jsr-353/src/main/java/com/fasterxml/jackson/datatype/jsr353/JSR353Module.java @@ -1,15 +1,18 @@ package com.fasterxml.jackson.datatype.jsr353; +import javax.json.*; +import javax.json.spi.JsonProvider; +import java.util.Collections; + import com.fasterxml.jackson.databind.*; import com.fasterxml.jackson.databind.jsontype.TypeDeserializer; import com.fasterxml.jackson.databind.module.SimpleDeserializers; import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.databind.ser.std.StdDelegatingSerializer; import com.fasterxml.jackson.databind.type.CollectionType; import com.fasterxml.jackson.databind.type.MapType; - -import javax.json.*; -import javax.json.spi.JsonProvider; -import java.util.Collections; +import com.fasterxml.jackson.databind.util.Converter; +import com.fasterxml.jackson.databind.util.StdConverter; public class JSR353Module extends SimpleModule { @@ -35,6 +38,10 @@ public JSR353Module(JsonProvider jsonProvider) final JsonMergePatchDeserializer jsonMergePatchDeser = new JsonMergePatchDeserializer(jsonValueDeser); addSerializer(JsonValue.class, new JsonValueSerializer()); + // Since 2.14.2 + addSerializer(JsonPatch.class, new JsonPatchSerializer()); + addSerializer(JsonMergePatch.class, new JsonMergePatchSerializer()); + setDeserializers(new SimpleDeserializers() { @Override public JsonDeserializer findBeanDeserializer( @@ -94,4 +101,68 @@ public boolean hasDeserializerFor(DeserializationConfig config, Class valueTy } }); } + + /** + * @since 2.14.2 + */ + static class JsonPatchSerializer extends StdDelegatingSerializer + { + private static final long serialVersionUID = 1L; + + public JsonPatchSerializer() { + super(new PatchConverter()); + } + + protected JsonPatchSerializer(Converter converter, + JavaType delegateType, JsonSerializer delegateSerialize) { + super(converter, delegateType, delegateSerialize); + } + + @Override + protected StdDelegatingSerializer withDelegate(Converter converter, + JavaType delegateType, JsonSerializer delegateSerializer) { + return new JsonPatchSerializer(converter, delegateType, delegateSerializer); + } + + static class PatchConverter + extends StdConverter + { + @Override + public JsonArray convert(JsonPatch value) { + return value.toJsonArray(); + } + } + } + + /** + * @since 2.14.2 + */ + static class JsonMergePatchSerializer extends StdDelegatingSerializer + { + private static final long serialVersionUID = 1L; + + public JsonMergePatchSerializer() { + super(new PatchConverter()); + } + + protected JsonMergePatchSerializer(Converter converter, + JavaType delegateType, JsonSerializer delegateSerialize) { + super(converter, delegateType, delegateSerialize); + } + + @Override + protected StdDelegatingSerializer withDelegate(Converter converter, + JavaType delegateType, JsonSerializer delegateSerializer) { + return new JsonMergePatchSerializer(converter, delegateType, delegateSerializer); + } + + static class PatchConverter + extends StdConverter + { + @Override + public JsonValue convert(JsonMergePatch value) { + return value.toJsonValue(); + } + } + } } diff --git a/jsr-353/src/test/java/com/fasterxml/jackson/datatype/jsr353/JsonMergePatchSerializationTest.java b/jsr-353/src/test/java/com/fasterxml/jackson/datatype/jsr353/JsonMergePatchSerializationTest.java new file mode 100644 index 0000000..5e4e632 --- /dev/null +++ b/jsr-353/src/test/java/com/fasterxml/jackson/datatype/jsr353/JsonMergePatchSerializationTest.java @@ -0,0 +1,24 @@ +package com.fasterxml.jackson.datatype.jsr353; + +import javax.json.JsonMergePatch; + +import com.fasterxml.jackson.databind.ObjectMapper; + +public class JsonMergePatchSerializationTest extends TestBase +{ + private static final ObjectMapper MAPPER = newMapper(); + + public void testSimpleSerialization() throws Exception + { + // First need a patch so deserialization must work + final String input = "{" + + "\"name\":\"Json\"" + + "}"; + final JsonMergePatch patch1 = MAPPER.readValue(input, JsonMergePatch.class); + final String output = MAPPER.writeValueAsString(patch1); + + // and read back + final JsonMergePatch patch2 = MAPPER.readValue(output, JsonMergePatch.class); + assertEquals(patch1.toJsonValue(), patch2.toJsonValue()); + } +} diff --git a/jsr-353/src/test/java/com/fasterxml/jackson/datatype/jsr353/JsonPatchSerializationTest.java b/jsr-353/src/test/java/com/fasterxml/jackson/datatype/jsr353/JsonPatchSerializationTest.java new file mode 100644 index 0000000..34b2c29 --- /dev/null +++ b/jsr-353/src/test/java/com/fasterxml/jackson/datatype/jsr353/JsonPatchSerializationTest.java @@ -0,0 +1,28 @@ +package com.fasterxml.jackson.datatype.jsr353; + +import javax.json.JsonPatch; + +import com.fasterxml.jackson.databind.ObjectMapper; + +public class JsonPatchSerializationTest extends TestBase +{ + private static final ObjectMapper MAPPER = newMapper(); + + public void testSimpleSerialization() throws Exception + { + // First need a patch so deserialization must work + final String input = "[" + + "{" + + "\"op\":\"replace\"," + + "\"path\":\"/name\"," + + "\"value\":\"Json\"" + + "}" + + "]"; + final JsonPatch jsonPatch = MAPPER.readValue(input, JsonPatch.class); + final String output = MAPPER.writeValueAsString(jsonPatch); + + // and read back + final JsonPatch jsonPatch2 = MAPPER.readValue(output, JsonPatch.class); + assertEquals(jsonPatch, jsonPatch2); + } +} diff --git a/release-notes/CREDITS-2.x b/release-notes/CREDITS-2.x index 2c3db30..9421e53 100644 --- a/release-notes/CREDITS-2.x +++ b/release-notes/CREDITS-2.x @@ -39,3 +39,8 @@ Andrzej PaƄkowski (apankowski@github) * Contributed #17: Add configurable amount representations for Joda Money module (2.14.0) + +Matt Nelson (mattnelson@github) + +* Suggested #28: Add delegating serializers for `JsonPatch` and `JsonMergePatch` + (2.14.2) diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x index 6a1a3e2..bfcf72f 100644 --- a/release-notes/VERSION-2.x +++ b/release-notes/VERSION-2.x @@ -10,6 +10,11 @@ Modules: === Releases === ------------------------------------------------------------------------ +2.14.2 (not yet released) + +#28: Add delegating serializers for `JsonPatch` and `JsonMergePatch` + (requested by Matt N) + 2.14.1 (21-Nov-2022) No changes since 2.14.0