Skip to content

Commit 7795579

Browse files
committed
#2013: add support for reading from / writing to a Path
And adding base tests for all createGenerator(..) and createParser(..) methods.
1 parent 44a5c9f commit 7795579

File tree

3 files changed

+215
-0
lines changed

3 files changed

+215
-0
lines changed

src/main/java/com/fasterxml/jackson/core/TokenStreamFactory.java

+70
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
import java.io.*;
88
import java.lang.ref.SoftReference;
99
import java.net.URL;
10+
import java.nio.file.Files;
11+
import java.nio.file.Path;
1012
import java.util.List;
1113
import java.util.Locale;
1214

@@ -703,6 +705,32 @@ public PropertyNameMatcher constructCINameMatcher(List<Named> matches, boolean a
703705
public abstract JsonParser createParser(ObjectReadContext readCtxt,
704706
File f) throws JacksonException;
705707

708+
/**
709+
* Method for constructing parser instance to decode
710+
* contents of specified path.
711+
*<p>
712+
* Encoding is auto-detected from contents according to JSON
713+
* specification recommended mechanism. Json specification
714+
* supports only UTF-8, UTF-16 and UTF-32 as valid encodings,
715+
* so auto-detection implemented only for this charsets.
716+
* For other charsets use {@link #createParser(java.io.Reader)}.
717+
*<p>
718+
* Underlying input stream (needed for reading contents)
719+
* will be <b>owned</b> (and managed, i.e. closed as need be) by
720+
* the parser, since caller has no access to it.
721+
*
722+
* @param readCtxt Object read context to use
723+
* @param p Path that contains content to parse
724+
*
725+
* @return Parser constructed
726+
*
727+
* @throws JacksonException If parser construction or initialization fails
728+
*
729+
* @since 3.0
730+
*/
731+
public abstract JsonParser createParser(ObjectReadContext readCtxt,
732+
Path p) throws JacksonException;
733+
706734
/**
707735
* Method for constructing JSON parser instance to decode
708736
* contents of resource reference by given URL.
@@ -1131,6 +1159,30 @@ public abstract JsonGenerator createGenerator(ObjectWriteContext writeCtxt, File
11311159
JsonEncoding enc)
11321160
throws JacksonException;
11331161

1162+
/**
1163+
* Method for constructing generator that writes contents
1164+
* to specified path, overwriting contents it might have (or creating
1165+
* it if such path does not yet exist).
1166+
*<p>
1167+
* Underlying stream <b>is owned</b> by the generator constructed,
1168+
* i.e. generator will handle closing of path when
1169+
* {@link JsonGenerator#close} is called.
1170+
*
1171+
* @param writeCtxt Object-binding context where applicable; used for providing contextual
1172+
* configuration
1173+
* @param p Path to write contents to
1174+
* @param enc Character set encoding to use (usually {@link JsonEncoding#UTF8})
1175+
*
1176+
* @return Generator constructed
1177+
*
1178+
* @throws JacksonException If generator construction or initialization fails
1179+
*
1180+
* @since 3.0
1181+
*/
1182+
public abstract JsonGenerator createGenerator(ObjectWriteContext writeCtxt, Path p,
1183+
JsonEncoding enc)
1184+
throws JacksonException;
1185+
11341186
/**
11351187
* Method for constructing generator that writes content into specified {@link DataOutput},
11361188
* using UTF-8 encoding (with formats where encoding is user-configurable).
@@ -1329,6 +1381,15 @@ protected InputStream _fileInputStream(File f) throws JacksonException
13291381
}
13301382
}
13311383

1384+
protected InputStream _pathInputStream(Path p) throws JacksonException
1385+
{
1386+
try {
1387+
return Files.newInputStream(p);
1388+
} catch (IOException e) {
1389+
throw _wrapIOFailure(e);
1390+
}
1391+
}
1392+
13321393
protected OutputStream _fileOutputStream(File f) throws JacksonException
13331394
{
13341395
try {
@@ -1338,6 +1399,15 @@ protected OutputStream _fileOutputStream(File f) throws JacksonException
13381399
}
13391400
}
13401401

1402+
protected OutputStream _pathOutputStream(Path p) throws JacksonException
1403+
{
1404+
try {
1405+
return Files.newOutputStream(p);
1406+
} catch (IOException e) {
1407+
throw _wrapIOFailure(e);
1408+
}
1409+
}
1410+
13411411
protected JacksonException _wrapIOFailure(IOException e) {
13421412
return WrappedIOException.construct(e, this);
13431413
}

src/main/java/com/fasterxml/jackson/core/base/TextualTSFactory.java

+25
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.io.*;
44
import java.net.URL;
5+
import java.nio.file.Path;
56

67
import com.fasterxml.jackson.core.*;
78
import com.fasterxml.jackson.core.io.IOContext;
@@ -95,6 +96,16 @@ public JsonParser createParser(ObjectReadContext readCtxt,
9596
_decorate(ioCtxt, _fileInputStream(f)));
9697
}
9798

99+
@Override
100+
public JsonParser createParser(ObjectReadContext readCtxt,
101+
Path p) throws JacksonException
102+
{
103+
// true, since we create InputStream from Path
104+
IOContext ioCtxt = _createContext(p, true);
105+
return _createParser(readCtxt, ioCtxt,
106+
_decorate(ioCtxt, _pathInputStream(p)));
107+
}
108+
98109
@Override
99110
public JsonParser createParser(ObjectReadContext readCtxt,
100111
URL url) throws JacksonException
@@ -233,6 +244,20 @@ public JsonGenerator createGenerator(ObjectWriteContext writeCtxt,
233244
_decorate(ioCtxt, _createWriter(ioCtxt, out, enc)));
234245
}
235246

247+
@Override
248+
public JsonGenerator createGenerator(ObjectWriteContext writeCtxt,
249+
Path p, JsonEncoding enc)
250+
throws JacksonException
251+
{
252+
final OutputStream out = _pathOutputStream(p);
253+
final IOContext ioCtxt = _createContext(p, true, enc);
254+
if (enc == JsonEncoding.UTF8) {
255+
return _createUTF8Generator(writeCtxt, ioCtxt, _decorate(ioCtxt, out));
256+
}
257+
return _createGenerator(writeCtxt, ioCtxt,
258+
_decorate(ioCtxt, _createWriter(ioCtxt, out, enc)));
259+
}
260+
236261
/*
237262
/**********************************************************************
238263
/* Factory methods: abstract, for sub-classes to implement

src/test/java/com/fasterxml/jackson/core/json/JsonFactoryTest.java

+120
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.fasterxml.jackson.core.json;
22

33
import java.io.*;
4+
import java.nio.charset.StandardCharsets;
5+
import java.nio.file.*;
46

57
import com.fasterxml.jackson.core.*;
68
import com.fasterxml.jackson.core.io.SerializedString;
@@ -200,4 +202,122 @@ public void testRootValues() throws Exception
200202
g.close();
201203
assertEquals("1/2/3", w.toString());
202204
}
205+
206+
public void test_createGenerator_OutputStream() throws Exception
207+
{
208+
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
209+
JsonGenerator jsonGenerator = new JsonFactory()
210+
.createGenerator(ObjectWriteContext.empty(), outputStream);
211+
212+
jsonGenerator.writeString("value");
213+
jsonGenerator.close();
214+
215+
assertEquals(new String(outputStream.toByteArray(), StandardCharsets.UTF_8), "\"value\"");
216+
217+
// the stream has not been closed by close
218+
outputStream.write(1);
219+
}
220+
221+
public void test_createGenerator_File() throws Exception
222+
{
223+
Path path = Files.createTempFile("", "");
224+
JsonGenerator jsonGenerator = new JsonFactory()
225+
.createGenerator(ObjectWriteContext.empty(), path.toFile(), JsonEncoding.UTF8);
226+
227+
jsonGenerator.writeString("value");
228+
jsonGenerator.close();
229+
230+
assertEquals(new String(Files.readAllBytes(path), StandardCharsets.UTF_8), "\"value\"");
231+
}
232+
233+
public void test_createGenerator_Path() throws Exception
234+
{
235+
Path path = Files.createTempFile("", "");
236+
JsonGenerator jsonGenerator = new JsonFactory()
237+
.createGenerator(ObjectWriteContext.empty(), path, JsonEncoding.UTF8);
238+
239+
jsonGenerator.writeString("value");
240+
jsonGenerator.close();
241+
242+
assertEquals(new String(Files.readAllBytes(path), StandardCharsets.UTF_8), "\"value\"");
243+
}
244+
245+
public void test_createGenerator_Writer() throws Exception
246+
{
247+
Writer writer = new StringWriter();
248+
JsonGenerator jsonGenerator = new JsonFactory()
249+
.createGenerator(ObjectWriteContext.empty(), writer);
250+
251+
jsonGenerator.writeString("value");
252+
jsonGenerator.close();
253+
254+
assertEquals(writer.toString(), "\"value\"");
255+
256+
// the writer has not been closed by close
257+
writer.append('1');
258+
}
259+
260+
public void test_createGenerator_DataOutput() throws Exception
261+
{
262+
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
263+
DataOutput dataOutput = new DataOutputStream(outputStream);
264+
JsonGenerator jsonGenerator = new JsonFactory()
265+
.createGenerator(ObjectWriteContext.empty(), dataOutput);
266+
267+
jsonGenerator.writeString("value");
268+
jsonGenerator.close();
269+
270+
assertEquals(new String(outputStream.toByteArray(), StandardCharsets.UTF_8), "\"value\"");
271+
272+
// the data output has not been closed by close
273+
dataOutput.write(1);
274+
}
275+
276+
public void test_createParser_OutputStream() throws Exception
277+
{
278+
ByteArrayInputStream inputStream = new ByteArrayInputStream("\"value\"".getBytes(StandardCharsets.UTF_8));
279+
JsonParser jsonParser = new JsonFactory()
280+
.createParser(ObjectReadContext.empty(), inputStream);
281+
282+
assertEquals(jsonParser.nextTextValue(), "value");
283+
}
284+
285+
public void test_createParser_File() throws Exception
286+
{
287+
Path path = Files.createTempFile("", "");
288+
Files.write(path, "\"value\"".getBytes(StandardCharsets.UTF_8));
289+
JsonParser jsonParser = new JsonFactory()
290+
.createParser(ObjectReadContext.empty(), path.toFile());
291+
292+
assertEquals(jsonParser.nextTextValue(), "value");
293+
}
294+
295+
public void test_createParser_Path() throws Exception
296+
{
297+
Path path = Files.createTempFile("", "");
298+
Files.write(path, "\"value\"".getBytes(StandardCharsets.UTF_8));
299+
JsonParser jsonParser = new JsonFactory()
300+
.createParser(ObjectReadContext.empty(), path);
301+
302+
assertEquals(jsonParser.nextTextValue(), "value");
303+
}
304+
305+
public void test_createParser_Reader() throws Exception
306+
{
307+
Reader reader = new StringReader("\"value\"");
308+
JsonParser jsonParser = new JsonFactory()
309+
.createParser(ObjectReadContext.empty(), reader);
310+
311+
assertEquals(jsonParser.nextTextValue(), "value");
312+
}
313+
314+
public void test_createParser_DataInput() throws Exception
315+
{
316+
InputStream inputStream = new ByteArrayInputStream("\"value\"".getBytes(StandardCharsets.UTF_8));
317+
DataInput dataInput = new DataInputStream(inputStream);
318+
JsonParser jsonParser = new JsonFactory()
319+
.createParser(ObjectReadContext.empty(), dataInput);
320+
321+
assertEquals(jsonParser.nextTextValue(), "value");
322+
}
203323
}

0 commit comments

Comments
 (0)