Skip to content
This repository was archived by the owner on Dec 19, 2024. It is now read-only.

Commit 773c778

Browse files
committed
Add new feature LITERAL_BLOCK_STYLE
If enabled will use a literal block style for string containing newlines. All other quotes are unaffected. This make sense in addition to MINIMIZE_QUOTES and ALWAYS_QUOTE_NUMBER_AS_STRINGS as e.g this is safer for string values like "true" (which when quotes are stripped mutate from a string type to a boolean type). It is false by default.
1 parent 29702cc commit 773c778

File tree

2 files changed

+84
-48
lines changed

2 files changed

+84
-48
lines changed

src/main/java/com/fasterxml/jackson/dataformat/yaml/YAMLGenerator.java

Lines changed: 46 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public enum Feature // implements FormatFeature // for 2.7
2828
/**
2929
* Whether we are to write an explicit document start marker ("---")
3030
* or not.
31-
*
31+
*
3232
* @since 2.3
3333
*/
3434
WRITE_DOC_START_MARKER(true),
@@ -38,17 +38,17 @@ public enum Feature // implements FormatFeature // for 2.7
3838
* or "generic" Object Id mechanism (false). Former works better for systems that
3939
* are YAML-centric; latter may be better choice for interoperability, when
4040
* converting between formats or accepting other formats.
41-
*
41+
*
4242
* @since 2.5
4343
*/
4444
USE_NATIVE_OBJECT_ID(true),
45-
45+
4646
/**
4747
* Whether to use YAML native Type Id construct for indicating type (true);
4848
* or "generic" type property (false). Former works better for systems that
4949
* are YAML-centric; latter may be better choice for interoperability, when
5050
* converting between formats or accepting other formats.
51-
*
51+
*
5252
* @since 2.5
5353
*/
5454
USE_NATIVE_TYPE_ID(true),
@@ -80,7 +80,7 @@ public enum Feature // implements FormatFeature // for 2.7
8080
* @since 2.7
8181
*/
8282
MINIMIZE_QUOTES(false),
83-
83+
8484
/**
8585
* Whether numbers stored as strings will be rendered with quotes (true) or
8686
* without quotes (false, default) when MINIMIZE_QUOTES is enabled.
@@ -91,12 +91,21 @@ public enum Feature // implements FormatFeature // for 2.7
9191
*
9292
* @since 2.8.2
9393
*/
94-
ALWAYS_QUOTE_NUMBERS_AS_STRINGS(false)
94+
ALWAYS_QUOTE_NUMBERS_AS_STRINGS(false),
95+
96+
/**
97+
* Whether for string containing newlines a <a href="http://www.yaml.org/spec/1.2/spec.html#style/block/literal">literal block style</a>
98+
* should be used. This automatically enabled when {@link #MINIMIZE_QUOTES} is set.
99+
* <p>
100+
* The content of such strinfs is limited to printable characters according to the rules of
101+
* <a href="http://www.yaml.org/spec/1.2/spec.html#style/block/literal">literal block style</a>.
102+
*/
103+
LITERAL_BLOCK_STYLE(false)
95104
;
96105

