From cdd85df15d8d6bd38f3b3d90bccf0678327e9efd Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Wed, 21 Aug 2019 22:53:17 -0700 Subject: [PATCH] Fix #60 --- .../com/fasterxml/jackson/jr/ob/JSON.java | 55 ++++++++++++++---- .../jackson/jr/ob/ValueIterator.java | 19 ++++++- .../fasterxml/jackson/jr/stree/JrsArray.java | 5 +- .../jackson/jr/stree/JrsMissing.java | 9 ++- .../fasterxml/jackson/jr/stree/JrsObject.java | 5 +- .../fasterxml/jackson/jr/stree/JrsValue.java | 20 +++++-- .../jr/stree/ReadTreeSequencesTest.java | 56 +++++++++++++++++++ 7 files changed, 140 insertions(+), 29 deletions(-) create mode 100644 jr-stree/src/test/java/com/fasterxml/jackson/jr/stree/ReadTreeSequencesTest.java diff --git a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/JSON.java b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/JSON.java index c6a12b09..a300d9d1 100644 --- a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/JSON.java +++ b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/JSON.java @@ -898,22 +898,22 @@ public T[] arrayOfFrom(Class type, Object source) throws IOException, JSO } @SuppressWarnings("unchecked") - public Map mapFrom(Object source) throws IOException, JSONObjectException + public Map mapFrom(Object source) throws IOException, JSONObjectException { if (source instanceof JsonParser) { JsonParser p = _initForReading((JsonParser) source); - Map result = _readerForOperation(p).readMap(); + Map result = _readerForOperation(p).readMap(); p.clearCurrentToken(); - return (Map) result; + return (Map) result; } JsonParser p = _parser(source); try { _initForReading(_config(p)); - Map result = _readerForOperation(p).readMap(); + Map result = _readerForOperation(p).readMap(); JsonParser p0 = p; p = null; _close(p0, null); - return (Map) result; + return (Map) result; } catch (Exception e) { return _closeWithError(p, e); } @@ -987,7 +987,7 @@ public Object anyFrom(Object source) throws IOException * @since 2.8 */ @SuppressWarnings("unchecked") - public TreeNode treeFrom(Object source) + public T treeFrom(Object source) throws IOException, JSONObjectException { if (_treeCodec == null) { @@ -1028,7 +1028,7 @@ public TreeNode treeFrom(Object source) * @since 2.10 */ public ValueIterator beanSequenceFrom(Class type, Object source) - throws IOException, JSONObjectException + throws IOException, JSONObjectException { JsonParser p; final boolean managed = !(source instanceof JsonParser); @@ -1040,19 +1040,21 @@ public ValueIterator beanSequenceFrom(Class type, Object source) } p = _initForReading(_config(p)); JSONReader reader = _readerForOperation(p); - return new ValueIterator(ValueIterator.MODE_BEAN, type, p, reader, managed); + return new ValueIterator(ValueIterator.MODE_BEAN, type, + p, reader, _treeCodec, managed); } /** * Method for creating {@link ValueIterator} for reading * streaming JSON * content (specifically line-delimited and concatenated variants); - * individual values are bound as "Any" type: {@link java.util.Map}, + * individual values are bound as "Simple" type: {@link java.util.Map}, * {@link java.util.List}, {@link String}, {@link Number} or {@link Boolean}. * * @since 2.10 */ - public ValueIterator anySequenceFrom(Object source) throws IOException + public ValueIterator anySequenceFrom(Object source) + throws IOException, JSONObjectException { JsonParser p; final boolean managed = !(source instanceof JsonParser); @@ -1064,9 +1066,38 @@ public ValueIterator anySequenceFrom(Object source) throws IOException } p = _initForReading(_config(p)); JSONReader reader = _readerForOperation(p); - return new ValueIterator(ValueIterator.MODE_ANY, Object.class, p, reader, managed); + return new ValueIterator(ValueIterator.MODE_ANY, Object.class, + p, reader, _treeCodec, managed); } - + + /** + * Method for creating {@link ValueIterator} for reading + * streaming JSON + * content (specifically line-delimited and concatenated variants); + * individual values are bound as JSON Trees(of type that configured + * {@link TreeCodec}, see {@link #with(TreeCodec)}) supports. + */ + public ValueIterator treeSequenceFrom(Object source) + throws IOException, JSONObjectException + { + if (_treeCodec == null) { + _noTreeCodec("read TreeNode"); + } + + JsonParser p; + final boolean managed = !(source instanceof JsonParser); + + if (managed) { + p = _parser(source); + } else { + p = (JsonParser) source; + } + p = _initForReading(_config(p)); + JSONReader reader = _readerForOperation(p); + return new ValueIterator(ValueIterator.MODE_TREE, TreeNode.class, + p, reader, _treeCodec, managed); + } + /* /********************************************************************** /* API: TreeNode construction diff --git a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/ValueIterator.java b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/ValueIterator.java index d0e522b3..654176c2 100644 --- a/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/ValueIterator.java +++ b/jr-objects/src/main/java/com/fasterxml/jackson/jr/ob/ValueIterator.java @@ -29,8 +29,14 @@ public class ValueIterator implements Iterator, Closeable */ protected final static int MODE_ANY = 2; + /** + * Mode in which values are read as "Tree" values, as bound + * by registered {@link TreeCodec}. + */ + protected final static int MODE_TREE = 3; + protected final static ValueIterator EMPTY_ITERATOR = - new ValueIterator(MODE_BEAN, null, null, null, false); + new ValueIterator(MODE_BEAN, null, null, null, null, false); /* /********************************************************************** @@ -81,6 +87,11 @@ public class ValueIterator implements Iterator, Closeable */ protected final JSONReader _reader; + /** + * If "Tree" values are read, codec we need to use for binding + */ + protected final TreeCodec _treeCodec; + /** * Underlying parser used for reading content to bind. Initialized * as not null but set as null when @@ -125,12 +136,13 @@ public class ValueIterator implements Iterator, Closeable * closed by iterator. */ protected ValueIterator(int mode, Class type, JsonParser p, JSONReader reader, - boolean managedParser) + TreeCodec treeCodec, boolean managedParser) { _mode = mode; _type = type; _parser = p; _reader = reader; + _treeCodec = treeCodec; _closeParser = managedParser; /* Ok: one more thing; we may have to skip START_ARRAY, assuming @@ -280,6 +292,9 @@ public T nextValue() throws IOException case MODE_ANY: value = _reader.readValue(); break; + case MODE_TREE: + value = _treeCodec.readTree(_parser); + break; default: throw new IllegalStateException("Invalid mode: "+_mode); } diff --git a/jr-stree/src/main/java/com/fasterxml/jackson/jr/stree/JrsArray.java b/jr-stree/src/main/java/com/fasterxml/jackson/jr/stree/JrsArray.java index f2dc0718..fbc52d07 100644 --- a/jr-stree/src/main/java/com/fasterxml/jackson/jr/stree/JrsArray.java +++ b/jr-stree/src/main/java/com/fasterxml/jackson/jr/stree/JrsArray.java @@ -6,7 +6,6 @@ import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonPointer; import com.fasterxml.jackson.core.JsonToken; -import com.fasterxml.jackson.core.TreeNode; import static com.fasterxml.jackson.core.JsonToken.START_ARRAY; @@ -53,7 +52,7 @@ public JrsValue get(int i) { } @Override - public TreeNode get(String s) { + public JrsValue get(String s) { return null; } @@ -63,7 +62,7 @@ public JrsValue path(int i){ } @Override - public TreeNode path(String s) { + public JrsValue path(String s) { return JrsMissing.instance(); } diff --git a/jr-stree/src/main/java/com/fasterxml/jackson/jr/stree/JrsMissing.java b/jr-stree/src/main/java/com/fasterxml/jackson/jr/stree/JrsMissing.java index a37561f2..0f3f85f4 100644 --- a/jr-stree/src/main/java/com/fasterxml/jackson/jr/stree/JrsMissing.java +++ b/jr-stree/src/main/java/com/fasterxml/jackson/jr/stree/JrsMissing.java @@ -5,7 +5,6 @@ import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonPointer; import com.fasterxml.jackson.core.JsonToken; -import com.fasterxml.jackson.core.TreeNode; /** * Virtual node used instead of `null`, when an operation does not match an @@ -51,22 +50,22 @@ public int size() { } @Override - public TreeNode get(String s) { + public JrsValue get(String s) { return null; } @Override - public TreeNode get(int i) { + public JrsValue get(int i) { return null; } @Override - public TreeNode path(String s) { + public JrsValue path(String s) { return this; } @Override - public TreeNode path(int i) { + public JrsValue path(int i) { return this; } diff --git a/jr-stree/src/main/java/com/fasterxml/jackson/jr/stree/JrsObject.java b/jr-stree/src/main/java/com/fasterxml/jackson/jr/stree/JrsObject.java index fff0d523..9e7d1a75 100644 --- a/jr-stree/src/main/java/com/fasterxml/jackson/jr/stree/JrsObject.java +++ b/jr-stree/src/main/java/com/fasterxml/jackson/jr/stree/JrsObject.java @@ -8,7 +8,6 @@ import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonPointer; import com.fasterxml.jackson.core.JsonToken; -import com.fasterxml.jackson.core.TreeNode; public class JrsObject extends JrsValue { @@ -54,7 +53,7 @@ public Iterator fieldNames() } @Override - public TreeNode get(int i) { + public JrsValue get(int i) { return null; } @@ -64,7 +63,7 @@ public JrsValue get(String name) { } @Override - public TreeNode path(int i) { + public JrsValue path(int i) { return JrsMissing.instance(); } diff --git a/jr-stree/src/main/java/com/fasterxml/jackson/jr/stree/JrsValue.java b/jr-stree/src/main/java/com/fasterxml/jackson/jr/stree/JrsValue.java index 2806a6a6..2bdd88e4 100644 --- a/jr-stree/src/main/java/com/fasterxml/jackson/jr/stree/JrsValue.java +++ b/jr-stree/src/main/java/com/fasterxml/jackson/jr/stree/JrsValue.java @@ -106,6 +106,18 @@ public String asText() { /********************************************************************** */ + @Override + public abstract JrsValue get(String s); + + @Override + public abstract JrsValue get(int i); + + @Override + public abstract JrsValue path(String s); + + @Override + public abstract JrsValue path(int i); + protected abstract JrsValue _at(JsonPointer ptr); protected abstract void write(JsonGenerator g, JacksonJrsTreeCodec codec) throws IOException; @@ -138,22 +150,22 @@ public int size() { } @Override - public TreeNode get(String s) { + public JrsValue get(String s) { return null; } @Override - public TreeNode get(int i) { + public JrsValue get(int i) { return null; } @Override - public TreeNode path(String s) { + public JrsValue path(String s) { return JrsMissing.instance(); } @Override - public TreeNode path(int i) { + public JrsValue path(int i) { return JrsMissing.instance(); } diff --git a/jr-stree/src/test/java/com/fasterxml/jackson/jr/stree/ReadTreeSequencesTest.java b/jr-stree/src/test/java/com/fasterxml/jackson/jr/stree/ReadTreeSequencesTest.java new file mode 100644 index 00000000..f20bb3df --- /dev/null +++ b/jr-stree/src/test/java/com/fasterxml/jackson/jr/stree/ReadTreeSequencesTest.java @@ -0,0 +1,56 @@ +package com.fasterxml.jackson.jr.stree; + +import java.io.StringReader; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonParser.NumberType; +import com.fasterxml.jackson.core.TreeCodec; +import com.fasterxml.jackson.jr.ob.JSON; +import com.fasterxml.jackson.jr.ob.ValueIterator; + +public class ReadTreeSequencesTest extends TestBase +{ + private final TreeCodec TREE_CODEC = new JacksonJrsTreeCodec(); + private final JSON treeJSON = JSON.std.with(TREE_CODEC); + + public void testBeanSequence() throws Exception + { + final String INPUT = aposToQuotes("{'id':1, 'msg':'foo'} [1, 2, 3] null "); + + // First, managed + ValueIterator it = treeJSON.treeSequenceFrom(INPUT); + _verifyTreeSequence(it); + it.close(); + + // and parser we create + JsonParser p = treeJSON.createParser(new StringReader(INPUT)); + + it = treeJSON.treeSequenceFrom(p); + _verifyTreeSequence(it); + it.close(); + p.close(); + } + + private void _verifyTreeSequence(ValueIterator it) throws Exception + { + assertTrue(it.hasNext()); + JrsValue tree = it.nextValue(); + assertTrue(tree.isObject()); + assertEquals(2, tree.size()); + assertEquals(NumberType.INT, tree.path("id").numberType()); + assertEquals("foo", tree.path("msg").asText()); + + assertTrue(it.hasNext()); + tree = it.nextValue(); + assertTrue(tree.isArray()); + assertEquals(3, tree.size()); + assertTrue(tree.get(0).isNumber()); + assertTrue(tree.get(1).isNumber()); + assertEquals(NumberType.INT, tree.get(2).numberType()); + + assertTrue(it.hasNext()); + assertNull(it.nextValue()); + + assertFalse(it.hasNext()); + } +}