Skip to content

Commit

Permalink
#2013: add support for reading from / writing to a Path (#3066)
Browse files Browse the repository at this point in the history
  • Loading branch information
sdoeringNew authored Feb 27, 2021
1 parent 733b8d6 commit b014bee
Show file tree
Hide file tree
Showing 6 changed files with 1,448 additions and 5 deletions.
132 changes: 132 additions & 0 deletions src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.io.*;
import java.lang.reflect.Type;
import java.net.URL;
import java.nio.file.Path;
import java.text.DateFormat;
import java.util.Collection;
import java.util.List;
Expand Down Expand Up @@ -583,6 +584,20 @@ public JsonParser createParser(File src) throws JacksonException {
return ctxt.assignAndReturnParser(_streamFactory.createParser(ctxt, src));
}

/**
* Factory method for constructing {@link JsonParser} that is properly
* wired to allow callbacks for deserialization: basically
* constructs a {@link ObjectReadContext} and then calls
* {@link TokenStreamFactory#createParser(ObjectReadContext,Path)}.
*
* @since 3.0
*/
public JsonParser createParser(Path src) throws JacksonException {
_assertNotNull("src", src);
DeserializationContextExt ctxt = _deserializationContext();
return ctxt.assignAndReturnParser(_streamFactory.createParser(ctxt, src));
}

/**
* Factory method for constructing {@link JsonParser} that is properly
* wired to allow callbacks for deserialization: basically
Expand Down Expand Up @@ -781,6 +796,19 @@ public JsonGenerator createGenerator(File f, JsonEncoding enc) throws JacksonExc
return _streamFactory.createGenerator(_serializerProvider(), f, enc);
}

/**
* Factory method for constructing {@link JsonGenerator} that is properly
* wired to allow callbacks for serialization: basically
* constructs a {@link ObjectWriteContext} and then calls
* {@link TokenStreamFactory#createGenerator(ObjectWriteContext,Path,JsonEncoding)}.
*
* @since 3.0
*/
public JsonGenerator createGenerator(Path p, JsonEncoding enc) throws JacksonException {
_assertNotNull("p", p);
return _streamFactory.createGenerator(_serializerProvider(), p, enc);
}

/**
* Factory method for constructing {@link JsonGenerator} that is properly
* wired to allow callbacks for serialization: basically
Expand Down Expand Up @@ -1151,6 +1179,19 @@ public JsonNode readTree(File file) throws JacksonException
return _readTreeAndClose(ctxt, _streamFactory.createParser(ctxt, file));
}

/**
* Same as {@link #readTree(InputStream)} except content read from
* passed-in {@link Path}.
*
* @since 3.0
*/
public JsonNode readTree(Path path) throws JacksonException
{
_assertNotNull("path", path);
DeserializationContextExt ctxt = _deserializationContext();
return _readTreeAndClose(ctxt, _streamFactory.createParser(ctxt, path));
}

/**
* Same as {@link #readTree(InputStream)} except content read from
* passed-in {@link URL}.
Expand Down Expand Up @@ -1365,6 +1406,74 @@ public <T> T readValue(File src, JavaType valueType) throws JacksonException
return (T) _readMapAndClose(ctxt, _streamFactory.createParser(ctxt, src), valueType);
}

/**
* Method to deserialize JSON content from given path into given Java type.
*
* @throws WrappedIOException if a low-level I/O problem (unexpected end-of-input,
* network error) occurs (passed through as-is without additional wrapping -- note
* that this is one case where {@link DeserializationFeature#WRAP_EXCEPTIONS}
* does NOT result in wrapping of exception even if enabled)
* @throws StreamReadException if underlying input contains invalid content
* of type {@link JsonParser} supports (JSON for default case)
* @throws DatabindException if the input JSON structure does not match structure
* expected for result type (or has other mismatch issues)
*
* @since 3.0
*/
@SuppressWarnings("unchecked")
public <T> T readValue(Path src, Class<T> valueType) throws JacksonException
{
_assertNotNull("src", src);
DeserializationContextExt ctxt = _deserializationContext();
return (T) _readMapAndClose(ctxt, _streamFactory.createParser(ctxt, src),
_typeFactory.constructType(valueType));
}

/**
* Method to deserialize JSON content from given path into given Java type.
*
* @throws WrappedIOException if a low-level I/O problem (unexpected end-of-input,
* network error) occurs (passed through as-is without additional wrapping -- note
* that this is one case where {@link DeserializationFeature#WRAP_EXCEPTIONS}
* does NOT result in wrapping of exception even if enabled)
* @throws StreamReadException if underlying input contains invalid content
* of type {@link JsonParser} supports (JSON for default case)
* @throws DatabindException if the input JSON structure does not match structure
* expected for result type (or has other mismatch issues)
*
* @since 3.0
*/
@SuppressWarnings({ "unchecked" })
public <T> T readValue(Path src, TypeReference<T> valueTypeRef) throws JacksonException
{
_assertNotNull("src", src);
DeserializationContextExt ctxt = _deserializationContext();
return (T) _readMapAndClose(ctxt, _streamFactory.createParser(ctxt, src),
_typeFactory.constructType(valueTypeRef));
}

