Skip to content

Commit 1680b20

Browse files
authored
Fix #5111: add ObjectMapper/ObjectReader methods that take TokenBuffer (#5117)
1 parent 275c599 commit 1680b20

File tree

6 files changed

+161
-5
lines changed

6 files changed

+161
-5
lines changed

release-notes/CREDITS

+3
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,8 @@ Andy Boothe (@sigpwned)
4444
Sébastien Deleuze (@sdeleuze)
4545
* Requested #5110: Add missing `ObjectMapper#createNonBlockingByteBufferParser()` method
4646
[3.0.0]
47+
* Requested #5111: Improve support for deserializing from `TokenBuffer` (f.ex for
48+
content buffered for non-blocking parsing)
49+
[3.0.0]
4750
* Requested #5112: Add a `MapperBuilder#findAndAddModules(ClassLoader)` variant
4851
[3.0.0]

release-notes/VERSION

+3
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ Versions: 3.x (for earlier see VERSION-2.x)
1313
to use `Supplier`
1414
#5110: Add missing `ObjectMapper#createNonBlockingByteBufferParser()` method
1515
(requested by Sébastien D)
16+
#5111: Improve support for deserializing from `TokenBuffer` (f.ex for
17+
content buffered for non-blocking parsing)
18+
(requested by Sébastien D)
1619
#5112: Add a `MapperBuilder#findAndAddModules(ClassLoader)` variant
1720
(requested by Sébastien D)
1821

src/main/java/tools/jackson/databind/ObjectMapper.java

+51-2
Original file line numberDiff line numberDiff line change
@@ -1204,8 +1204,6 @@ public JsonNode readTree(File file) throws JacksonException
12041204
/**
12051205
* Same as {@link #readTree(InputStream)} except content read from
12061206
* passed-in {@link Path}.
1207-
*
1208-
* @since 3.0
12091207
*/
12101208
public JsonNode readTree(Path path) throws JacksonException
12111209
{
@@ -1230,6 +1228,16 @@ public JsonNode readTree(URL src) throws JacksonException {
12301228
return _readTreeAndClose(ctxt, _streamFactory.createParser(ctxt, src));
12311229
}
12321230

1231+
/**
1232+
* Same as {@link #readTree(InputStream)} except content read from
1233+
* passed-in {@link TokenBuffer}.
1234+
*/
1235+
public JsonNode readTree(TokenBuffer src) throws JacksonException {
1236+
_assertNotNull("src", src);
1237+
DeserializationContextExt ctxt = _deserializationContext();
1238+
return _readTreeAndClose(ctxt, src.asParser(ctxt));
1239+
}
1240+
12331241
/*
12341242
/**********************************************************************
12351243
/* Public API serialization
@@ -1774,6 +1782,33 @@ public <T> T readValue(DataInput src, TypeReference<T> valueTypeRef) throws Jack
17741782
_streamFactory.createParser(ctxt, src), _typeFactory.constructType(valueTypeRef));
17751783
}
17761784

1785+
@SuppressWarnings("unchecked")
1786+
public <T> T readValue(TokenBuffer src, Class<T> valueType) throws JacksonException
1787+
{
1788+
_assertNotNull("src", src);
1789+
DeserializationContextExt ctxt = _deserializationContext();
1790+
return (T) _readMapAndClose(ctxt,
1791+
src.asParser(ctxt), _typeFactory.constructType(valueType));
1792+
}
1793+
1794+
@SuppressWarnings("unchecked")
1795+
public <T> T readValue(TokenBuffer src, JavaType valueType) throws JacksonException
1796+
{
1797+
_assertNotNull("src", src);
1798+
DeserializationContextExt ctxt = _deserializationContext();
1799+
return (T) _readMapAndClose(ctxt,
1800+
src.asParser(ctxt), valueType);
1801+
}
1802+
1803+
@SuppressWarnings("unchecked")
1804+
public <T> T readValue(TokenBuffer src, TypeReference<T> valueTypeRef) throws JacksonException
1805+
{
1806+
_assertNotNull("src", src);
1807+
DeserializationContextExt ctxt = _deserializationContext();
1808+
return (T) _readMapAndClose(ctxt,
1809+
src.asParser(ctxt), _typeFactory.constructType(valueTypeRef));
1810+
}
1811+
17771812
/*
17781813
/**********************************************************************
17791814
/* Public API: serialization (mapping from Java types to external format)
@@ -1891,6 +1926,20 @@ public byte[] writeValueAsBytes(Object value) throws JacksonException
18911926
}
18921927
}
18931928

1929+
/**
1930+
* Convenience method that can be used to serialize any Java value into newly created
1931+
* {@link TokenBuffer}. Functionally equivalent to calling
1932+
* {@link #writeValue(JsonGenerator, Object)} passing buffer as generator.
1933+
*/
1934+
public TokenBuffer writeValueIntoBuffer(Object value) throws JacksonException
1935+
{
1936+
final SerializationContextExt ctxt = _serializationContext();
1937+
try (TokenBuffer buf = ctxt.bufferForValueConversion()) {
1938+
_configAndWriteValue(ctxt, buf, value);
1939+
return buf;
1940+
}
1941+
}
1942+
18941943
/**
18951944
* Method called to configure the generator as necessary and then
18961945
* call write functionality

src/main/java/tools/jackson/databind/ObjectReader.java

+38-2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import tools.jackson.databind.type.SimpleType;
2828
import tools.jackson.databind.type.TypeFactory;
2929
import tools.jackson.databind.util.ClassUtil;
30+
import tools.jackson.databind.util.TokenBuffer;
3031

3132
/**
3233
* Builder object that can be used for per-serialization configuration of
@@ -1280,8 +1281,6 @@ public <T> T readValue(File f) throws JacksonException
12801281
* was specified with {@link #withValueToUpdate(Object)}.
12811282
*
12821283
* @param path Path that contains content to read
1283-
*
1284-
* @since 3.0
12851284
*/
12861285
@SuppressWarnings("unchecked")
12871286
public <T> T readValue(Path path) throws JacksonException
@@ -1341,6 +1340,23 @@ public <T> T readValue(DataInput input) throws JacksonException
13411340
_considerFilter(_parserFactory.createParser(ctxt, input), false));
13421341
}
13431342

