Skip to content

Commit 66fbf33

Browse files
committed
Merge pull request #866 from islanderman/820
Add new method for ObjectReader to bind from JSON Pointer position
2 parents 817d8ec + 41be898 commit 66fbf33

File tree

2 files changed

+178
-21
lines changed

2 files changed

+178
-21
lines changed

src/main/java/com/fasterxml/jackson/databind/ObjectReader.java

+102-19
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,34 @@
11
package com.fasterxml.jackson.databind;
22

3-
import java.io.*;
3+
import java.io.File;
4+
import java.io.FileInputStream;
5+
import java.io.IOException;
6+
import java.io.InputStream;
7+
import java.io.Reader;
48
import java.net.URL;
59
import java.util.Iterator;
610
import java.util.Locale;
711
import java.util.Map;
812
import java.util.TimeZone;
913
import java.util.concurrent.ConcurrentHashMap;
1014

11-
import com.fasterxml.jackson.core.*;
15+
import com.fasterxml.jackson.core.Base64Variant;
16+
import com.fasterxml.jackson.core.FormatSchema;
17+
import com.fasterxml.jackson.core.JsonFactory;
18+
import com.fasterxml.jackson.core.JsonGenerator;
19+
import com.fasterxml.jackson.core.JsonLocation;
20+
import com.fasterxml.jackson.core.JsonParseException;
21+
import com.fasterxml.jackson.core.JsonParser;
22+
import com.fasterxml.jackson.core.JsonPointer;
23+
import com.fasterxml.jackson.core.JsonProcessingException;
24+
import com.fasterxml.jackson.core.JsonToken;
25+
import com.fasterxml.jackson.core.ObjectCodec;
26+
import com.fasterxml.jackson.core.TreeNode;
27+
import com.fasterxml.jackson.core.Version;
28+
import com.fasterxml.jackson.core.Versioned;
29+
import com.fasterxml.jackson.core.filter.FilteringParserDelegate;
30+
import com.fasterxml.jackson.core.filter.JsonPointerBasedFilter;
31+
import com.fasterxml.jackson.core.filter.TokenFilter;
1232
import com.fasterxml.jackson.core.type.ResolvedType;
1333
import com.fasterxml.jackson.core.type.TypeReference;
1434
import com.fasterxml.jackson.databind.cfg.ContextAttributes;
@@ -69,6 +89,12 @@ public class ObjectReader
6989
*/
7090
protected final boolean _unwrapRoot;
7191