97106
protected final boolean _defaultState;
98107
protected final int _mask;
99-
108+
100109
/**
101110
* Method that calculates bit set (flags) of all features that
102111
* are enabled by default.
@@ -111,14 +120,14 @@ public static int collectDefaults()
111120
}
112121
return flags;
113122
}
114-
123+
115124
private Feature(boolean defaultState) {
116125
_defaultState = defaultState;
117126
_mask = (1 << ordinal());
118127
}
119-
128+
120129
public boolean enabledByDefault() { return _defaultState; }
121-
public boolean enabledIn(int flags) { return (flags & _mask) != 0; }
130+
public boolean enabledIn(int flags) { return (flags & _mask) != 0; }
122131
public int getMask() { return _mask; }
123132
}
124133

@@ -127,7 +136,7 @@ private Feature(boolean defaultState) {
127136
/* Internal constants
128137
/**********************************************************
129138
*/
130-
139+
131140
protected final static long MIN_INT_AS_LONG = (long) Integer.MIN_VALUE;
132141
protected final static long MAX_INT_AS_LONG = (long) Integer.MAX_VALUE;
133142
protected final static Pattern PLAIN_NUMBER_P = Pattern.compile("[0-9]*(\\.[0-9]*)?");
@@ -153,7 +162,7 @@ private Feature(boolean defaultState) {
153162

154163
// for field names, leave out quotes
155164
private final static Character STYLE_NAME = null;
156-
165+
157166
// numbers, booleans, should use implicit
158167
private final static Character STYLE_SCALAR = null;
159168
// Strings quoted for fun
@@ -185,7 +194,7 @@ private Feature(boolean defaultState) {
185194
* need to output one.
186195
*/
187196
protected String _typeId;
188-
197+
189198
/*
190199
/**********************************************************
191200
/* Life-cycle
@@ -203,14 +212,14 @@ public YAMLGenerator(IOContext ctxt, int jsonFeatures, int yamlFeatures,
203212
_writer = out;
204213

205214
_outputOptions = buildDumperOptions(jsonFeatures, yamlFeatures, version);
206-
215+
207216
_emitter = new Emitter(_writer, _outputOptions);
208217
// should we start output now, or try to defer?
209218
_emitter.emit(new StreamStartEvent(null, null));
210219
Map<String,String> noTags = Collections.emptyMap();
211-
220+
212221
boolean startMarker = Feature.WRITE_DOC_START_MARKER.enabledIn(yamlFeatures);
213-
222+
214223
_emitter.emit(new DocumentStartEvent(null, null, startMarker,
215224
version, // for 1.10 was: ((version == null) ? null : version.getArray()),
216225
noTags));
@@ -232,10 +241,10 @@ protected DumperOptions buildDumperOptions(int jsonFeatures, int yamlFeatures, o
232241
return opt;
233242
}
234243

235-
/*
236-
/**********************************************************
237-
/* Versioned
238-
/**********************************************************
244+
/*
245+
/**********************************************************
246+
/* Versioned
247+
/**********************************************************
239248
*/
240249

241250
@Override
@@ -291,7 +300,7 @@ public JsonGenerator overrideFormatFeatures(int values, int mask) {
291300
_formatFeatures = (_formatFeatures & ~mask) | (values & mask);
292301
return this;
293302
}
294-
303+
295304
@Override
296305
public boolean canUseSchema(FormatSchema schema) {
297306
return false;
@@ -330,13 +339,13 @@ public YAMLGenerator configure(Feature f, boolean state) {
330339
}
331340
return this;
332341
}
333-
342+
334343
/*
335344
/**********************************************************************
336345
/* Overridden methods; writing field names
337346
/**********************************************************************
338347
*/
339-
348+
340349
/* And then methods overridden to make final, streamline some
341350
* aspects...
342351
*/
@@ -389,7 +398,7 @@ public final void flush() throws IOException
389398
{
390399
_writer.flush();
391400
}
392-
401+
393402
@Override
394403
public void close() throws IOException
395404
{
@@ -406,7 +415,7 @@ public void close() throws IOException
406415
/* Public API: structural output
407416
/**********************************************************
408417
*/
409-
418+
410419
@Override
411420
public final void writeStartArray() throws IOException
412421
{
@@ -422,15 +431,15 @@ public final void writeStartArray() throws IOException
422431
_emitter.emit(new SequenceStartEvent(anchor, yamlTag,
423432
implicit, null, null, style));
424433
}
425-
434+
426435
@Override
427436
public final void writeEndArray() throws IOException
428437
{
429438
if (!_writeContext.inArray()) {
430439
_reportError("Current context not Array but "+_writeContext.typeDesc());
431440
}
432441
// just to make sure we don't "leak" type ids
433-
_typeId = null;
442+
_typeId = null;
434443
_writeContext = _writeContext.getParent();
435444
_emitter.emit(new SequenceEndEvent(null, null));
436445
}
@@ -458,7 +467,7 @@ public final void writeEndObject() throws IOException
458467
_reportError("Current context not Object but "+_writeContext.typeDesc());
459468
}
460469
// just to make sure we don't "leak" type ids
461-
_typeId = null;
470+
_typeId = null;
462471
_writeContext = _writeContext.getParent();
463472
_emitter.emit(new MappingEndEvent(null, null));
464473
}
@@ -488,6 +497,8 @@ public void writeString(String text) throws IOException,JsonGenerationException
488497
} else {
489498
style = STYLE_PLAIN;
490499
}
500+
} else if (Feature.LITERAL_BLOCK_STYLE.enabledIn(_formatFeatures) && text.indexOf('\n') >= 0) {
501+
style = STYLE_LITERAL;
491502
}
492503
_writeScalar(text, "string", style);
493504
}
@@ -565,7 +576,7 @@ public void writeRawValue(char[] text, int offset, int len) throws IOException {
565576
/* Output method implementations, base64-encoded binary
566577
/**********************************************************
567578
*/
568-
579+
569580
@Override
570581
public void writeBinary(Base64Variant b64variant, byte[] data, int offset, int len) throws IOException
571582
{
@@ -624,13 +635,13 @@ public void writeNumber(BigInteger v) throws IOException
624635
_verifyValueWrite("write number");
625636
_writeScalar(String.valueOf(v.toString()), "java.math.BigInteger", STYLE_SCALAR);
626637
}
627-
638+
628639
@Override
629640
public void writeNumber(double d) throws IOException
630641
{
631642
_verifyValueWrite("write number");
632643
_writeScalar(String.valueOf(d), "double", STYLE_SCALAR);
633-
}
644+
}
634645

635646
@Override
636647
public void writeNumber(float f) throws IOException
@@ -681,14 +692,14 @@ public boolean canWriteObjectId() {
681692
// yes, YAML does support Native Type Ids!
682693
// 10-Sep-2014, tatu: Except as per [#23] might not want to...
683694
return Feature.USE_NATIVE_OBJECT_ID.enabledIn(_formatFeatures);
684-
}
695+
}
685696

686697
@Override
687698
public boolean canWriteTypeId() {
688699
// yes, YAML does support Native Type Ids!
689700
// 10-Sep-2014, tatu: Except as per [#22] might not want to...
690701
return Feature.USE_NATIVE_TYPE_ID.enabledIn(_formatFeatures);
691-
}
702+
}
692703

693704
@Override
694705
public void writeTypeId(Object id)
@@ -706,7 +717,7 @@ public void writeObjectRef(Object id)
706717
AliasEvent evt = new AliasEvent(String.valueOf(id), null, null);
707718
_emitter.emit(evt);
708719
}
709-
720+
710721
@Override
711722
public void writeObjectId(Object id)
712723
throws IOException
@@ -749,7 +760,7 @@ protected void _writeScalar(String value, String type, Character style) throws I
749760
{
750761
_emitter.emit(_scalarEvent(value, style));
751762
}
752-
763+
753764
protected ScalarEvent _scalarEvent(String value, Character style)
754765
{
755766
String yamlTag = _typeId;

0 commit comments

Comments
 (0)