JOHNZON-195 ensure jsongenerator can write pritmitives directly (jsonp 1.1) and it still fails when it writes array items in an object
Project: http://git-wip-us.apache.org/repos/asf/johnzon/repo Commit: http://git-wip-us.apache.org/repos/asf/johnzon/commit/2893743f Tree: http://git-wip-us.apache.org/repos/asf/johnzon/tree/2893743f Diff: http://git-wip-us.apache.org/repos/asf/johnzon/diff/2893743f Branch: refs/heads/master Commit: 2893743f2846e0e5983d4efb593492e6525ae058 Parents: 54c0b11 Author: Romain Manni-Bucau <[email protected]> Authored: Thu Nov 22 09:55:02 2018 +0100 Committer: Romain Manni-Bucau <[email protected]> Committed: Thu Nov 22 09:55:02 2018 +0100 ---------------------------------------------------------------------- .../johnzon/core/JsonGeneratorFactoryImpl.java | 8 +- .../apache/johnzon/core/JsonGeneratorImpl.java | 98 +++++++++----------- .../johnzon/core/JsonGeneratorImplTest.java | 33 +++++++ .../johnzon/core/TestJsonGeneratorFactory.java | 5 +- 4 files changed, 84 insertions(+), 60 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/johnzon/blob/2893743f/johnzon-core/src/main/java/org/apache/johnzon/core/JsonGeneratorFactoryImpl.java ---------------------------------------------------------------------- diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonGeneratorFactoryImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonGeneratorFactoryImpl.java index 92abbcd..8d1f6ec 100644 --- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonGeneratorFactoryImpl.java +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonGeneratorFactoryImpl.java @@ -26,7 +26,6 @@ import java.nio.charset.Charset; import java.util.Collection; import java.util.Collections; import java.util.Map; -import java.util.concurrent.ConcurrentMap; import javax.json.stream.JsonGenerator; import javax.json.stream.JsonGeneratorFactory; @@ -39,7 +38,6 @@ public class JsonGeneratorFactoryImpl extends AbstractJsonFactory implements Jso JsonGenerator.PRETTY_PRINTING, GENERATOR_BUFFER_LENGTH, BUFFER_STRATEGY ); //key caching currently disabled - private final ConcurrentMap<String, String> cache = null;//new ConcurrentHashMap<String, String>(); private final boolean pretty; private final BufferStrategy.BufferProvider<char[]> bufferProvider; @@ -59,17 +57,17 @@ public class JsonGeneratorFactoryImpl extends AbstractJsonFactory implements Jso @Override public JsonGenerator createGenerator(final Writer writer) { - return new JsonGeneratorImpl(writer, bufferProvider, cache, pretty); + return new JsonGeneratorImpl(writer, bufferProvider, pretty); } @Override public JsonGenerator createGenerator(final OutputStream out) { - return new JsonGeneratorImpl(out, bufferProvider, cache, pretty); + return new JsonGeneratorImpl(out, bufferProvider, pretty); } @Override public JsonGenerator createGenerator(final OutputStream out, final Charset charset) { - return new JsonGeneratorImpl(out,charset, bufferProvider, cache, pretty); + return new JsonGeneratorImpl(out,charset, bufferProvider, pretty); } @Override http://git-wip-us.apache.org/repos/asf/johnzon/blob/2893743f/johnzon-core/src/main/java/org/apache/johnzon/core/JsonGeneratorImpl.java ---------------------------------------------------------------------- diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonGeneratorImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonGeneratorImpl.java index 49f52e1..ce5e8b7 100644 --- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonGeneratorImpl.java +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonGeneratorImpl.java @@ -36,7 +36,6 @@ import java.math.BigInteger; import java.nio.charset.Charset; import java.util.Iterator; import java.util.Map; -import java.util.concurrent.ConcurrentMap; class JsonGeneratorImpl implements JsonGenerator, JsonChars, Serializable { private static final Charset UTF8_CHARSET = Charset.forName("UTF-8"); @@ -47,27 +46,31 @@ class JsonGeneratorImpl implements JsonGenerator, JsonChars, Serializable { private int bufferPos = 0; private final boolean prettyPrint; private static final String INDENT = " "; - //private final ConcurrentMap<String, String> cache; private int depth = 0; private boolean closed; private final HStack<GeneratorState> state = new HStack<GeneratorState>(); private enum GeneratorState { - INITIAL(false, true), START_OBJECT(true, false), IN_OBJECT(true, false), AFTER_KEY(false, true), START_ARRAY(false, true), IN_ARRAY( - false, true), END(false, false); + INITIAL(false, true, false), // nothing created yet + START_OBJECT(true, false, true), IN_OBJECT(true, false, true), AFTER_KEY(false, true, false), // object + START_ARRAY(false, true, true), IN_ARRAY(false, true, true), // array + END(false, false, false), // end of context + ROOT_VALUE(false, false, true); // direct primitive (added in jsonp 1.1, was not supported in 1.0) private final boolean acceptsKey; private final boolean acceptsValue; + private final boolean endable; - GeneratorState(final boolean acceptsKey, final boolean acceptsValue) { + GeneratorState(final boolean acceptsKey, final boolean acceptsValue, final boolean endable) { this.acceptsKey = acceptsKey; this.acceptsValue = acceptsValue; + this.endable = endable; } } JsonGeneratorImpl(final Writer writer, final BufferStrategy.BufferProvider<char[]> bufferProvider, - final ConcurrentMap<String, String> cache, final boolean prettyPrint) { + final boolean prettyPrint) { this.writer = writer; //this.cache = cache; this.buffer = bufferProvider.newBuffer(); @@ -77,13 +80,13 @@ class JsonGeneratorImpl implements JsonGenerator, JsonChars, Serializable { } JsonGeneratorImpl(final OutputStream out, final BufferStrategy.BufferProvider<char[]> bufferProvider, - final ConcurrentMap<String, String> cache, final boolean prettyPrint) { - this(new OutputStreamWriter(out, UTF8_CHARSET), bufferProvider, cache, prettyPrint); + final boolean prettyPrint) { + this(new OutputStreamWriter(out, UTF8_CHARSET), bufferProvider, prettyPrint); } JsonGeneratorImpl(final OutputStream out, final Charset encoding, final BufferStrategy.BufferProvider<char[]> bufferProvider, - final ConcurrentMap<String, String> cache, final boolean prettyPrint) { - this(new OutputStreamWriter(out, encoding), bufferProvider, cache, prettyPrint); + final boolean prettyPrint) { + this(new OutputStreamWriter(out, encoding), bufferProvider, prettyPrint); } private void writeEol() { @@ -144,7 +147,7 @@ class JsonGeneratorImpl implements JsonGenerator, JsonChars, Serializable { @Override public JsonGenerator writeStartObject(final String name) { - checkObject(false); + checkObject(); writeKey(name); justWrite(START_OBJECT_CHAR); writeEol(); @@ -166,7 +169,7 @@ class JsonGeneratorImpl implements JsonGenerator, JsonChars, Serializable { @Override public JsonGenerator writeStartArray(final String name) { - checkObject(false); + checkObject(); writeKey(name); justWrite(START_ARRAY_CHAR); writeEol(); @@ -176,7 +179,7 @@ class JsonGeneratorImpl implements JsonGenerator, JsonChars, Serializable { } private void writeJsonValue(final String name, final JsonValue value) { - checkObject(false); + checkObject(); //TODO check null handling switch (value.getValueType()) { case ARRAY: @@ -227,7 +230,7 @@ class JsonGeneratorImpl implements JsonGenerator, JsonChars, Serializable { } private void writeJsonValue(final JsonValue value) { - checkArray(true); + checkArray(); //TODO check null handling switch (value.getValueType()) { case ARRAY: @@ -279,14 +282,14 @@ class JsonGeneratorImpl implements JsonGenerator, JsonChars, Serializable { @Override public JsonGenerator write(final String name, final JsonValue value) { - checkObject(false); + checkObject(); writeJsonValue(name, value); return this; } @Override public JsonGenerator write(final String name, final String value) { - checkObject(false); + checkObject(); writeKey(name); writeValueAsJsonString(value); return this; @@ -294,7 +297,7 @@ class JsonGeneratorImpl implements JsonGenerator, JsonChars, Serializable { @Override public JsonGenerator write(final String name, final BigInteger value) { - checkObject(false); + checkObject(); writeKey(name); writeValue(String.valueOf(value)); return this; @@ -302,7 +305,7 @@ class JsonGeneratorImpl implements JsonGenerator, JsonChars, Serializable { @Override public JsonGenerator write(final String name, final BigDecimal value) { - checkObject(false); + checkObject(); writeKey(name); writeValue(String.valueOf(value)); return this; @@ -310,7 +313,7 @@ class JsonGeneratorImpl implements JsonGenerator, JsonChars, Serializable { @Override public JsonGenerator write(final String name, final int value) { - checkObject(false); + checkObject(); writeKey(name); writeValue(value); return this; @@ -318,7 +321,7 @@ class JsonGeneratorImpl implements JsonGenerator, JsonChars, Serializable { @Override public JsonGenerator write(final String name, final long value) { - checkObject(false); + checkObject(); writeKey(name); writeValue(value); return this; @@ -326,7 +329,7 @@ class JsonGeneratorImpl implements JsonGenerator, JsonChars, Serializable { @Override public JsonGenerator write(final String name, final double value) { - checkObject(false); + checkObject(); checkDoubleRange(value); writeKey(name); writeValue(String.valueOf(value)); @@ -335,7 +338,7 @@ class JsonGeneratorImpl implements JsonGenerator, JsonChars, Serializable { @Override public JsonGenerator write(final String name, final boolean value) { - checkObject(false); + checkObject(); writeKey(name); writeValue(String.valueOf(value)); return this; @@ -343,7 +346,7 @@ class JsonGeneratorImpl implements JsonGenerator, JsonChars, Serializable { @Override public JsonGenerator writeNull(final String name) { - checkObject(false); + checkObject(); writeKey(name); writeValue(NULL); return this; @@ -351,8 +354,10 @@ class JsonGeneratorImpl implements JsonGenerator, JsonChars, Serializable { @Override public JsonGenerator writeEnd() { - checkArrayOrObject(false); final GeneratorState last = state.pop(); + if (last == null || !last.endable) { + throw new JsonGenerationException("Can't end current context: " + last); + } depth--; if (last != GeneratorState.START_ARRAY) { writeEol(); @@ -360,7 +365,7 @@ class JsonGeneratorImpl implements JsonGenerator, JsonChars, Serializable { writeIndent(); if (last == GeneratorState.IN_ARRAY || last == GeneratorState.START_ARRAY) { justWrite(END_ARRAY_CHAR); - } else { + } else if (last != GeneratorState.ROOT_VALUE) { justWrite(END_OBJECT_CHAR); } alignState(); @@ -369,49 +374,49 @@ class JsonGeneratorImpl implements JsonGenerator, JsonChars, Serializable { @Override public JsonGenerator write(final JsonValue value) { - checkArray(true); + checkArray(); writeJsonValue(value); return this; } @Override public JsonGenerator write(final String value) { - checkArray(true); + checkArray(); writeValueAsJsonString(value); return this; } @Override public JsonGenerator write(final BigDecimal value) { - checkArray(true); + checkArray(); writeValue(String.valueOf(value)); return this; } @Override public JsonGenerator write(final BigInteger value) { - checkArray(true); + checkArray(); writeValue(String.valueOf(value)); return this; } @Override public JsonGenerator write(final int value) { - checkArray(true); + checkArray(); writeValue(value); return this; } @Override public JsonGenerator write(final long value) { - checkArray(true); + checkArray(); writeValue(value); return this; } @Override public JsonGenerator write(final double value) { - checkArray(true); + checkArray(); checkDoubleRange(value); writeValue(String.valueOf(value)); return this; @@ -419,14 +424,14 @@ class JsonGeneratorImpl implements JsonGenerator, JsonChars, Serializable { @Override public JsonGenerator write(final boolean value) { - checkArray(true); + checkArray(); writeValue(String.valueOf(value)); return this; } @Override public JsonGenerator writeNull() { - checkArray(true); + checkArray(); writeValue(NULL); return this; } @@ -457,7 +462,8 @@ class JsonGeneratorImpl implements JsonGenerator, JsonChars, Serializable { return; } try { - if (currentState() != GeneratorState.END) { + final GeneratorState state = currentState(); + if (state != GeneratorState.END && state != GeneratorState.ROOT_VALUE) { throw new JsonGenerationException("Invalid json"); } } finally { @@ -603,34 +609,22 @@ class JsonGeneratorImpl implements JsonGenerator, JsonChars, Serializable { buffer[bufferPos++] = value; } - private void checkObject(final boolean allowInitial) { + private void checkObject() { final GeneratorState currentState = currentState(); if (currentState != GeneratorState.IN_OBJECT && currentState != GeneratorState.START_OBJECT) { - if (!allowInitial || currentState != GeneratorState.INITIAL) { - throw new JsonGenerationException("write(name, param) is only valid in objects"); - } + throw new JsonGenerationException("write(name, param) is only valid in objects"); } } - private void checkArray(final boolean allowInitial) { + private void checkArray() { final GeneratorState currentState = currentState(); if (currentState != GeneratorState.IN_ARRAY && currentState != GeneratorState.START_ARRAY) { - if (!allowInitial || currentState != GeneratorState.INITIAL) { + if (currentState != GeneratorState.INITIAL) { throw new JsonGenerationException("write(param) is only valid in arrays"); } } } - private void checkArrayOrObject(final boolean allowInitial) { - final GeneratorState currentState = currentState(); - if (currentState != GeneratorState.IN_ARRAY && currentState != GeneratorState.START_ARRAY - && currentState != GeneratorState.IN_OBJECT && currentState != GeneratorState.START_OBJECT) { - if (!allowInitial || currentState != GeneratorState.INITIAL) { - throw new JsonGenerationException("only valid within array or object"); - } - } - } - private static void checkDoubleRange(final double value) { if (Double.isInfinite(value) || Double.isNaN(value)) { throw new NumberFormatException("double can't be infinite or NaN"); @@ -661,7 +655,7 @@ class JsonGeneratorImpl implements JsonGenerator, JsonChars, Serializable { swapState(GeneratorState.IN_OBJECT); break; case INITIAL: - swapState(GeneratorState.END); + state.push(GeneratorState.ROOT_VALUE); break; default: } http://git-wip-us.apache.org/repos/asf/johnzon/blob/2893743f/johnzon-core/src/test/java/org/apache/johnzon/core/JsonGeneratorImplTest.java ---------------------------------------------------------------------- diff --git a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonGeneratorImplTest.java b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonGeneratorImplTest.java index e373f41..b359e20 100644 --- a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonGeneratorImplTest.java +++ b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonGeneratorImplTest.java @@ -441,4 +441,37 @@ public class JsonGeneratorImplTest { assertEquals("{\n" + " \"firstName\":\"John\"\n" + "}", buffer.toString()); } + + @Test(expected = JsonGenerationException.class) + public void errorWhenWritingValueInObject() { + Json.createGenerator(new StringWriter()).writeStartObject().write(1); + } + + @Test + public void writeNumber() { + { + final StringWriter writer = new StringWriter(); + Json.createGenerator(writer).write(1).writeEnd().close(); + assertEquals("1", writer.toString()); + } + { + final StringWriter writer = new StringWriter(); + Json.createGenerator(writer).write(1).close(); + assertEquals("1", writer.toString()); + } + } + + @Test + public void writeBoolean() { + { + final StringWriter writer = new StringWriter(); + Json.createGenerator(writer).write(true).writeEnd().close(); + assertEquals("true", writer.toString()); + } + { + final StringWriter writer = new StringWriter(); + Json.createGenerator(writer).write(true).close(); + assertEquals("true", writer.toString()); + } + } } http://git-wip-us.apache.org/repos/asf/johnzon/blob/2893743f/johnzon-mapper/src/test/java/org/apache/johnzon/core/TestJsonGeneratorFactory.java ---------------------------------------------------------------------- diff --git a/johnzon-mapper/src/test/java/org/apache/johnzon/core/TestJsonGeneratorFactory.java b/johnzon-mapper/src/test/java/org/apache/johnzon/core/TestJsonGeneratorFactory.java index 363a86d..3380b82 100644 --- a/johnzon-mapper/src/test/java/org/apache/johnzon/core/TestJsonGeneratorFactory.java +++ b/johnzon-mapper/src/test/java/org/apache/johnzon/core/TestJsonGeneratorFactory.java @@ -21,7 +21,6 @@ package org.apache.johnzon.core; import javax.json.stream.JsonGenerator; import java.io.Writer; import java.util.Collections; -import java.util.concurrent.ConcurrentHashMap; /** * This class is only used for {@link org.apache.johnzon.mapper.JsonGeneratorCloseTest}. @@ -36,13 +35,13 @@ import java.util.concurrent.ConcurrentHashMap; public class TestJsonGeneratorFactory extends JsonGeneratorFactoryImpl { public TestJsonGeneratorFactory() { - super(Collections.<String, Object>emptyMap()); + super(Collections.emptyMap()); } @Override public JsonGenerator createGenerator(Writer writer) { - return new JsonGeneratorImpl(writer, TestBufferProvider.INSTANCE, new ConcurrentHashMap<String, String>(0), false); + return new JsonGeneratorImpl(writer, TestBufferProvider.INSTANCE, false); } }