/**
* Method to deserialize JSON content from given path into given Java type.
*
* @throws WrappedIOException if a low-level I/O problem (unexpected end-of-input,
* network error) occurs (passed through as-is without additional wrapping -- note
* that this is one case where {@link DeserializationFeature#WRAP_EXCEPTIONS}
* does NOT result in wrapping of exception even if enabled)
* @throws StreamReadException if underlying input contains invalid content
* of type {@link JsonParser} supports (JSON for default case)
* @throws DatabindException if the input JSON structure does not match structure
* expected for result type (or has other mismatch issues)
*
* @since 3.0
*/
@SuppressWarnings("unchecked")
public <T> T readValue(Path src, JavaType valueType) throws JacksonException
{
_assertNotNull("src", src);
DeserializationContextExt ctxt = _deserializationContext();
return (T) _readMapAndClose(ctxt, _streamFactory.createParser(ctxt, src), valueType);
}

/**
* Method to deserialize JSON content from given resource into given Java type.
*<p>
Expand Down Expand Up @@ -1610,6 +1719,15 @@ public <T> T readValue(DataInput src, JavaType valueType) throws JacksonExceptio
_streamFactory.createParser(ctxt, src), valueType);
}

@SuppressWarnings("unchecked")
public <T> T readValue(DataInput src, TypeReference<T> valueTypeRef) throws JacksonException
{
_assertNotNull("src", src);
DeserializationContextExt ctxt = _deserializationContext();
return (T) _readMapAndClose(ctxt,
_streamFactory.createParser(ctxt, src), _typeFactory.constructType(valueTypeRef));
}

/*
/**********************************************************************
/* Public API: serialization (mapping from Java types to external format)
Expand All @@ -1628,6 +1746,20 @@ public void writeValue(File file, Object value) throws JacksonException
_streamFactory.createGenerator(prov, file, JsonEncoding.UTF8), value);
}

/**
* Method that can be used to serialize any Java value as
* JSON output, written to Path provided.
*
* @since 3.0
*/
public void writeValue(Path path, Object value) throws JacksonException
{
_assertNotNull("path", path);
SerializationContextExt prov = _serializerProvider();
_configAndWriteValue(prov,
_streamFactory.createGenerator(prov, path, JsonEncoding.UTF8), value);
}

/**
* Method that can be used to serialize any Java value as
* JSON output, using output stream provided (using encoding
Expand Down
56 changes: 56 additions & 0 deletions src/main/java/com/fasterxml/jackson/databind/ObjectReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import java.io.*;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

Expand Down Expand Up @@ -773,6 +775,20 @@ public JsonParser createParser(File src) throws JacksonException {
return ctxt.assignAndReturnParser(_parserFactory.createParser(ctxt, src));
}

/**
* Factory method for constructing {@link JsonParser} that is properly
* wired to allow callbacks for deserialization: basically
* constructs a {@link ObjectReadContext} and then calls
* {@link TokenStreamFactory#createParser(ObjectReadContext,Path)}.
*
* @since 3.0
*/
public JsonParser createParser(Path src) throws JacksonException {
_assertNotNull("src", src);
DeserializationContextExt ctxt = _deserializationContext();
return ctxt.assignAndReturnParser(_parserFactory.createParser(ctxt, src));
}

/**
* Factory method for constructing {@link JsonParser} that is properly
* wired to allow callbacks for deserialization: basically
Expand Down Expand Up @@ -1202,6 +1218,25 @@ public <T> T readValue(File f) throws JacksonException
_considerFilter(_parserFactory.createParser(ctxt, f), false));
}

/**
* Method that binds content read from given {@link Path}
* using configuration of this reader.
* Value return is either newly constructed, or root value that
* was specified with {@link #withValueToUpdate(Object)}.
*
* @param p Path that contains content to read
*
* @since 3.0
*/
@SuppressWarnings("unchecked")
public <T> T readValue(Path p) throws JacksonException
{
_assertNotNull("p", p);
DeserializationContextExt ctxt = _deserializationContext();
return (T) _bindAndClose(ctxt,
_considerFilter(_parserFactory.createParser(ctxt, p), false));
}

/**
* Method that binds content read from given input source,
* using configuration of this reader.
Expand Down Expand Up @@ -1456,6 +1491,19 @@ public <T> MappingIterator<T> readValues(File src) throws JacksonException
_considerFilter(_parserFactory.createParser(ctxt, src), true));
}

/**
* Overloaded version of {@link #readValues(InputStream)}.
*
* @since 3.0
*/
public <T> MappingIterator<T> readValues(Path src) throws JacksonException
{
_assertNotNull("src", src);
DeserializationContextExt ctxt = _deserializationContext();
return _bindAndReadValues(ctxt,
_considerFilter(_parserFactory.createParser(ctxt, src), true));
}

