diff --git a/src/main/java/com/fasterxml/jackson/core/JsonFactory.java b/src/main/java/com/fasterxml/jackson/core/JsonFactory.java
index bee48c17d6..b0608b98fa 100644
--- a/src/main/java/com/fasterxml/jackson/core/JsonFactory.java
+++ b/src/main/java/com/fasterxml/jackson/core/JsonFactory.java
@@ -282,6 +282,14 @@ public static int collectDefaults() {
*/
protected StreamReadConstraints _streamReadConstraints;
+ /**
+ * Write constraints to use for {@link JsonGenerator}s constructed using
+ * this factory.
+ *
+ * @since 2.16
+ */
+ protected StreamWriteConstraints _streamWriteConstraints;
+
/**
* Optional helper object that may decorate input sources, to do
* additional processing on input during parsing.
@@ -350,6 +358,7 @@ public JsonFactory(ObjectCodec oc) {
_objectCodec = oc;
_quoteChar = DEFAULT_QUOTE_CHAR;
_streamReadConstraints = StreamReadConstraints.defaults();
+ _streamWriteConstraints = StreamWriteConstraints.defaults();
_generatorDecorators = null;
}
@@ -374,6 +383,8 @@ protected JsonFactory(JsonFactory src, ObjectCodec codec)
_generatorDecorators = _copy(src._generatorDecorators);
_streamReadConstraints = src._streamReadConstraints == null ?
StreamReadConstraints.defaults() : src._streamReadConstraints;
+ _streamWriteConstraints = src._streamWriteConstraints == null ?
+ StreamWriteConstraints.defaults() : src._streamWriteConstraints;
// JSON-specific
_characterEscapes = src._characterEscapes;
@@ -401,6 +412,8 @@ public JsonFactory(JsonFactoryBuilder b) {
_generatorDecorators = _copy(b._generatorDecorators);
_streamReadConstraints = b._streamReadConstraints == null ?
StreamReadConstraints.defaults() : b._streamReadConstraints;
+ _streamWriteConstraints = b._streamWriteConstraints == null ?
+ StreamWriteConstraints.defaults() : b._streamWriteConstraints;
// JSON-specific
_characterEscapes = b._characterEscapes;
@@ -428,6 +441,8 @@ protected JsonFactory(TSFBuilder,?> b, boolean bogus) {
_generatorDecorators = _copy(b._generatorDecorators);
_streamReadConstraints = b._streamReadConstraints == null ?
StreamReadConstraints.defaults() : b._streamReadConstraints;
+ _streamWriteConstraints = b._streamWriteConstraints == null ?
+ StreamWriteConstraints.defaults() : b._streamWriteConstraints;
// JSON-specific: need to assign even if not really used
_characterEscapes = null;
@@ -802,6 +817,11 @@ public StreamReadConstraints streamReadConstraints() {
return _streamReadConstraints;
}
+ @Override
+ public StreamWriteConstraints streamWriteConstraints() {
+ return _streamWriteConstraints;
+ }
+
/**
* Method for overriding {@link StreamReadConstraints} defined for
* this factory.
@@ -822,6 +842,26 @@ public JsonFactory setStreamReadConstraints(StreamReadConstraints src) {
return this;
}
+ /**
+ * Method for overriding {@link StreamWriteConstraints} defined for
+ * this factory.
+ *
+ * NOTE: the preferred way to set constraints is by using
+ * {@link JsonFactoryBuilder#streamWriteConstraints}: this method is only
+ * provided to support older non-builder-based construction.
+ * In Jackson 3.x this method will not be available.
+ *
+ * @param swc Constraints
+ *
+ * @return This factory instance (to allow call chaining)
+ *
+ * @since 2.16
+ */
+ public JsonFactory setStreamWriteConstraints(StreamWriteConstraints swc) {
+ _streamWriteConstraints = Objects.requireNonNull(swc);
+ return this;
+ }
+
/*
/**********************************************************
/* Configuration, parser configuration
@@ -2076,7 +2116,8 @@ protected IOContext _createContext(ContentReference contentRef, boolean resource
if (contentRef == null) {
contentRef = ContentReference.unknown();
}
- return new IOContext(_streamReadConstraints, _getBufferRecycler(), contentRef, resourceManaged);
+ return new IOContext(_streamReadConstraints, _streamWriteConstraints,
+ _getBufferRecycler(), contentRef, resourceManaged);
}
/**
@@ -2091,7 +2132,8 @@ protected IOContext _createContext(ContentReference contentRef, boolean resource
*/
@Deprecated // @since 2.13
protected IOContext _createContext(Object rawContentRef, boolean resourceManaged) {
- return new IOContext(_streamReadConstraints, _getBufferRecycler(),
+ return new IOContext(_streamReadConstraints, _streamWriteConstraints,
+ _getBufferRecycler(),
_createContentReference(rawContentRef),
resourceManaged);
}
@@ -2109,7 +2151,8 @@ protected IOContext _createContext(Object rawContentRef, boolean resourceManaged
protected IOContext _createNonBlockingContext(Object srcRef) {
// [jackson-core#479]: allow recycling for non-blocking parser again
// now that access is thread-safe
- return new IOContext(_streamReadConstraints, _getBufferRecycler(),
+ return new IOContext(_streamReadConstraints, _streamWriteConstraints,
+ _getBufferRecycler(),
_createContentReference(srcRef),
false);
}
diff --git a/src/main/java/com/fasterxml/jackson/core/JsonGenerator.java b/src/main/java/com/fasterxml/jackson/core/JsonGenerator.java
index 8137453ffc..d524939aef 100644
--- a/src/main/java/com/fasterxml/jackson/core/JsonGenerator.java
+++ b/src/main/java/com/fasterxml/jackson/core/JsonGenerator.java
@@ -341,6 +341,15 @@ protected JsonGenerator() { }
*/
public abstract ObjectCodec getCodec();
+ /**
+ * Get the constraints to apply when performing streaming writes.
+ *
+ * @since 2.16
+ */
+ public StreamWriteConstraints streamWriteConstraints() {
+ return StreamWriteConstraints.defaults();
+ }
+
/**
* Accessor for finding out version of the bundle that provided this generator instance.
*
diff --git a/src/main/java/com/fasterxml/jackson/core/StreamWriteConstraints.java b/src/main/java/com/fasterxml/jackson/core/StreamWriteConstraints.java
new file mode 100644
index 0000000000..83ac7ca66f
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/core/StreamWriteConstraints.java
@@ -0,0 +1,157 @@
+package com.fasterxml.jackson.core;
+
+import com.fasterxml.jackson.core.exc.StreamConstraintsException;
+
+/**
+ * The constraints to use for streaming writes: used to guard against problematic
+ * output by preventing processing of "too big" output constructs (values,
+ * structures).
+ * Constraints are registered with {@code TokenStreamFactory} (such as
+ * {@code JsonFactory}); if nothing explicitly specified, default
+ * constraints are used.
+ *
+ * Currently constrained aspects, with default settings, are:
+ *
+ * - Maximum Nesting depth: default 1000 (see {@link #DEFAULT_MAX_DEPTH})
+ *
+ *
+ *
+ * @since 2.16
+ */
+public class StreamWriteConstraints
+ implements java.io.Serializable
+{
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Default setting for maximum depth: see {@link Builder#maxNestingDepth(int)} for details.
+ */
+ public static final int DEFAULT_MAX_DEPTH = 1000;
+
+ protected final int _maxNestingDepth;
+
+ private static final StreamWriteConstraints DEFAULT =
+ new StreamWriteConstraints(DEFAULT_MAX_DEPTH);
+
+ public static final class Builder {
+ private int maxNestingDepth;
+
+ /**
+ * Sets the maximum nesting depth. The depth is a count of objects and arrays that have not
+ * been closed, `{` and `[` respectively.
+ *
+ * @param maxNestingDepth the maximum depth
+ *
+ * @return this builder
+ * @throws IllegalArgumentException if the maxNestingDepth is set to a negative value
+ */
+ public Builder maxNestingDepth(final int maxNestingDepth) {
+ if (maxNestingDepth < 0) {
+ throw new IllegalArgumentException("Cannot set maxNestingDepth to a negative value");
+ }
+ this.maxNestingDepth = maxNestingDepth;
+ return this;
+ }
+
+ Builder() {
+ this(DEFAULT_MAX_DEPTH);
+ }
+
+ Builder(final int maxNestingDepth) {
+ this.maxNestingDepth = maxNestingDepth;
+ }
+
+ Builder(StreamWriteConstraints src) {
+ maxNestingDepth = src._maxNestingDepth;
+ }
+
+ public StreamWriteConstraints build() {
+ return new StreamWriteConstraints(maxNestingDepth);
+ }
+ }
+
+ /*
+ /**********************************************************************
+ /* Life-cycle
+ /**********************************************************************
+ */
+
+ protected StreamWriteConstraints(final int maxNestingDepth) {
+ _maxNestingDepth = maxNestingDepth;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static StreamWriteConstraints defaults() {
+ return DEFAULT;
+ }
+
+ /**
+ * @return New {@link Builder} initialized with settings of this constraints
+ * instance
+ */
+ public Builder rebuild() {
+ return new Builder(this);
+ }
+
+ /*
+ /**********************************************************************
+ /* Accessors
+ /**********************************************************************
+ */
+
+ /**
+ * Accessor for maximum depth.
+ * see {@link Builder#maxNestingDepth(int)} for details.
+ *
+ * @return Maximum allowed depth
+ */
+ public int getMaxNestingDepth() {
+ return _maxNestingDepth;
+ }
+
+ /*
+ /**********************************************************************
+ /* Convenience methods for validation, document limits
+ /**********************************************************************
+ */
+
+ /**
+ * Convenience method that can be used to verify that the
+ * nesting depth does not exceed the maximum specified by this
+ * constraints object: if it does, a
+ * {@link StreamConstraintsException}
+ * is thrown.
+ *
+ * @param depth count of unclosed objects and arrays
+ *
+ * @throws StreamConstraintsException If depth exceeds maximum
+ */
+ public void validateNestingDepth(int depth) throws StreamConstraintsException
+ {
+ if (depth > _maxNestingDepth) {
+ throw _constructException(
+ "Document nesting depth (%d) exceeds the maximum allowed (%d, from %s)",
+ depth, _maxNestingDepth,
+ _constrainRef("getMaxNestingDepth"));
+ }
+ }
+
+ /*
+ /**********************************************************************
+ /* Error reporting
+ /**********************************************************************
+ */
+
+ // @since 2.16
+ protected StreamConstraintsException _constructException(String msgTemplate, Object... args) throws StreamConstraintsException {
+ throw new StreamConstraintsException(String.format(msgTemplate, args));
+ }
+
+ // @since 2.16
+ protected String _constrainRef(String method) {
+ return "`StreamWriteConstraints."+method+"()`";
+ }
+}
diff --git a/src/main/java/com/fasterxml/jackson/core/TSFBuilder.java b/src/main/java/com/fasterxml/jackson/core/TSFBuilder.java
index f85308a848..fe0965f93c 100644
--- a/src/main/java/com/fasterxml/jackson/core/TSFBuilder.java
+++ b/src/main/java/com/fasterxml/jackson/core/TSFBuilder.java
@@ -82,12 +82,19 @@ public abstract class TSFBuilderStreamWriteConstraints
*/
public IOContext(StreamReadConstraints src, BufferRecycler br,
ContentReference contentRef, boolean managedResource)
{
_streamReadConstraints = (src == null) ?
StreamReadConstraints.defaults() : src;
+ _streamWriteConstraints = StreamWriteConstraints.defaults();
_bufferRecycler = br;
_contentReference = contentRef;
_sourceRef = contentRef.getRawContent();
@@ -141,7 +168,7 @@ public IOContext(StreamReadConstraints src, BufferRecycler br,
@Deprecated // since 2.15
public IOContext(BufferRecycler br, ContentReference contentRef, boolean managedResource)
{
- this(null, br, contentRef, managedResource);
+ this(null, null, br, contentRef, managedResource);
}
@Deprecated // since 2.13
@@ -157,6 +184,14 @@ public StreamReadConstraints streamReadConstraints() {
return _streamReadConstraints;
}
+ /**
+ * @return constraints for streaming writes
+ * @since 2.16
+ */
+ public StreamWriteConstraints streamWriteConstraints() {
+ return _streamWriteConstraints;
+ }
+
public void setEncoding(JsonEncoding enc) {
_encoding = enc;
}
diff --git a/src/main/java/com/fasterxml/jackson/core/json/JsonGeneratorImpl.java b/src/main/java/com/fasterxml/jackson/core/json/JsonGeneratorImpl.java
index 807a92fda8..da3c2de251 100644
--- a/src/main/java/com/fasterxml/jackson/core/json/JsonGeneratorImpl.java
+++ b/src/main/java/com/fasterxml/jackson/core/json/JsonGeneratorImpl.java
@@ -139,6 +139,17 @@ public Version version() {
return VersionUtil.versionFor(getClass());
}
+ /*
+ /**********************************************************************
+ /* Constraints violation checking (2.16)
+ /**********************************************************************
+ */
+
+ @Override
+ public StreamWriteConstraints streamWriteConstraints() {
+ return _ioContext.streamWriteConstraints();
+ }
+
/*
/**********************************************************
/* Overridden configuration methods
diff --git a/src/main/java/com/fasterxml/jackson/core/json/JsonWriteContext.java b/src/main/java/com/fasterxml/jackson/core/json/JsonWriteContext.java
index 87b1ef4ad0..12103e1cc1 100644
--- a/src/main/java/com/fasterxml/jackson/core/json/JsonWriteContext.java
+++ b/src/main/java/com/fasterxml/jackson/core/json/JsonWriteContext.java
@@ -69,6 +69,7 @@ protected JsonWriteContext(int type, JsonWriteContext parent, DupDetector dups)
super();
_type = type;
_parent = parent;
+ _nestingDepth = parent == null ? 0 : parent._nestingDepth + 1;
_dups = dups;
_index = -1;
}
@@ -79,6 +80,7 @@ protected JsonWriteContext(int type, JsonWriteContext parent, DupDetector dups,
super();
_type = type;
_parent = parent;
+ _nestingDepth = parent == null ? 0 : parent._nestingDepth + 1;
_dups = dups;
_index = -1;
_currentValue = currValue;
diff --git a/src/main/java/com/fasterxml/jackson/core/json/UTF8JsonGenerator.java b/src/main/java/com/fasterxml/jackson/core/json/UTF8JsonGenerator.java
index 3966d52f82..553fb7be93 100644
--- a/src/main/java/com/fasterxml/jackson/core/json/UTF8JsonGenerator.java
+++ b/src/main/java/com/fasterxml/jackson/core/json/UTF8JsonGenerator.java
@@ -312,6 +312,7 @@ public final void writeStartArray() throws IOException
{
_verifyValueWrite("start an array");
_writeContext = _writeContext.createChildArrayContext();
+ streamWriteConstraints().validateNestingDepth(_writeContext.getNestingDepth());
if (_cfgPrettyPrinter != null) {
_cfgPrettyPrinter.writeStartArray(this);
} else {
@@ -327,6 +328,7 @@ public final void writeStartArray(Object currentValue) throws IOException
{
_verifyValueWrite("start an array");
_writeContext = _writeContext.createChildArrayContext(currentValue);
+ streamWriteConstraints().validateNestingDepth(_writeContext.getNestingDepth());
if (_cfgPrettyPrinter != null) {
_cfgPrettyPrinter.writeStartArray(this);
} else {
@@ -342,6 +344,7 @@ public void writeStartArray(Object currentValue, int size) throws IOException
{
_verifyValueWrite("start an array");
_writeContext = _writeContext.createChildArrayContext(currentValue);
+ streamWriteConstraints().validateNestingDepth(_writeContext.getNestingDepth());
if (_cfgPrettyPrinter != null) {
_cfgPrettyPrinter.writeStartArray(this);
} else {
@@ -374,6 +377,7 @@ public final void writeStartObject() throws IOException
{
_verifyValueWrite("start an object");
_writeContext = _writeContext.createChildObjectContext();
+ streamWriteConstraints().validateNestingDepth(_writeContext.getNestingDepth());
if (_cfgPrettyPrinter != null) {
_cfgPrettyPrinter.writeStartObject(this);
} else {
@@ -389,6 +393,7 @@ public void writeStartObject(Object forValue) throws IOException
{
_verifyValueWrite("start an object");
JsonWriteContext ctxt = _writeContext.createChildObjectContext(forValue);
+ streamWriteConstraints().validateNestingDepth(ctxt.getNestingDepth());
_writeContext = ctxt;
if (_cfgPrettyPrinter != null) {
_cfgPrettyPrinter.writeStartObject(this);
diff --git a/src/main/java/com/fasterxml/jackson/core/json/WriterBasedJsonGenerator.java b/src/main/java/com/fasterxml/jackson/core/json/WriterBasedJsonGenerator.java
index 01ccf3bfca..b1628c92b3 100644
--- a/src/main/java/com/fasterxml/jackson/core/json/WriterBasedJsonGenerator.java
+++ b/src/main/java/com/fasterxml/jackson/core/json/WriterBasedJsonGenerator.java
@@ -251,6 +251,7 @@ public void writeStartArray() throws IOException
{
_verifyValueWrite("start an array");
_writeContext = _writeContext.createChildArrayContext();
+ streamWriteConstraints().validateNestingDepth(_writeContext.getNestingDepth());
if (_cfgPrettyPrinter != null) {
_cfgPrettyPrinter.writeStartArray(this);
} else {
@@ -266,6 +267,7 @@ public void writeStartArray(Object currentValue) throws IOException
{
_verifyValueWrite("start an array");
_writeContext = _writeContext.createChildArrayContext(currentValue);
+ streamWriteConstraints().validateNestingDepth(_writeContext.getNestingDepth());
if (_cfgPrettyPrinter != null) {
_cfgPrettyPrinter.writeStartArray(this);
} else {
@@ -281,6 +283,7 @@ public void writeStartArray(Object currentValue, int size) throws IOException
{
_verifyValueWrite("start an array");
_writeContext = _writeContext.createChildArrayContext(currentValue);
+ streamWriteConstraints().validateNestingDepth(_writeContext.getNestingDepth());
if (_cfgPrettyPrinter != null) {
_cfgPrettyPrinter.writeStartArray(this);
} else {
@@ -313,6 +316,7 @@ public void writeStartObject() throws IOException
{
_verifyValueWrite("start an object");
_writeContext = _writeContext.createChildObjectContext();
+ streamWriteConstraints().validateNestingDepth(_writeContext.getNestingDepth());
if (_cfgPrettyPrinter != null) {
_cfgPrettyPrinter.writeStartObject(this);
} else {
@@ -328,6 +332,7 @@ public void writeStartObject(Object forValue) throws IOException
{
_verifyValueWrite("start an object");
JsonWriteContext ctxt = _writeContext.createChildObjectContext(forValue);
+ streamWriteConstraints().validateNestingDepth(_writeContext.getNestingDepth());
_writeContext = ctxt;
if (_cfgPrettyPrinter != null) {
_cfgPrettyPrinter.writeStartObject(this);
diff --git a/src/main/java/com/fasterxml/jackson/core/util/JsonGeneratorDelegate.java b/src/main/java/com/fasterxml/jackson/core/util/JsonGeneratorDelegate.java
index 85c8a0e519..5879063d62 100644
--- a/src/main/java/com/fasterxml/jackson/core/util/JsonGeneratorDelegate.java
+++ b/src/main/java/com/fasterxml/jackson/core/util/JsonGeneratorDelegate.java
@@ -186,6 +186,17 @@ public JsonGenerator setPrettyPrinter(PrettyPrinter pp) {
public JsonGenerator setRootValueSeparator(SerializableString sep) { delegate.setRootValueSeparator(sep);
return this; }
+ /*
+ /**********************************************************************
+ /* Constraints violation checking (2.16)
+ /**********************************************************************
+ */
+
+ @Override
+ public StreamWriteConstraints streamWriteConstraints() {
+ return delegate.streamWriteConstraints();
+ }
+
/*
/**********************************************************************
/* Public API, write methods, structural
diff --git a/src/test/java/com/fasterxml/jackson/core/write/UTF8GeneratorTest.java b/src/test/java/com/fasterxml/jackson/core/write/UTF8GeneratorTest.java
index 469fe58325..1e83778040 100644
--- a/src/test/java/com/fasterxml/jackson/core/write/UTF8GeneratorTest.java
+++ b/src/test/java/com/fasterxml/jackson/core/write/UTF8GeneratorTest.java
@@ -3,6 +3,7 @@
import java.io.*;
import com.fasterxml.jackson.core.*;
+import com.fasterxml.jackson.core.exc.StreamConstraintsException;
import com.fasterxml.jackson.core.filter.FilteringGeneratorDelegate;
import com.fasterxml.jackson.core.filter.JsonPointerBasedFilter;
import com.fasterxml.jackson.core.filter.TokenFilter.Inclusion;
@@ -18,8 +19,7 @@ public class UTF8GeneratorTest extends BaseTest
public void testUtf8Issue462() throws Exception
{
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- IOContext ioc = new IOContext(StreamReadConstraints.defaults(),
- new BufferRecycler(),
+ IOContext ioc = new IOContext(new BufferRecycler(),
ContentReference.rawReference(bytes), true);
JsonGenerator gen = new UTF8JsonGenerator(ioc, 0, null, bytes, '"');
String str = "Natuurlijk is alles gelukt en weer een tevreden klant\uD83D\uDE04";
@@ -44,6 +44,43 @@ public void testUtf8Issue462() throws Exception
p.close();
}
+ public void testNestingDepthWithSmallLimit() throws Exception
+ {
+ ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+ IOContext ioc = new IOContext(null,
+ StreamWriteConstraints.builder().maxNestingDepth(1).build(),
+ new BufferRecycler(),
+ ContentReference.rawReference(bytes), true);
+ try (JsonGenerator gen = new UTF8JsonGenerator(ioc, 0, null, bytes, '"')) {
+ gen.writeStartObject();
+ gen.writeFieldName("array");
+ gen.writeStartArray();
+ fail("expected StreamConstraintsException");
+ } catch (StreamConstraintsException sce) {
+ String expected = "Document nesting depth (2) exceeds the maximum allowed (1, from `StreamWriteConstraints.getMaxNestingDepth()`)";
+ assertEquals(expected, sce.getMessage());
+ }
+ }
+
+ public void testNestingDepthWithSmallLimitNestedObject() throws Exception
+ {
+ ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+ IOContext ioc = new IOContext(null,
+ StreamWriteConstraints.builder().maxNestingDepth(1).build(),
+ new BufferRecycler(),
+ ContentReference.rawReference(bytes), true);
+ try (JsonGenerator gen = new UTF8JsonGenerator(ioc, 0, null, bytes, '"')) {
+ gen.writeStartObject();
+ gen.writeFieldName("object");
+ gen.writeStartObject();
+ fail("expected StreamConstraintsException");
+ } catch (StreamConstraintsException sce) {
+ String expected = "Document nesting depth (2) exceeds the maximum allowed (1, from `StreamWriteConstraints.getMaxNestingDepth()`)";
+ assertEquals(expected, sce.getMessage());
+ }
+ }
+
+
// for [core#115]
public void testSurrogatesWithRaw() throws Exception
{
diff --git a/src/test/java/com/fasterxml/jackson/core/write/WriterBasedJsonGeneratorTest.java b/src/test/java/com/fasterxml/jackson/core/write/WriterBasedJsonGeneratorTest.java
new file mode 100644
index 0000000000..3f4eb63ec1
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/core/write/WriterBasedJsonGeneratorTest.java
@@ -0,0 +1,55 @@
+package com.fasterxml.jackson.core.write;
+
+import com.fasterxml.jackson.core.BaseTest;
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.StreamWriteConstraints;
+import com.fasterxml.jackson.core.exc.StreamConstraintsException;
+import com.fasterxml.jackson.core.io.ContentReference;
+import com.fasterxml.jackson.core.io.IOContext;
+import com.fasterxml.jackson.core.json.WriterBasedJsonGenerator;
+import com.fasterxml.jackson.core.util.BufferRecycler;
+
+import java.io.StringWriter;
+
+public class WriterBasedJsonGeneratorTest extends BaseTest
+{
+ private final JsonFactory JSON_F = new JsonFactory();
+
+ public void testNestingDepthWithSmallLimit() throws Exception
+ {
+ StringWriter sw = new StringWriter();
+ IOContext ioc = new IOContext(null,
+ StreamWriteConstraints.builder().maxNestingDepth(1).build(),
+ new BufferRecycler(),
+ ContentReference.rawReference(sw), true);
+ try (JsonGenerator gen = new WriterBasedJsonGenerator(ioc, 0, null, sw, '"')) {
+ gen.writeStartObject();
+ gen.writeFieldName("array");
+ gen.writeStartArray();
+ fail("expected StreamConstraintsException");
+ } catch (StreamConstraintsException sce) {
+ String expected = "Document nesting depth (2) exceeds the maximum allowed (1, from `StreamWriteConstraints.getMaxNestingDepth()`)";
+ assertEquals(expected, sce.getMessage());
+ }
+ }
+
+ public void testNestingDepthWithSmallLimitNestedObject() throws Exception
+ {
+ StringWriter sw = new StringWriter();
+ IOContext ioc = new IOContext(null,
+ StreamWriteConstraints.builder().maxNestingDepth(1).build(),
+ new BufferRecycler(),
+ ContentReference.rawReference(sw), true);
+ try (JsonGenerator gen = new WriterBasedJsonGenerator(ioc, 0, null, sw, '"')) {
+ gen.writeStartObject();
+ gen.writeFieldName("object");
+ gen.writeStartObject();
+ fail("expected StreamConstraintsException");
+ } catch (StreamConstraintsException sce) {
+ String expected = "Document nesting depth (2) exceeds the maximum allowed (1, from `StreamWriteConstraints.getMaxNestingDepth()`)";
+ assertEquals(expected, sce.getMessage());
+ }
+ }
+
+}