1343+
/**
1344+
* Method that binds content read from given {@link TokenBuffer}
1345+
* using configuration of this reader.
1346+
* Value return is either newly constructed, or root value that
1347+
* was specified with {@link #withValueToUpdate(Object)}.
1348+
*
1349+
* @param src {@link TokenBuffer} that contains content to read
1350+
*/
1351+
@SuppressWarnings("unchecked")
1352+
public <T> T readValue(TokenBuffer src) throws JacksonException
1353+
{
1354+
_assertNotNull("src", src);
1355+
DeserializationContextExt ctxt = _deserializationContext();
1356+
return (T) _bindAndClose(ctxt,
1357+
_considerFilter(src.asParser(ctxt) , false));
1358+
}
1359+
13441360
/*
13451361
/**********************************************************************
13461362
/* Deserialization methods; JsonNode ("tree")
@@ -1432,6 +1448,18 @@ public JsonNode readTree(DataInput content) throws JacksonException
14321448
_considerFilter(_parserFactory.createParser(ctxt, content), false));
14331449
}
14341450

1451+
/**
1452+
* Same as {@link #readTree(InputStream)} except content read using
1453+
* passed-in {@link TokenBuffer}.
1454+
*/
1455+
public JsonNode readTree(TokenBuffer src) throws JacksonException
1456+
{
1457+
_assertNotNull("src", src);
1458+
DeserializationContextExt ctxt = _deserializationContext();
1459+
return _bindAndCloseAsTree(ctxt,
1460+
_considerFilter(src.asParser(ctxt), false));
1461+
}
1462+
14351463
/*
14361464
/**********************************************************************
14371465
/* Deserialization methods; reading sequence of values
@@ -1586,6 +1614,14 @@ public <T> MappingIterator<T> readValues(DataInput src) throws JacksonException
15861614
_considerFilter(_parserFactory.createParser(ctxt, src), true));
15871615
}
15881616

1617+
public <T> MappingIterator<T> readValues(TokenBuffer src) throws JacksonException
1618+
{
1619+
_assertNotNull("src", src);
1620+
DeserializationContextExt ctxt = _deserializationContext();
1621+
return _bindAndReadValues(ctxt,
1622+
_considerFilter(src.asParser(ctxt), true));
1623+
}
1624+
15891625
/*
15901626
/**********************************************************************
15911627
/* Misc conversion methods

src/main/java/tools/jackson/databind/ObjectWriter.java

+14
Original file line numberDiff line numberDiff line change
@@ -1090,6 +1090,20 @@ public byte[] writeValueAsBytes(Object value) throws JacksonException
10901090
}
10911091
}
10921092

1093+
/**
1094+
* Convenience method that can be used to serialize any Java value into newly created
1095+
* {@link TokenBuffer}. Functionally equivalent to calling
1096+
* {@link #writeValue(JsonGenerator, Object)} passing buffer as generator.
1097+
*/
1098+
public TokenBuffer writeValueIntoBuffer(Object value) throws JacksonException
1099+
{
1100+
final SerializationContextExt ctxt = _serializationContext();
1101+
try (TokenBuffer buf = ctxt.bufferForValueConversion()) {
1102+
_configAndWriteValue(ctxt, buf, value);
1103+
return buf;
1104+
}
1105+
}
1106+
10931107
/**
10941108
* Method called to configure the generator as necessary and then
10951109
* call write functionality

src/test/java/tools/jackson/databind/util/TokenBufferTest.java

+52-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public void serialize(Foo3816 value, JsonGenerator gen, SerializationContext pro
5151

5252
/*
5353
/**********************************************************************
54-
/* Basic TokenBuffer tests
54+
/* Basic TokenBuffer tests, direct access
5555
/**********************************************************************
5656
*/
5757

