From 2aee38eebb10ffaf4f2a8fc16fb81199ebbee4b6 Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Mon, 16 Dec 2019 22:14:44 -0800 Subject: [PATCH] Continue work on #70, first feature should work (but lacking tests) --- .../jr/ob/api/ReaderWriterModifier.java | 58 ++++++++++++++++++- .../jr/ob/impl/ValueReaderLocator.java | 12 ++++ .../jr/ob/impl/ValueWriterLocator.java | 25 ++++++-- 3 files changed, 90 insertions(+), 5 deletions(-) diff --git a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/api/ReaderWriterModifier.java b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/api/ReaderWriterModifier.java index 50e51d3c..0e498d29 100644 --- a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/api/ReaderWriterModifier.java +++ b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/api/ReaderWriterModifier.java @@ -14,15 +14,71 @@ public abstract class ReaderWriterModifier { // // Reader handling + /** + * Method called after {@link ValueReader} to use has been constructed, but + * before it is to be used for the first time. Method may either return that + * reader as-is, or construct a different {@link ValueReader} and return that + * to be used. + *

+ * This method is often used to create a new {@link ValueReader} that needs to + * delegate to the original reader for some uses, but not all. + * + * @param readContext Context that may be used to access configuration + * @param type Type of values to read + * @param defaultReader {@link ValueReader} that is to be used + * + * @return either {@code defaultReader} as-is, or an alternate {@link ValueReader} to use. + */ public ValueReader modifyValueReader(JSONReader readContext, Class type, ValueReader defaultReader) { - return null; + return defaultReader; } // // Writer handling + /** + * Method called after {@link ValueWriter} to use has been constructed, but + * before it is to be used for the first time. Method may either return that + * writer as-is, or construct a different {@link ValueWriter} and return that + * to be used. + *

+ * Note that this method is NOT called for non-POJO JDK "standard" values that + * jackson-jr supports (such as {@link java.lang.Number}s, {@link java.lang.String} + * and {@link java.net.URL}); for these types, {@link #overrideStandardValueWriter} + * is called instead. + *

+ * This method is often used to create a new {@link ValueReader} that needs to + * delegate to the original reader for some uses, but not all. + * + * @param writeContext Context that may be used to access configuration + * @param type Type of values to write + * @param defaultWriter {@link ValueReader} that is to be used + * + * @return either {@code defaultReader} as-is, or an alternate {@link ValueWriter} to use; + * must not return {@code null}. + */ public ValueWriter modifyValueWriter(JSONWriter writeContext, Class type, ValueWriter defaultWriter) { + return defaultWriter; + } + + /** + * Method called instead of {@link #modifyValueWriter} for set of non-POJO + * "standard" JDK types that do not have matching {@link ValueWriter} and are + * normally directly serialized by {@link JSONWriter} itself. + * Handler may either return {@code null} to indicate "no override" or return + * custom {@link ValueWriter} to use. + * + * @param writeContext Context that may be used to access configuration + * @param type Type of values to write + * @param stdTypeId Internal identifier of standard type (not usually useful, + * but could potentially be used for delegating) + * + * @return {@code null} if no override should occur, or {@link ValueWriter} + * to use. + */ + public ValueWriter overrideStandardValueWriter(JSONWriter writeContext, + Class type, int stdTypeId) { return null; } } diff --git a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/ValueReaderLocator.java b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/ValueReaderLocator.java index d0c1b029..dc6a3952 100644 --- a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/ValueReaderLocator.java +++ b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/ValueReaderLocator.java @@ -217,6 +217,18 @@ public ValueReader findReader(Class raw) * for {@link java.util.Map}, {@link java.util.Collection}). */ protected ValueReader createReader(Class contextType, Class type, Type genericType) + { + ValueReader r = _createReader(contextType, type, genericType); + if (_readerModifier != null) { + r = _readerModifier.modifyValueReader(_readContext, type, r); + if (r == null) { // sanity check + throw new IllegalArgumentException("ReaderWriterModifier.modifyValueReader() returned null"); + } + } + return r; + } + + protected ValueReader _createReader(Class contextType, Class type, Type genericType) { if (type == Object.class) { return AnyReader.std; diff --git a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/ValueWriterLocator.java b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/ValueWriterLocator.java index 9bda491f..cd1259f5 100644 --- a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/ValueWriterLocator.java +++ b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/impl/ValueWriterLocator.java @@ -158,7 +158,7 @@ public final int findSerializationType(Class raw) if (raw == _prevClass) { return _prevType; } - if (raw == String.class) { + if (raw == String.class && (_writerModifier == null)) { return SER_STRING; } ClassKey k = (_key == null) ? new ClassKey(raw, _features) : _key.with(raw, _features); @@ -202,21 +202,38 @@ protected int _findPOJOSerializationType(Class raw) if (_writerProvider != null) { ValueWriter w = _writerProvider.findValueWriter(_writeContext, raw); if (w != null) { - return _registerWriter(raw, w); + return _modifyAndRegisterWriter(raw, w); } } - + int type = _findSimpleType(raw, true); if (type == SER_UNKNOWN) { if (JSON.Feature.HANDLE_JAVA_BEANS.isEnabled(_features)) { final BeanPropertyWriter[] props = _resolveBeanForSer(raw, _resolveBeanDef(raw)); - return _registerWriter(raw, new BeanWriter(raw, props)); + return _modifyAndRegisterWriter(raw, new BeanWriter(raw, props)); + } + } else { + if (_writerModifier != null) { + ValueWriter w = _writerModifier.overrideStandardValueWriter(_writeContext, raw, type); + if (w != null) { + return _registerWriter(raw, w); + } } } return type; } + private int _modifyAndRegisterWriter(Class rawType, ValueWriter w) { + if (_writerModifier != null) { + w = _writerModifier.modifyValueWriter(_writeContext, rawType, w); + if (w == null) { // sanity check + throw new IllegalArgumentException("ReaderWriterModifier.modifyValueWriter() returned null"); + } + } + return _registerWriter(rawType, w); + } + private int _registerWriter(Class rawType, ValueWriter valueWriter) { // Due to concurrent access, possible that someone might have added it synchronized (_knownWriters) {