| package com.fasterxml.jackson.core.util; |
| |
| import java.io.*; |
| |
| import com.fasterxml.jackson.core.*; |
| import com.fasterxml.jackson.core.io.SerializedString; |
| |
| /** |
| * Default {@link PrettyPrinter} implementation that uses 2-space |
| * indentation with platform-default linefeeds. |
| * Usually this class is not instantiated directly, but instead |
| * method {@link JsonGenerator#useDefaultPrettyPrinter} is |
| * used, which will use an instance of this class for operation. |
| */ |
| @SuppressWarnings("serial") |
| public class DefaultPrettyPrinter |
| implements PrettyPrinter, Instantiatable<DefaultPrettyPrinter>, |
| java.io.Serializable |
| { |
| private static final long serialVersionUID = 1; |
| |
| /** |
| * Constant that specifies default "root-level" separator to use between |
| * root values: a single space character. |
| * |
| * @since 2.1 |
| */ |
| public final static SerializedString DEFAULT_ROOT_VALUE_SEPARATOR = new SerializedString(" "); |
| |
| /** |
| * Interface that defines objects that can produce indentation used |
| * to separate object entries and array values. Indentation in this |
| * context just means insertion of white space, independent of whether |
| * linefeeds are output. |
| */ |
| public interface Indenter |
| { |
| void writeIndentation(JsonGenerator g, int level) throws IOException; |
| |
| /** |
| * @return True if indenter is considered inline (does not add linefeeds), |
| * false otherwise |
| */ |
| boolean isInline(); |
| } |
| |
| // // // Config, indentation |
| |
| /** |
| * By default, let's use only spaces to separate array values. |
| */ |
| protected Indenter _arrayIndenter = FixedSpaceIndenter.instance; |
| |
| /** |
| * By default, let's use linefeed-adding indenter for separate |
| * object entries. We'll further configure indenter to use |
| * system-specific linefeeds, and 2 spaces per level (as opposed to, |
| * say, single tabs) |
| */ |
| protected Indenter _objectIndenter = DefaultIndenter.SYSTEM_LINEFEED_INSTANCE; |
| |
| /** |
| * String printed between root-level values, if any. |
| */ |
| protected final SerializableString _rootSeparator; |
| |
| // // // Config, other white space configuration |
| |
| /** |
| * By default we will add spaces around colons used to |
| * separate object fields and values. |
| * If disabled, will not use spaces around colon. |
| */ |
| protected boolean _spacesInObjectEntries = true; |
| |
| // // // State: |
| |
| /** |
| * Number of open levels of nesting. Used to determine amount of |
| * indentation to use. |
| */ |
| protected transient int _nesting; |
| |
| /** |
| * @since 2.9 |
| */ |
| protected Separators _separators; |
| |
| /** |
| * @since 2.9 |
| */ |
| protected String _objectFieldValueSeparatorWithSpaces; |
| |
| /* |
| /********************************************************** |
| /* Life-cycle (construct, configure) |
| /********************************************************** |
| */ |
| |
| public DefaultPrettyPrinter() { |
| this(DEFAULT_ROOT_VALUE_SEPARATOR); |
| } |
| |
| /** |
| * Constructor that specifies separator String to use between root values; |
| * if null, no separator is printed. |
| *<p> |
| * Note: simply constructs a {@link SerializedString} out of parameter, |
| * calls {@link #DefaultPrettyPrinter(SerializableString)} |
| * |
| * @param rootSeparator |
| * |
| * @since 2.1 |
| */ |
| public DefaultPrettyPrinter(String rootSeparator) { |
| this((rootSeparator == null) ? null : new SerializedString(rootSeparator)); |
| } |
| |
| /** |
| * Constructor that specifies separator String to use between root values; |
| * if null, no separator is printed. |
| * |
| * @param rootSeparator |
| * |
| * @since 2.1 |
| */ |
| public DefaultPrettyPrinter(SerializableString rootSeparator) { |
| _rootSeparator = rootSeparator; |
| withSeparators(DEFAULT_SEPARATORS); |
| } |
| |
| public DefaultPrettyPrinter(DefaultPrettyPrinter base) { |
| this(base, base._rootSeparator); |
| } |
| |
| public DefaultPrettyPrinter(DefaultPrettyPrinter base, |
| SerializableString rootSeparator) |
| { |
| _arrayIndenter = base._arrayIndenter; |
| _objectIndenter = base._objectIndenter; |
| _spacesInObjectEntries = base._spacesInObjectEntries; |
| _nesting = base._nesting; |
| |
| _separators = base._separators; |
| _objectFieldValueSeparatorWithSpaces = base._objectFieldValueSeparatorWithSpaces; |
| |
| _rootSeparator = rootSeparator; |
| } |
| |
| public DefaultPrettyPrinter withRootSeparator(SerializableString rootSeparator) |
| { |
| if (_rootSeparator == rootSeparator || |
| (rootSeparator != null && rootSeparator.equals(_rootSeparator))) { |
| return this; |
| } |
| return new DefaultPrettyPrinter(this, rootSeparator); |
| } |
| |
| /** |
| * @since 2.6.0 |
| */ |
| public DefaultPrettyPrinter withRootSeparator(String rootSeparator) { |
| return withRootSeparator((rootSeparator == null) ? null : new SerializedString(rootSeparator)); |
| } |
| |
| public void indentArraysWith(Indenter i) { |
| _arrayIndenter = (i == null) ? NopIndenter.instance : i; |
| } |
| |
| public void indentObjectsWith(Indenter i) { |
| _objectIndenter = (i == null) ? NopIndenter.instance : i; |
| } |
| |
| /** |
| * @since 2.3 |
| */ |
| public DefaultPrettyPrinter withArrayIndenter(Indenter i) { |
| if (i == null) { |
| i = NopIndenter.instance; |
| } |
| if (_arrayIndenter == i) { |
| return this; |
| } |
| DefaultPrettyPrinter pp = new DefaultPrettyPrinter(this); |
| pp._arrayIndenter = i; |
| return pp; |
| } |
| |
| /** |
| * @since 2.3 |
| */ |
| public DefaultPrettyPrinter withObjectIndenter(Indenter i) { |
| if (i == null) { |
| i = NopIndenter.instance; |
| } |
| if (_objectIndenter == i) { |
| return this; |
| } |
| DefaultPrettyPrinter pp = new DefaultPrettyPrinter(this); |
| pp._objectIndenter = i; |
| return pp; |
| } |
| |
| /** |
| * "Mutant factory" method that will return a pretty printer instance |
| * that does use spaces inside object entries; if 'this' instance already |
| * does this, it is returned; if not, a new instance will be constructed |
| * and returned. |
| * |
| * @since 2.3 |
| */ |
| public DefaultPrettyPrinter withSpacesInObjectEntries() { |
| return _withSpaces(true); |
| } |
| |
| /** |
| * "Mutant factory" method that will return a pretty printer instance |
| * that does not use spaces inside object entries; if 'this' instance already |
| * does this, it is returned; if not, a new instance will be constructed |
| * and returned. |
| * |
| * @since 2.3 |
| */ |
| public DefaultPrettyPrinter withoutSpacesInObjectEntries() { |
| return _withSpaces(false); |
| } |
| |
| protected DefaultPrettyPrinter _withSpaces(boolean state) |
| { |
| if (_spacesInObjectEntries == state) { |
| return this; |
| } |
| DefaultPrettyPrinter pp = new DefaultPrettyPrinter(this); |
| pp._spacesInObjectEntries = state; |
| return pp; |
| } |
| |
| /** |
| * @since 2.9 |
| */ |
| public DefaultPrettyPrinter withSeparators(Separators separators) { |
| _separators = separators; |
| _objectFieldValueSeparatorWithSpaces = " " + separators.getObjectFieldValueSeparator() + " "; |
| return this; |
| } |
| |
| /* |
| /********************************************************** |
| /* Instantiatable impl |
| /********************************************************** |
| */ |
| |
| @Override |
| public DefaultPrettyPrinter createInstance() { |
| return new DefaultPrettyPrinter(this); |
| } |
| |
| /* |
| /********************************************************** |
| /* PrettyPrinter impl |
| /********************************************************** |
| */ |
| |
| @Override |
| public void writeRootValueSeparator(JsonGenerator g) throws IOException |
| { |
| if (_rootSeparator != null) { |
| g.writeRaw(_rootSeparator); |
| } |
| } |
| |
| @Override |
| public void writeStartObject(JsonGenerator g) throws IOException |
| { |
| g.writeRaw('{'); |
| if (!_objectIndenter.isInline()) { |
| ++_nesting; |
| } |
| } |
| |
| @Override |
| public void beforeObjectEntries(JsonGenerator g) throws IOException |
| { |
| _objectIndenter.writeIndentation(g, _nesting); |
| } |
| |
| /** |
| * Method called after an object field has been output, but |
| * before the value is output. |
| *<p> |
| * Default handling (without pretty-printing) will output a single |
| * colon to separate the two. Pretty-printer is |
| * to output a colon as well, but can surround that with other |
| * (white-space) decoration. |
| */ |
| @Override |
| public void writeObjectFieldValueSeparator(JsonGenerator g) throws IOException |
| { |
| if (_spacesInObjectEntries) { |
| g.writeRaw(_objectFieldValueSeparatorWithSpaces); |
| } else { |
| g.writeRaw(_separators.getObjectFieldValueSeparator()); |
| } |
| } |
| |
| /** |
| * Method called after an object entry (field:value) has been completely |
| * output, and before another value is to be output. |
| *<p> |
| * Default handling (without pretty-printing) will output a single |
| * comma to separate the two. Pretty-printer is |
| * to output a comma as well, but can surround that with other |
| * (white-space) decoration. |
| */ |
| @Override |
| public void writeObjectEntrySeparator(JsonGenerator g) throws IOException |
| { |
| g.writeRaw(_separators.getObjectEntrySeparator()); |
| _objectIndenter.writeIndentation(g, _nesting); |
| } |
| |
| @Override |
| public void writeEndObject(JsonGenerator g, int nrOfEntries) throws IOException |
| { |
| if (!_objectIndenter.isInline()) { |
| --_nesting; |
| } |
| if (nrOfEntries > 0) { |
| _objectIndenter.writeIndentation(g, _nesting); |
| } else { |
| g.writeRaw(' '); |
| } |
| g.writeRaw('}'); |
| } |
| |
| @Override |
| public void writeStartArray(JsonGenerator g) throws IOException |
| { |
| if (!_arrayIndenter.isInline()) { |
| ++_nesting; |
| } |
| g.writeRaw('['); |
| } |
| |
| @Override |
| public void beforeArrayValues(JsonGenerator g) throws IOException { |
| _arrayIndenter.writeIndentation(g, _nesting); |
| } |
| |
| /** |
| * Method called after an array value has been completely |
| * output, and before another value is to be output. |
| *<p> |
| * Default handling (without pretty-printing) will output a single |
| * comma to separate the two. Pretty-printer is |
| * to output a comma as well, but can surround that with other |
| * (white-space) decoration. |
| */ |
| @Override |
| public void writeArrayValueSeparator(JsonGenerator g) throws IOException |
| { |
| g.writeRaw(_separators.getArrayValueSeparator()); |
| _arrayIndenter.writeIndentation(g, _nesting); |
| } |
| |
| @Override |
| public void writeEndArray(JsonGenerator g, int nrOfValues) throws IOException |
| { |
| if (!_arrayIndenter.isInline()) { |
| --_nesting; |
| } |
| if (nrOfValues > 0) { |
| _arrayIndenter.writeIndentation(g, _nesting); |
| } else { |
| g.writeRaw(' '); |
| } |
| g.writeRaw(']'); |
| } |
| |
| /* |
| /********************************************************** |
| /* Helper classes |
| /********************************************************** |
| */ |
| |
| /** |
| * Dummy implementation that adds no indentation whatsoever |
| */ |
| public static class NopIndenter |
| implements Indenter, java.io.Serializable |
| { |
| public static final NopIndenter instance = new NopIndenter(); |
| |
| @Override |
| public void writeIndentation(JsonGenerator g, int level) throws IOException { } |
| |
| @Override |
| public boolean isInline() { return true; } |
| } |
| |
| /** |
| * This is a very simple indenter that only adds a |
| * single space for indentation. It is used as the default |
| * indenter for array values. |
| */ |
| public static class FixedSpaceIndenter extends NopIndenter |
| { |
| public static final FixedSpaceIndenter instance = new FixedSpaceIndenter(); |
| |
| @Override |
| public void writeIndentation(JsonGenerator g, int level) throws IOException |
| { |
| g.writeRaw(' '); |
| } |
| |
| @Override |
| public boolean isInline() { return true; } |
| } |
| } |