/**
* Overloaded version of {@link #readValue(InputStream)}.
*<p>
Expand Down Expand Up @@ -1701,6 +1749,14 @@ protected InputStream _inputStream(File f) throws JacksonException {
}
}

protected InputStream _inputStream(Path p) throws JacksonException {
try {
return Files.newInputStream(p);
} catch (IOException e) {
throw WrappedIOException.construct(e);
}
}

protected final void _assertNotNull(String paramName, Object src) {
if (src == null){
throw new IllegalArgumentException(String.format("argument \"%s\" is null", paramName));
Expand Down
75 changes: 75 additions & 0 deletions src/main/java/com/fasterxml/jackson/databind/ObjectWriter.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.fasterxml.jackson.databind;

import java.io.*;
import java.nio.file.Path;
import java.text.*;
import java.util.Locale;
import java.util.Map;
Expand Down Expand Up @@ -569,6 +570,19 @@ public JsonGenerator createGenerator(File target, JsonEncoding enc) {
return _generatorFactory.createGenerator(_serializerProvider(), target, enc);
}

/**
* Factory method for constructing {@link JsonGenerator} that is properly
* wired to allow callbacks for serialization: basically
* constructs a {@link ObjectWriteContext} and then calls
* {@link TokenStreamFactory#createGenerator(ObjectWriteContext,Path,JsonEncoding)}.
*
* @since 3.0
*/
public JsonGenerator createGenerator(Path target, JsonEncoding enc) {
_assertNotNull("target", target);
return _generatorFactory.createGenerator(_serializerProvider(), target, enc);
}

/**
* Factory method for constructing {@link JsonGenerator} that is properly
* wired to allow callbacks for serialization: basically
Expand Down Expand Up @@ -622,6 +636,28 @@ public SequenceWriter writeValues(File target)
_generatorFactory.createGenerator(ctxt, target, JsonEncoding.UTF8), true);
}

/**
* Method for creating a {@link SequenceWriter} to write a sequence of root
* values using configuration of this {@link ObjectWriter}.
* Sequence is not surrounded by JSON array; some backend types may not
* support writing of such sequences as root level.
* Resulting writer needs to be {@link SequenceWriter#close()}d after all
* values have been written to ensure closing of underlying generator and
* output stream.
*
* @param target Target path to write value sequence to.
*
* @since 3.0
*/
public SequenceWriter writeValues(Path target)
throws JacksonException
{
_assertNotNull("target", target);
SerializationContextExt ctxt = _serializerProvider();
return _newSequenceWriter(ctxt, false,
_generatorFactory.createGenerator(ctxt, target, JsonEncoding.UTF8), true);
}

/**
* Method for creating a {@link SequenceWriter} to write a sequence of root
* values using configuration of this {@link ObjectWriter}.
Expand Down Expand Up @@ -707,6 +743,30 @@ public SequenceWriter writeValuesAsArray(File target)
_generatorFactory.createGenerator(ctxt, target, JsonEncoding.UTF8), true);
}

/**
* Method for creating a {@link SequenceWriter} to write an array of
* root-level values, using configuration of this {@link ObjectWriter}.
* Resulting writer needs to be {@link SequenceWriter#close()}d after all
* values have been written to ensure closing of underlying generator and
* output stream.
*<p>
* Note that the type to use with {@link ObjectWriter#forType(Class)} needs to
* be type of individual values (elements) to write and NOT matching array
* or {@link java.util.Collection} type.
*
* @param target Path to write token stream to
*
* @since 3.0
*/
public SequenceWriter writeValuesAsArray(Path target)
throws JacksonException
{
_assertNotNull("target", target);
SerializationContextExt ctxt = _serializerProvider();
return _newSequenceWriter(ctxt, true,
_generatorFactory.createGenerator(ctxt, target, JsonEncoding.UTF8), true);
}

/**
* Method for creating a {@link SequenceWriter} to write an array of
* root-level values, using configuration of this {@link ObjectWriter}.
Expand Down Expand Up @@ -891,6 +951,21 @@ public void writeValue(File target, Object value)
_generatorFactory.createGenerator(ctxt, target, JsonEncoding.UTF8), value);
}

/**
* Method that can be used to serialize any Java value as
* JSON output, written to Path provided.
*
* @since 3.0
*/
public void writeValue(Path target, Object value)
throws JacksonException
{
_assertNotNull("target", target);
SerializationContextExt ctxt = _serializerProvider();
_configAndWriteValue(ctxt,
_generatorFactory.createGenerator(ctxt, target, JsonEncoding.UTF8), value);
}

/**
* Method that can be used to serialize any Java value as
* JSON output, using output stream provided (using encoding
Expand Down
Loading

0 comments on commit b014bee

Please sign in to comment.