Fix #246
diff --git a/release-notes/VERSION b/release-notes/VERSION
index 994cc2e..b83ff4a 100644
--- a/release-notes/VERSION
+++ b/release-notes/VERSION
@@ -14,6 +14,11 @@
=== Releases ===
------------------------------------------------------------------------
+2.7.2 (not yet released)
+
+#246: Fix UTF8JsonGenerator to allow QUOTE_FIELD_NAMES to be toggled
+ (suggested by philipa@github)
+
2.7.1 (02-Feb-2016)
No changes since 2.7.0.
diff --git a/src/main/java/com/fasterxml/jackson/core/base/GeneratorBase.java b/src/main/java/com/fasterxml/jackson/core/base/GeneratorBase.java
index 38302b5..c99832b 100644
--- a/src/main/java/com/fasterxml/jackson/core/base/GeneratorBase.java
+++ b/src/main/java/com/fasterxml/jackson/core/base/GeneratorBase.java
@@ -26,7 +26,8 @@
*
* @since 2.5
*/
- protected final static int DERIVED_FEATURES_MASK = Feature.WRITE_NUMBERS_AS_STRINGS.getMask()
+ protected final static int DERIVED_FEATURES_MASK =
+ Feature.WRITE_NUMBERS_AS_STRINGS.getMask()
| Feature.ESCAPE_NON_ASCII.getMask()
| Feature.STRICT_DUPLICATE_DETECTION.getMask()
;
@@ -61,7 +62,7 @@
* {@link com.fasterxml.jackson.core.JsonGenerator.Feature#WRITE_NUMBERS_AS_STRINGS}).
*/
protected boolean _cfgNumbersAsStrings;
-
+
/*
/**********************************************************
/* State
@@ -136,12 +137,13 @@
@Override public int getFeatureMask() { return _features; }
//public JsonGenerator configure(Feature f, boolean state) { }
-
+
@Override
public JsonGenerator enable(Feature f) {
final int mask = f.getMask();
_features |= mask;
if ((mask & DERIVED_FEATURES_MASK) != 0) {
+ // why not switch? Requires addition of a generated class, alas
if (f == Feature.WRITE_NUMBERS_AS_STRINGS) {
_cfgNumbersAsStrings = true;
} else if (f == Feature.ESCAPE_NON_ASCII) {
@@ -226,7 +228,7 @@
}
}
}
-
+
@Override public JsonGenerator useDefaultPrettyPrinter() {
// Should not override a pretty printer if one already assigned.
if (getPrettyPrinter() != null) {
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 c09d2cf..1270eae 100644
--- a/src/main/java/com/fasterxml/jackson/core/json/JsonGeneratorImpl.java
+++ b/src/main/java/com/fasterxml/jackson/core/json/JsonGeneratorImpl.java
@@ -84,6 +84,14 @@
protected SerializableString _rootValueSeparator
= DefaultPrettyPrinter.DEFAULT_ROOT_VALUE_SEPARATOR;
+ /**
+ * Flag that is set if quoting is not to be added around
+ * JSON Object property names.
+ *
+ * @since 2.7
+ */
+ protected boolean _cfgUnqNames;
+
/*
/**********************************************************
/* Life-cycle
@@ -94,10 +102,11 @@
{
super(features, codec);
_ioContext = ctxt;
- if (isEnabled(Feature.ESCAPE_NON_ASCII)) {
+ if (Feature.ESCAPE_NON_ASCII.enabledIn(features)) {
// inlined `setHighestNonEscapedChar()`
_maximumNonEscapedChar = 127;
}
+ _cfgUnqNames = !Feature.QUOTE_FIELD_NAMES.enabledIn(features);
}
/*
@@ -107,6 +116,30 @@
*/
@Override
+ public JsonGenerator enable(Feature f) {
+ super.enable(f);
+ if (f == Feature.QUOTE_FIELD_NAMES) {
+ _cfgUnqNames = false;
+ }
+ return this;
+ }
+
+ @Override
+ public JsonGenerator disable(Feature f) {
+ super.disable(f);
+ if (f == Feature.QUOTE_FIELD_NAMES) {
+ _cfgUnqNames = true;
+ }
+ return this;
+ }
+
+ @Override
+ protected void _checkStdFeatureChanges(int newFeatureFlags, int changedFeatures) {
+ super._checkStdFeatureChanges(newFeatureFlags, changedFeatures);
+ _cfgUnqNames = !Feature.QUOTE_FIELD_NAMES.enabledIn(newFeatureFlags);
+ }
+
+ @Override
public JsonGenerator setHighestNonEscapedChar(int charCode) {
_maximumNonEscapedChar = (charCode < 0) ? 0 : charCode;
return this;
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 90079f1..8f17ea3 100644
--- a/src/main/java/com/fasterxml/jackson/core/json/UTF8JsonGenerator.java
+++ b/src/main/java/com/fasterxml/jackson/core/json/UTF8JsonGenerator.java
@@ -93,18 +93,6 @@
/*
/**********************************************************
- /* Quick flags
- /**********************************************************
- */
-
- /**
- * Flag that is set if quoting is not to be added around
- * JSON Object property names.
- */
- protected boolean _cfgUnqNames;
-
- /*
- /**********************************************************
/* Life-cycle
/**********************************************************
*/
@@ -130,7 +118,6 @@
if (isEnabled(Feature.ESCAPE_NON_ASCII)) {
setHighestNonEscapedChar(127);
}
- _cfgUnqNames = !Feature.QUOTE_FIELD_NAMES.enabledIn(features);
}
public UTF8JsonGenerator(IOContext ctxt, int features, ObjectCodec codec,
@@ -148,7 +135,6 @@
_outputMaxContiguous = (_outputEnd >> 3);
_charBuffer = ctxt.allocConcatBuffer();
_charBufferLength = _charBuffer.length;
- _cfgUnqNames = !Feature.QUOTE_FIELD_NAMES.enabledIn(features);
}
/*
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 af871ce..316886b 100644
--- a/src/main/java/com/fasterxml/jackson/core/json/WriterBasedJsonGenerator.java
+++ b/src/main/java/com/fasterxml/jackson/core/json/WriterBasedJsonGenerator.java
@@ -136,7 +136,7 @@
_outputBuffer[_outputTail++] = ',';
}
// Alternate mode, in which quoting of field names disabled?
- if (!isEnabled(Feature.QUOTE_FIELD_NAMES)) {
+ if (_cfgUnqNames) {
_writeString(name);
return;
}
@@ -166,7 +166,7 @@
}
// Alternate mode, in which quoting of field names disabled?
final char[] quoted = name.asQuotedChars();
- if (!isEnabled(Feature.QUOTE_FIELD_NAMES)) {
+ if (_cfgUnqNames) {
writeRaw(quoted, 0, quoted.length);
return;
}
@@ -270,7 +270,9 @@
_cfgPrettyPrinter.beforeObjectEntries(this);
}
- if (isEnabled(Feature.QUOTE_FIELD_NAMES)) { // standard
+ if (_cfgUnqNames) {// non-standard, omit quotes
+ _writeString(name);
+ } else {
if (_outputTail >= _outputEnd) {
_flushBuffer();
}
@@ -280,8 +282,6 @@
_flushBuffer();
}
_outputBuffer[_outputTail++] = '"';
- } else { // non-standard, omit quotes
- _writeString(name);
}
}
@@ -294,7 +294,9 @@
}
final char[] quoted = name.asQuotedChars();
- if (isEnabled(Feature.QUOTE_FIELD_NAMES)) { // standard
+ if (_cfgUnqNames) {// non-standard, omit quotes
+ writeRaw(quoted, 0, quoted.length);
+ } else {
if (_outputTail >= _outputEnd) {
_flushBuffer();
}
@@ -304,8 +306,6 @@
_flushBuffer();
}
_outputBuffer[_outputTail++] = '"';
- } else { // non-standard, omit quotes
- writeRaw(quoted, 0, quoted.length);
}
}
diff --git a/src/test/java/com/fasterxml/jackson/core/json/TestJsonGeneratorFeatures.java b/src/test/java/com/fasterxml/jackson/core/json/TestJsonGeneratorFeatures.java
index 5a42c83..68b7b7b 100644
--- a/src/test/java/com/fasterxml/jackson/core/json/TestJsonGeneratorFeatures.java
+++ b/src/test/java/com/fasterxml/jackson/core/json/TestJsonGeneratorFeatures.java
@@ -13,10 +13,11 @@
public class TestJsonGeneratorFeatures
extends com.fasterxml.jackson.core.BaseTest
{
+ private final JsonFactory JSON_F = new JsonFactory();
+
public void testConfigDefaults() throws IOException
{
- JsonFactory jf = new JsonFactory();
- JsonGenerator jg = jf.createGenerator(new StringWriter());
+ JsonGenerator jg = JSON_F.createGenerator(new StringWriter());
assertFalse(jg.isEnabled(JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS));
assertFalse(jg.isEnabled(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN));
jg.close();
@@ -35,8 +36,7 @@
_testFieldNameQuoting(jf, true);
}
- public void testNonNumericQuoting()
- throws IOException
+ public void testNonNumericQuoting() throws IOException
{
JsonFactory jf = new JsonFactory();
// by default, quoting should be enabled
@@ -126,6 +126,54 @@
return sw.toString();
}
+ // for [core#246]
+ public void testFieldNameQuotingEnabled() throws IOException
+ {
+ // // First, test with default factory, with quoting enabled by default
+
+ // First, default, with quotes
+ _testFieldNameQuotingEnabled(JSON_F, true, true, "{\"foo\":1}");
+ _testFieldNameQuotingEnabled(JSON_F, false, true, "{\"foo\":1}");
+
+ // then without quotes
+ _testFieldNameQuotingEnabled(JSON_F, true, false, "{foo:1}");
+ _testFieldNameQuotingEnabled(JSON_F, false, false, "{foo:1}");
+
+ // // Then with alternatively configured factory
+
+ JsonFactory JF2 = new JsonFactory();
+ JF2.disable(JsonGenerator.Feature.QUOTE_FIELD_NAMES);
+
+ _testFieldNameQuotingEnabled(JF2, true, true, "{\"foo\":1}");
+ _testFieldNameQuotingEnabled(JF2, false, true, "{\"foo\":1}");
+
+ // then without quotes
+ _testFieldNameQuotingEnabled(JF2, true, false, "{foo:1}");
+ _testFieldNameQuotingEnabled(JF2, false, false, "{foo:1}");
+ }
+
+ private void _testFieldNameQuotingEnabled(JsonFactory jf, boolean useBytes,
+ boolean useQuotes, String exp) throws IOException
+ {
+ ByteArrayOutputStream bytes = useBytes ? new ByteArrayOutputStream() : null;
+ StringWriter sw = useBytes ? null : new StringWriter();
+ JsonGenerator gen = useBytes ? jf.createGenerator(bytes) : jf.createGenerator(sw);
+ if (useQuotes) {
+ gen.enable(JsonGenerator.Feature.QUOTE_FIELD_NAMES);
+ } else {
+ gen.disable(JsonGenerator.Feature.QUOTE_FIELD_NAMES);
+ }
+
+ gen.writeStartObject();
+ gen.writeFieldName("foo");
+ gen.writeNumber(1);
+ gen.writeEndObject();
+ gen.close();
+
+ String json = useBytes ? bytes.toString("UTF-8") : sw.toString();
+ assertEquals(exp, json);
+ }
+
/*
/**********************************************************
/* Helper methods