92+
/**
93+
* Filter to be consider for JsonParser.
94+
* Default value to be null as filter not considered.
95+
*/
96+
private final TokenFilter _filter;
97+
7298
/*
7399
/**********************************************************
74100
/* Configuration that can be changed during building
@@ -178,6 +204,7 @@ protected ObjectReader(ObjectMapper mapper, DeserializationConfig config,
178204

179205
_rootDeserializer = _prefetchRootDeserializer(valueType);
180206
_dataFormatReaders = null;
207+
_filter = null;
181208
}
182209

183210
/**
@@ -204,6 +231,7 @@ protected ObjectReader(ObjectReader base, DeserializationConfig config,
204231
_injectableValues = injectableValues;
205232
_unwrapRoot = config.useRootWrapping();
206233
_dataFormatReaders = dataFormatReaders;
234+
_filter = base._filter;
207235
}
208236

209237
/**
@@ -224,6 +252,7 @@ protected ObjectReader(ObjectReader base, DeserializationConfig config)
224252
_injectableValues = base._injectableValues;
225253
_unwrapRoot = config.useRootWrapping();
226254
_dataFormatReaders = base._dataFormatReaders;
255+
_filter = base._filter;
227256
}
228257

229258
protected ObjectReader(ObjectReader base, JsonFactory f)
@@ -243,6 +272,22 @@ protected ObjectReader(ObjectReader base, JsonFactory f)
243272
_injectableValues = base._injectableValues;
244273
_unwrapRoot = base._unwrapRoot;
245274
_dataFormatReaders = base._dataFormatReaders;
275+
_filter = base._filter;
276+
}
277+
278+
protected ObjectReader(ObjectReader base, TokenFilter filter) {
279+
_config = base._config;
280+
_context = base._context;
281+
_rootDeserializers = base._rootDeserializers;
282+
_parserFactory = base._parserFactory;
283+
_valueType = base._valueType;
284+
_rootDeserializer = base._rootDeserializer;
285+
_valueToUpdate = base._valueToUpdate;
286+
_schema = base._schema;
287+
_injectableValues = base._injectableValues;
288+
_unwrapRoot = base._unwrapRoot;
289+
_dataFormatReaders = base._dataFormatReaders;
290+
_filter = filter;
246291
}
247292

248293
/**
@@ -1053,7 +1098,8 @@ public <T> T readValue(InputStream src)
10531098
if (_dataFormatReaders != null) {
10541099
return (T) _detectBindAndClose(_dataFormatReaders.findFormat(src), false);
10551100
}
1056-
return (T) _bindAndClose(_parserFactory.createParser(src));
1101+
1102+
return (T) _bindAndClose(_considerFilter(_parserFactory.createParser(src)));
10571103
}
10581104

10591105
/**
@@ -1069,7 +1115,8 @@ public <T> T readValue(Reader src)
10691115
if (_dataFormatReaders != null) {
10701116
_reportUndetectableSource(src);
10711117
}
1072-
return (T) _bindAndClose(_parserFactory.createParser(src));
1118+
1119+
return (T) _bindAndClose(_considerFilter(_parserFactory.createParser(src)));
10731120
}
10741121

10751122
/**
@@ -1085,7 +1132,8 @@ public <T> T readValue(String src)
10851132
if (_dataFormatReaders != null) {
10861133
_reportUndetectableSource(src);
10871134
}
1088-
return (T) _bindAndClose(_parserFactory.createParser(src));
1135+
1136+
return (T) _bindAndClose(_considerFilter(_parserFactory.createParser(src)));
10891137
}
10901138

10911139
/**
@@ -1101,7 +1149,8 @@ public <T> T readValue(byte[] src)
11011149
if (_dataFormatReaders != null) {
11021150
return (T) _detectBindAndClose(src, 0, src.length);
11031151
}
1104-
return (T) _bindAndClose(_parserFactory.createParser(src));
1152+
1153+
return (T) _bindAndClose(_considerFilter(_parserFactory.createParser(src)));
11051154
}
11061155

11071156
/**
@@ -1117,7 +1166,8 @@ public <T> T readValue(byte[] src, int offset, int length)
11171166
if (_dataFormatReaders != null) {
11181167
return (T) _detectBindAndClose(src, offset, length);
11191168
}
1120-
return (T) _bindAndClose(_parserFactory.createParser(src, offset, length));
1169+
1170+
return (T) _bindAndClose(_considerFilter(_parserFactory.createParser(src, offset, length)));
11211171
}
11221172

11231173
@SuppressWarnings("unchecked")
@@ -1127,7 +1177,8 @@ public <T> T readValue(File src)
11271177
if (_dataFormatReaders != null) {
11281178
return (T) _detectBindAndClose(_dataFormatReaders.findFormat(_inputStream(src)), true);
11291179
}
1130-
return (T) _bindAndClose(_parserFactory.createParser(src));
1180+
1181+
return (T) _bindAndClose(_considerFilter(_parserFactory.createParser(src)));
11311182
}
11321183

11331184
/**
@@ -1143,7 +1194,8 @@ public <T> T readValue(URL src)
11431194
if (_dataFormatReaders != null) {
11441195
return (T) _detectBindAndClose(_dataFormatReaders.findFormat(_inputStream(src)), true);
11451196
}
1146-
return (T) _bindAndClose(_parserFactory.createParser(src));
1197+
1198+
return (T) _bindAndClose(_considerFilter(_parserFactory.createParser(src)));
11471199
}
11481200

11491201
/**
@@ -1160,7 +1212,8 @@ public <T> T readValue(JsonNode src)
11601212
if (_dataFormatReaders != null) {
11611213
_reportUndetectableSource(src);
11621214
}
1163-
return (T) _bindAndClose(treeAsTokens(src));
1215+
1216+
return (T) _bindAndClose(_considerFilter(treeAsTokens(src)));
11641217
}
11651218

11661219
/**
@@ -1178,7 +1231,8 @@ public JsonNode readTree(InputStream in)
11781231
if (_dataFormatReaders != null) {
11791232
return _detectBindAndCloseAsTree(in);
11801233
}
1181-
return _bindAndCloseAsTree(_parserFactory.createParser(in));
1234+
1235+
return _bindAndCloseAsTree(_considerFilter(_parserFactory.createParser(in)));
11821236
}
11831237

11841238
/**
@@ -1196,7 +1250,8 @@ public JsonNode readTree(Reader r)
11961250
if (_dataFormatReaders != null) {
11971251
_reportUndetectableSource(r);
11981252
}
1199-
return _bindAndCloseAsTree(_parserFactory.createParser(r));
1253+
1254+
return _bindAndCloseAsTree(_considerFilter(_parserFactory.createParser(r)));
12001255
}
12011256

12021257
/**
@@ -1214,7 +1269,8 @@ public JsonNode readTree(String json)
12141269
if (_dataFormatReaders != null) {
12151270
_reportUndetectableSource(json);
12161271
}
1217-
return _bindAndCloseAsTree(_parserFactory.createParser(json));
1272+
1273+
return _bindAndCloseAsTree(_considerFilter(_parserFactory.createParser(json)));
12181274
}
12191275

12201276
/*
@@ -1268,7 +1324,8 @@ public <T> MappingIterator<T> readValues(InputStream src)
12681324
if (_dataFormatReaders != null) {
12691325
return _detectBindAndReadValues(_dataFormatReaders.findFormat(src), false);
12701326
}
1271-
return _bindAndReadValues(_parserFactory.createParser(src));
1327+
1328+
return _bindAndReadValues(_considerFilter(_parserFactory.createParser(src)));
12721329
}
12731330

12741331
/**
@@ -1281,7 +1338,7 @@ public <T> MappingIterator<T> readValues(Reader src)
12811338
if (_dataFormatReaders != null) {
12821339
_reportUndetectableSource(src);
12831340
}
1284-
JsonParser p = _parserFactory.createParser(src);
1341+
JsonParser p = _considerFilter(_parserFactory.createParser(src));
12851342
_initForMultiRead(p);
12861343
p.nextToken();
12871344
DeserializationContext ctxt = createDeserializationContext(p);
@@ -1300,7 +1357,7 @@ public <T> MappingIterator<T> readValues(String json)
13001357
if (_dataFormatReaders != null) {
13011358
_reportUndetectableSource(json);
13021359
}
1303-
JsonParser p = _parserFactory.createParser(json);
1360+
JsonParser p = _considerFilter(_parserFactory.createParser(json));
13041361
_initForMultiRead(p);
13051362
p.nextToken();
13061363
DeserializationContext ctxt = createDeserializationContext(p);
@@ -1316,7 +1373,7 @@ public <T> MappingIterator<T> readValues(byte[] src, int offset, int length)
13161373
if (_dataFormatReaders != null) {
13171374
return _detectBindAndReadValues(_dataFormatReaders.findFormat(src, offset, length), false);
13181375
}
1319-
return _bindAndReadValues(_parserFactory.createParser(src));
1376+
return _bindAndReadValues(_considerFilter(_parserFactory.createParser(src)));
13201377
}
13211378

13221379
/**
@@ -1337,7 +1394,7 @@ public <T> MappingIterator<T> readValues(File src)
13371394
return _detectBindAndReadValues(
13381395
_dataFormatReaders.findFormat(_inputStream(src)), false);
13391396
}
1340-
return _bindAndReadValues(_parserFactory.createParser(src));
1397+
return _bindAndReadValues(_considerFilter(_parserFactory.createParser(src)));
13411398
}
13421399

13431400
/**
@@ -1352,7 +1409,7 @@ public <T> MappingIterator<T> readValues(URL src)
13521409
return _detectBindAndReadValues(
13531410
_dataFormatReaders.findFormat(_inputStream(src)), true);
13541411
}
1355-
return _bindAndReadValues(_parserFactory.createParser(src));
1412+
return _bindAndReadValues(_considerFilter(_parserFactory.createParser(src)));
13561413
}
13571414

13581415
/*
@@ -1422,6 +1479,14 @@ protected Object _bind(JsonParser p, Object valueToUpdate) throws IOException
14221479
return result;
14231480
}
14241481

1482+
/**
1483+
* Consider filter when creating JsonParser.
1484+
*/
1485+
protected JsonParser _considerFilter(final JsonParser p) {
1486+
return _filter == null || FilteringParserDelegate.class.isInstance(p)
1487+
? p : new FilteringParserDelegate(p, _filter, false, false);
1488+
}
1489+
14251490
protected Object _bindAndClose(JsonParser p) throws IOException
14261491
{
14271492
try {
@@ -1734,4 +1799,22 @@ protected JsonDeserializer<Object> _prefetchRootDeserializer(JavaType valueType)
17341799
}
17351800
return deser;
17361801
}
1802+
1803+
/**
1804+
* Convenience method to bind from {@link JsonPointer}.
1805+
* {@link JsonPointerBasedFilter} is registered and will be used for parsing later.
1806+
* @since 2.6
1807+
*/
1808+
public ObjectReader at(final String value) {
1809+
return new ObjectReader(this, new JsonPointerBasedFilter(value));
1810+
}
1811+
1812+
/**
1813+
* Convenience method to bind from {@link JsonPointer}
1814+
* {@link JsonPointerBasedFilter} is registered and will be used for parsing later.
1815+
* @since 2.6
1816+
*/
1817+
public ObjectReader at(final JsonPointer pointer) {
1818+
return new ObjectReader(this, new JsonPointerBasedFilter(pointer));
1819+
}
17371820
}