@@ -524,6 +524,57 @@ public void testWithUUID() throws IOException
524524
}
525525
}
526526

527+
/*
528+
/**********************************************************************
529+
/* TokenBuffer as source for ObjectMapper/ObjectReader tests
530+
/**********************************************************************
531+
*/
532+
533+
@Test
534+
public void readFromBufferViaObjectMapper() throws Exception {
535+
final Point TEST_OB = new Point(123, -456);
536+
537+
assertEquals(TEST_OB, MAPPER.readValue(_tokenBufferFor(TEST_OB),
538+
Point.class));
539+
assertEquals(TEST_OB, MAPPER.readValue(_tokenBufferFor(TEST_OB),
540+
MAPPER.constructType(Point.class)));
541+
assertEquals(TEST_OB, MAPPER.readValue(_tokenBufferFor(TEST_OB),
542+
new TypeReference<Point>() {}));
543+
544+
assertEquals(MAPPER.valueToTree(TEST_OB),
545+
MAPPER.readTree(_tokenBufferFor(TEST_OB)));
546+
547+
// Try alternate that fills TokenBuffer using mapper itself
548+
assertEquals(TEST_OB, MAPPER.readValue(MAPPER.writeValueIntoBuffer(TEST_OB),
549+
Point.class));
550+
}
551+
552+
@Test
553+
public void readFromBufferViaObjectReader() throws Exception {
554+
final Point TEST_OB = new Point(234, 5678);
555+
final ObjectReader R = MAPPER.readerFor(Point.class);
556+
557+
assertEquals(TEST_OB, R.readValue(_tokenBufferFor(TEST_OB)));
558+
559+
assertEquals(MAPPER.valueToTree(TEST_OB),
560+
R.readTree(_tokenBufferFor(TEST_OB)));
561+
562+
// Try alternate that fills TokenBuffer using ObjectWriter
563+
assertEquals(TEST_OB,
564+
R.readValue(MAPPER.writer().writeValueIntoBuffer(TEST_OB)));
565+
}
566+
567+
private TokenBuffer _tokenBufferFor(Object value) {
568+
final String json = MAPPER.writeValueAsString(value);
569+
TokenBuffer buf = TokenBuffer.forGeneration();
570+
try (JsonParser p = MAPPER.createParser(json)) {
571+
while (p.nextToken() != null) {
572+
buf.copyCurrentEvent(p);
573+
}
574+
}
575+
return buf;
576+
}
577+
527578
/*
528579
/**********************************************************
529580
/* Tests for read/output contexts

0 commit comments

Comments
 (0)