From 499a7b6368720f36edc55c9d1fcbe10bade00c1d Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Wed, 17 Dec 2014 20:02:22 -0800 Subject: [PATCH] Implemented #654 --- release-notes/VERSION | 1 + .../jackson/databind/ObjectWriter.java | 84 ++++++++++++++++--- .../databind/seq/SequenceWriterTest.java | 6 +- 3 files changed, 76 insertions(+), 15 deletions(-) diff --git a/release-notes/VERSION b/release-notes/VERSION index e4c00654a6..626421f666 100644 --- a/release-notes/VERSION +++ b/release-notes/VERSION @@ -62,6 +62,7 @@ Project: jackson-databind (using @JsonAppend, VirtualBeanPropertyWriter) #647: Deserialization fails when @JsonUnwrapped property contains an object with same property name (reported by Konstantin L) +#654: Add support for (re)configuring `JsonGenerator.setRootValueSeparator()` via `ObjectWriter` #655: Add `ObjectWriter.writeValues()` for writing value sequences - Allow use of `Shape.ARRAY` for Enums, as an alias to 'use index' - Start using `JsonGenerator.writeStartArray(int)` to help data formats diff --git a/src/main/java/com/fasterxml/jackson/databind/ObjectWriter.java b/src/main/java/com/fasterxml/jackson/databind/ObjectWriter.java index e4cc60ef89..6d0146f1d0 100644 --- a/src/main/java/com/fasterxml/jackson/databind/ObjectWriter.java +++ b/src/main/java/com/fasterxml/jackson/databind/ObjectWriter.java @@ -8,6 +8,7 @@ import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.io.CharacterEscapes; import com.fasterxml.jackson.core.io.SegmentedStringWriter; +import com.fasterxml.jackson.core.io.SerializedString; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.util.*; import com.fasterxml.jackson.databind.cfg.ContextAttributes; @@ -98,7 +99,7 @@ protected ObjectWriter(ObjectMapper mapper, SerializationConfig config, _serializerFactory = mapper._serializerFactory; _generatorFactory = mapper._jsonFactory; _generatorSettings = (pp == null) ? GeneratorSettings.empty - : new GeneratorSettings(pp, null, null); + : new GeneratorSettings(pp, null, null, null); // 29-Apr-2014, tatu: There is no "untyped serializer", so: if (rootType == null || rootType.hasRawClass(Object.class)) { @@ -137,7 +138,7 @@ protected ObjectWriter(ObjectMapper mapper, SerializationConfig config, _prefetch = Prefetch.empty; _generatorSettings = (s == null) ? GeneratorSettings.empty - : new GeneratorSettings(null, s, null); + : new GeneratorSettings(null, s, null, null); } /** @@ -580,6 +581,28 @@ public ObjectWriter withoutAttribute(Object key) { return (newConfig == _config) ? this : _new(this, newConfig); } + /** + * @since 2.5 + */ + public ObjectWriter withRootValueSeparator(String sep) { + GeneratorSettings genSet = _generatorSettings.withRootValueSeparator(sep); + if (genSet == _generatorSettings) { + return this; + } + return _new(genSet, _prefetch); + } + + /** + * @since 2.5 + */ + public ObjectWriter withRootValueSeparator(SerializableString sep) { + GeneratorSettings genSet = _generatorSettings.withRootValueSeparator(sep); + if (genSet == _generatorSettings) { + return this; + } + return _new(genSet, _prefetch); + } + /* /********************************************************** /* Factory methods for sequence writers (2.5) @@ -1192,11 +1215,14 @@ protected JsonGenerator _configureGenerator(JsonGenerator gen) if (esc != null) { gen.setCharacterEscapes(esc); } - // [JACKSON-520]: add support for pass-through schema: FormatSchema sch = genSet.schema; if (sch != null) { gen.setSchema(sch); } + SerializableString sep = genSet.rootValueSeparator; + if (sep != null) { + gen.setRootValueSeparator(sep); + } _config.initialize(gen); // since 2.5 return gen; } @@ -1219,31 +1245,41 @@ public final static class GeneratorSettings { private static final long serialVersionUID = 1L; - public final static GeneratorSettings empty = new GeneratorSettings(null, null, null); - + public final static GeneratorSettings empty = new GeneratorSettings(null, null, null, null); + /** * To allow for dynamic enabling/disabling of pretty printing, * pretty printer can be optionally configured for writer * as well */ public final PrettyPrinter prettyPrinter; - + /** * When using data format that uses a schema, schema is passed * to generator. */ public final FormatSchema schema; - + /** * Caller may want to specify character escaping details, either as * defaults, or on call-by-call basis. */ public final CharacterEscapes characterEscapes; - public GeneratorSettings(PrettyPrinter pp, FormatSchema sch, CharacterEscapes esc) { + /** + * Caller may want to override so-called "root value separator", + * String added (verbatim, with no quoting or escaping) between + * values in root context. Default value is a single space character, + * but this is often changed to linefeed. + */ + public final SerializableString rootValueSeparator; + + public GeneratorSettings(PrettyPrinter pp, FormatSchema sch, + CharacterEscapes esc, SerializableString rootSep) { prettyPrinter = pp; schema = sch; characterEscapes = esc; + rootValueSeparator = rootSep; } public GeneratorSettings with(PrettyPrinter pp) { @@ -1252,17 +1288,43 @@ public GeneratorSettings with(PrettyPrinter pp) { pp = NULL_PRETTY_PRINTER; } return (pp == prettyPrinter) ? this - : new GeneratorSettings(pp, schema, characterEscapes); + : new GeneratorSettings(pp, schema, characterEscapes, rootValueSeparator); } public GeneratorSettings with(FormatSchema sch) { return (schema == sch) ? this - : new GeneratorSettings(prettyPrinter, sch, characterEscapes); + : new GeneratorSettings(prettyPrinter, sch, characterEscapes, rootValueSeparator); } public GeneratorSettings with(CharacterEscapes esc) { return (characterEscapes == esc) ? this - : new GeneratorSettings(prettyPrinter, schema, esc); + : new GeneratorSettings(prettyPrinter, schema, esc, rootValueSeparator); + } + + public GeneratorSettings withRootValueSeparator(String sep) { + if (sep == null) { + if (rootValueSeparator == null) { + return this; + } + } else if (sep.equals(rootValueSeparator)) { + return this; + } + return new GeneratorSettings(prettyPrinter, schema, characterEscapes, + (sep == null) ? null : new SerializedString(sep)); + } + + public GeneratorSettings withRootValueSeparator(SerializableString sep) { + if (sep == null) { + if (rootValueSeparator == null) { + return this; + } + } else { + if (rootValueSeparator != null + && sep.getValue().equals(rootValueSeparator.getValue())) { + return this; + } + } + return new GeneratorSettings(prettyPrinter, schema, characterEscapes, sep); } } diff --git a/src/test/java/com/fasterxml/jackson/databind/seq/SequenceWriterTest.java b/src/test/java/com/fasterxml/jackson/databind/seq/SequenceWriterTest.java index 3351d7a8e8..43c6edb542 100644 --- a/src/test/java/com/fasterxml/jackson/databind/seq/SequenceWriterTest.java +++ b/src/test/java/com/fasterxml/jackson/databind/seq/SequenceWriterTest.java @@ -47,10 +47,8 @@ static class ImplB extends PolyBase { */ private final ObjectMapper MAPPER = new ObjectMapper(); - { - MAPPER.getFactory().setRootValueSeparator("\n"); - } - private final ObjectWriter WRITER = MAPPER.writer(); + private final ObjectWriter WRITER = MAPPER.writer() + .withRootValueSeparator("\n"); public void testSimpleNonArray() throws Exception {