src/test/java/com/fasterxml/jackson/databind/seq/ObjectReaderTest.java

+76-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,23 @@
11
package com.fasterxml.jackson.databind.seq;
22

3-
import com.fasterxml.jackson.core.*;
3+
import java.util.Map;
44

5-
import com.fasterxml.jackson.databind.*;
5+
import com.fasterxml.jackson.core.JsonParser;
6+
import com.fasterxml.jackson.core.JsonProcessingException;
7+
import com.fasterxml.jackson.databind.BaseMapTest;
8+
import com.fasterxml.jackson.databind.JsonNode;
9+
import com.fasterxml.jackson.databind.MappingIterator;
10+
import com.fasterxml.jackson.databind.ObjectMapper;
11+
import com.fasterxml.jackson.databind.ObjectReader;
612

713
public class ObjectReaderTest extends BaseMapTest
814
{
915
final ObjectMapper MAPPER = new ObjectMapper();
1016

17+
static class POJO {
18+
public Map<String, Object> name;
19+
}
20+
1121
public void testParserFeatures() throws Exception
1222
{
1323
final String JSON = "[ /* foo */ 7 ]";
@@ -28,4 +38,68 @@ public void testParserFeatures() throws Exception
2838
verifyException(e, "foo");
2939
}
3040
}
41+
42+
public void testNoPointerLoading() throws Exception {
43+
final String source = "{\"foo\":{\"bar\":{\"caller\":{\"name\":{\"value\":1234}}}}}";
44+
45+
JsonNode tree = MAPPER.readTree(source);
46+
JsonNode node = tree.at("/foo/bar/caller");
47+
POJO pojo = MAPPER.treeToValue(node, POJO.class);
48+
assertTrue(pojo.name.containsKey("value"));
49+
assertEquals(1234, pojo.name.get("value"));
50+
}
51+
52+
public void testPointerLoading() throws Exception {
53+
final String source = "{\"foo\":{\"bar\":{\"caller\":{\"name\":{\"value\":1234}}}}}";
54+
55+
ObjectReader reader = MAPPER.readerFor(POJO.class).at("/foo/bar/caller");
56+
57+
POJO pojo = reader.readValue(source);
58+
assertTrue(pojo.name.containsKey("value"));
59+
assertEquals(1234, pojo.name.get("value"));
60+
}
61+
62+
public void testPointerLoadingAsJsonNode() throws Exception {
63+
final String source = "{\"foo\":{\"bar\":{\"caller\":{\"name\":{\"value\":1234}}}}}";
64+
65+
ObjectReader reader = MAPPER.readerFor(POJO.class).at("/foo/bar/caller");
66+
67+
JsonNode node = reader.readTree(source);
68+
assertTrue(node.has("name"));
69+
assertEquals("{\"value\":1234}", node.get("name").toString());
70+
}
71+
72+
public void testPointerLoadingMappingIteratorOne() throws Exception {
73+
final String source = "{\"foo\":{\"bar\":{\"caller\":{\"name\":{\"value\":1234}}}}}";
74+
75+
ObjectReader reader = MAPPER.readerFor(POJO.class).at("/foo/bar/caller");
76+
77+
MappingIterator<POJO> itr = reader.readValues(source);
78+
79+
POJO pojo = itr.next();
80+
81+
assertTrue(pojo.name.containsKey("value"));
82+
assertEquals(1234, pojo.name.get("value"));
83+
assertFalse(itr.hasNext());
84+
}
85+
86+
public void testPointerLoadingMappingIteratorMany() throws Exception {
87+
final String source = "{\"foo\":{\"bar\":{\"caller\":[{\"name\":{\"value\":1234}}, {\"name\":{\"value\":5678}}]}}}";
88+
89+
ObjectReader reader = MAPPER.readerFor(POJO.class).at("/foo/bar/caller");
90+
91+
MappingIterator<POJO> itr = reader.readValues(source);
92+
93+
POJO pojo = itr.next();
94+
95+
assertTrue(pojo.name.containsKey("value"));
96+
assertEquals(1234, pojo.name.get("value"));
97+
assertTrue(itr.hasNext());
98+
99+
pojo = itr.next();
100+
101+
assertTrue(pojo.name.containsKey("value"));
102+
assertEquals(5678, pojo.name.get("value"));
103+
assertFalse(itr.hasNext());
104+
}
31105
}

0 commit comments

Comments
 (0)