Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/**
* Copyright (C) 2014-2020 Philip Helger (www.helger.com)
* philip[at]helger[dot]com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.helger.json.serialize;
import java.io.File;
import java.io.InputStream;
import java.io.Reader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.WillClose;
import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.ThreadSafe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.helger.commons.ValueEnforcer;
import com.helger.commons.annotation.PresentForCodeCoverage;
import com.helger.commons.charset.CharsetHelper;
import com.helger.commons.concurrent.SimpleReadWriteLock;
import com.helger.commons.io.IHasInputStream;
import com.helger.commons.io.resource.FileSystemResource;
import com.helger.commons.io.stream.NonBlockingByteArrayInputStream;
import com.helger.commons.io.stream.NonBlockingStringReader;
import com.helger.commons.io.stream.NonClosingReader;
import com.helger.commons.io.stream.StreamHelper;
import com.helger.commons.state.ESuccess;
import com.helger.commons.state.EValidity;
import com.helger.json.IJson;
import com.helger.json.IJsonArray;
import com.helger.json.IJsonObject;
import com.helger.json.IJsonValue;
import com.helger.json.parser.IJsonParserCustomizeCallback;
import com.helger.json.parser.JsonParseException;
import com.helger.json.parser.JsonParser;
import com.helger.json.parser.errorhandler.IJsonParseExceptionCallback;
import com.helger.json.parser.errorhandler.LoggingJsonParseExceptionCallback;
import com.helger.json.parser.handler.CollectingJsonParserHandler;
import com.helger.json.parser.handler.DoNothingJsonParserHandler;
import com.helger.json.parser.handler.IJsonParserHandler;
/**
* This is the central user class for reading and parsing Json from different
* sources. This class reads full Json declarations only.
*
* @author Philip Helger
*/
@ThreadSafe
public final class JsonReader
{
public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
private static final Logger LOGGER = LoggerFactory.getLogger (JsonReader.class);
private static final SimpleReadWriteLock s_aRWLock = new SimpleReadWriteLock ();
// Use the LoggingJsonParseExceptionHandler for maximum backward compatibility
@GuardedBy ("s_aRWLock")
private static IJsonParseExceptionCallback s_aDefaultParseExceptionCallback = new LoggingJsonParseExceptionCallback ();
@PresentForCodeCoverage
private static final JsonReader s_aInstance = new JsonReader ();
private JsonReader ()
{}
/**
* @return The default Json parse exception handler. May not be
* null. For backwards compatibility reasons this is be
* default an instance of {@link LoggingJsonParseExceptionCallback}.
*/
@Nonnull
public static IJsonParseExceptionCallback getDefaultParseExceptionCallback ()
{
return s_aRWLock.readLockedGet ( () -> s_aDefaultParseExceptionCallback);
}
/**
* Set the default Json parse exception handler (for unrecoverable errors).
*
* @param aDefaultParseExceptionCallback
* The new default exception handler to be used. May not be
* null.
*/
public static void setDefaultParseExceptionCallback (@Nonnull final IJsonParseExceptionCallback aDefaultParseExceptionCallback)
{
ValueEnforcer.notNull (aDefaultParseExceptionCallback, "DefaultParseExceptionCallback");
s_aRWLock.writeLockedGet ( () -> s_aDefaultParseExceptionCallback = aDefaultParseExceptionCallback);
}
/**
* Simple JSON parse method taking only the most basic parameters.
*
* @param aReader
* The reader to read from. Should be buffered. May not be
* null.
* @param aParserHandler
* The parser handler. May not be null.
* @return {@link ESuccess}
*/
@Nonnull
public static ESuccess parseJson (@Nonnull @WillClose final Reader aReader, @Nonnull final IJsonParserHandler aParserHandler)
{
return parseJson (aReader, aParserHandler, (IJsonParserCustomizeCallback) null, (IJsonParseExceptionCallback) null);
}
/**
* Generic JSON parse method. Usually this is not to be called manually - call
* this only when you know what you are doing :)
*
* @param aReader
* The reader to read from. Should be buffered. May not be
* null.
* @param aParserHandler
* The parser handler. May not be null.
* @param aCustomizeCallback
* An optional {@link JsonParser} customization callback. May be
* null.
* @param aCustomExceptionCallback
* A custom handler for unrecoverable errors. May be null.
* @return {@link ESuccess}
*/
@Nonnull
public static ESuccess parseJson (@Nonnull @WillClose final Reader aReader,
@Nonnull final IJsonParserHandler aParserHandler,
@Nullable final IJsonParserCustomizeCallback aCustomizeCallback,
@Nullable final IJsonParseExceptionCallback aCustomExceptionCallback)
{
ValueEnforcer.notNull (aReader, "Reader");
ValueEnforcer.notNull (aParserHandler, "ParserHandler");
try
{
final JsonParser aParser = new JsonParser (aReader, aParserHandler);
if (aCustomizeCallback != null)
aCustomizeCallback.customizeJsonParser (aParser);
aParser.parse ();
return ESuccess.SUCCESS;
}
catch (final JsonParseException ex)
{
// Unrecoverable error
if (aCustomExceptionCallback != null)
aCustomExceptionCallback.onException (ex);
else
getDefaultParseExceptionCallback ().onException (ex);
return ESuccess.FAILURE;
}
finally
{
StreamHelper.close (aReader);
}
}
/**
* Validate a JSON without building the tree in memory.
*
* @param aReader
* The reader to read from. Should be buffered. May not be
* null.
* @return {@link EValidity#VALID} if the JSON is valid,
* {@link EValidity#INVALID} otherwise.
*/
@Nonnull
private static EValidity _validateJson (@Nonnull @WillClose final Reader aReader)
{
// Force silent parsing :)
final ESuccess eSuccess = parseJson (aReader, new DoNothingJsonParserHandler (), (IJsonParserCustomizeCallback) null, ex -> {});
return EValidity.valueOf (eSuccess.isSuccess ());
}
/**
* Check if the passed File can be resembled to valid Json content. This is
* accomplished by fully parsing the Json file each time the method is called.
* This consumes less memory than calling any of the
* read... methods and checking for a non-null
* result.
*
* @param aFile
* The file to be parsed. May not be null.
* @return true if the file can be parsed without error,
* false if not
* @deprecated Since v9.3.3 - use {@link #builder()} instead.
*/
@Deprecated
public static boolean isValidJson (@Nonnull final File aFile)
{
return isValidJson (aFile, DEFAULT_CHARSET);
}
/**
* Check if the passed File can be resembled to valid Json content. This is
* accomplished by fully parsing the Json file each time the method is called.
* This consumes less memory than calling any of the
* read... methods and checking for a non-null
* result.
*
* @param aFile
* The file to be parsed. May not be null.
* @param aFallbackCharset
* The charset to be used for reading the Json file in case no BOM is
* present. May not be null.
* @return true if the file can be parsed without error,
* false if not
* @deprecated Since v9.3.3 - use {@link #builder()} instead.
*/
@Deprecated
public static boolean isValidJson (@Nonnull final File aFile, @Nonnull final Charset aFallbackCharset)
{
return isValidJson (new FileSystemResource (aFile), aFallbackCharset);
}
/**
* Check if the passed Path can be resembled to valid Json content. This is
* accomplished by fully parsing the Json file each time the method is called.
* This consumes less memory than calling any of the
* read... methods and checking for a non-null
* result.
*
* @param aPath
* The file to be parsed. May not be null.
* @return true if the file can be parsed without error,
* false if not
* @deprecated Since v9.3.3 - use {@link #builder()} instead.
*/
@Deprecated
public static boolean isValidJson (@Nonnull final Path aPath)
{
return isValidJson (aPath, DEFAULT_CHARSET);
}
/**
* Check if the passed Path can be resembled to valid Json content. This is
* accomplished by fully parsing the Json file each time the method is called.
* This consumes less memory than calling any of the
* read... methods and checking for a non-null
* result.
*
* @param aPath
* The file to be parsed. May not be null.
* @param aFallbackCharset
* The charset to be used for reading the Json file in case no BOM is
* present. May not be null.
* @return true if the file can be parsed without error,
* false if not
* @deprecated Since v9.3.3 - use {@link #builder()} instead.
*/
@Deprecated
public static boolean isValidJson (@Nonnull final Path aPath, @Nonnull final Charset aFallbackCharset)
{
return isValidJson (new FileSystemResource (aPath), aFallbackCharset);
}
/**
* Check if the passed input stream can be resembled to valid Json content.
* This is accomplished by fully parsing the Json file each time the method is
* called. This consumes less memory than calling any of the
* read... methods and checking for a non-null
* result.
*
* @param aISP
* The resource to be parsed. May not be null.
* @return true if the file can be parsed without error,
* false if not
* @deprecated Since v9.3.3 - use {@link #builder()} instead.
*/
@Deprecated
public static boolean isValidJson (@Nonnull final IHasInputStream aISP)
{
return isValidJson (aISP, DEFAULT_CHARSET);
}
/**
* Check if the passed input stream can be resembled to valid Json content.
* This is accomplished by fully parsing the Json file each time the method is
* called. This consumes less memory than calling any of the
* read... methods and checking for a non-null
* result.
*
* @param aISP
* The resource to be parsed. May not be null.
* @param aFallbackCharset
* The charset to be used for reading the Json file in case no BOM is
* present. May not be null.
* @return true if the file can be parsed without error,
* false if not
* @deprecated Since v9.3.3 - use {@link #builder()} instead.
*/
@Deprecated
public static boolean isValidJson (@Nonnull final IHasInputStream aISP, @Nonnull final Charset aFallbackCharset)
{
ValueEnforcer.notNull (aISP, "InputStreamProvider");
ValueEnforcer.notNull (aFallbackCharset, "FallbackCharset");
final InputStream aIS = aISP.getInputStream ();
if (aIS == null)
{
if (LOGGER.isWarnEnabled ())
LOGGER.warn ("Failed to open Json InputStream from " + aISP);
return false;
}
return isValidJson (aIS, aFallbackCharset);
}
/**
* Check if the passed input stream can be resembled to valid Json content.
* This is accomplished by fully parsing the Json file each time the method is
* called using the default charset. This consumes less memory than
* calling any of the read... methods and checking for a non-
* null result.
*
* @param aIS
* The input stream to use. Is automatically closed. May not be
* null.
* @return true if the Json is valid according to the version,
* false if not
* @deprecated Since v9.3.3 - use {@link #builder()} instead.
*/
@Deprecated
public static boolean isValidJson (@Nonnull @WillClose final InputStream aIS)
{
return isValidJson (aIS, DEFAULT_CHARSET);
}
/**
* Check if the passed input stream can be resembled to valid Json content.
* This is accomplished by fully parsing the Json file each time the method is
* called. This consumes less memory than calling any of the
* read... methods and checking for a non-null
* result.
*
* @param aIS
* The input stream to use. Is automatically closed. May not be
* null.
* @param aFallbackCharset
* The charset to be used in case no BOM is present. May not be
* null.
* @return true if the Json is valid according to the version,
* false if not
* @deprecated Since v9.3.3 - use {@link #builder()} instead.
*/
@Deprecated
public static boolean isValidJson (@Nonnull @WillClose final InputStream aIS, @Nonnull final Charset aFallbackCharset)
{
ValueEnforcer.notNull (aIS, "InputStream");
ValueEnforcer.notNull (aFallbackCharset, "FallbackCharset");
try
{
final Reader aReader = CharsetHelper.getReaderByBOM (aIS, aFallbackCharset);
return isValidJson (aReader);
}
finally
{
StreamHelper.close (aIS);
}
}
/**
* Check if the passed String can be resembled to valid Json content. This is
* accomplished by fully parsing the Json file each time the method is called.
* This consumes less memory than calling any of the
* read... methods and checking for a non-null
* result.
*
* @param sJson
* The Json string to scan. May not be null.
* @return true if the Json is valid according to the version,
* false if not
* @deprecated Since v9.3.3 - use {@link #builder()} instead.
*/
@Deprecated
public static boolean isValidJson (@Nonnull final String sJson)
{
ValueEnforcer.notNull (sJson, "Json");
return isValidJson (new NonBlockingStringReader (sJson));
}
/**
* Check if the passed reader can be resembled to valid Json content. This is
* accomplished by fully parsing the Json each time the method is called. This
* consumes less memory than calling any of the read...
* methods and checking for a non-null result.
*
* @param aReader
* The reader to use. May not be null.
* @return true if the Json is valid according to the version,
* false if not
* @deprecated Since v9.3.3 - use {@link #builder()} instead.
*/
@Deprecated
public static boolean isValidJson (@Nonnull @WillClose final Reader aReader)
{
ValueEnforcer.notNull (aReader, "Reader");
return _validateJson (StreamHelper.getBuffered (aReader)).isValid ();
}
/**
* Main reading of the JSON
*
* @param aReader
* The reader to read from. Should be buffered. May not be
* null.
* @param aCustomizeCallback
* An optional {@link JsonParser} customization callback. May be
* null.
* @param aCustomExceptionCallback
* A custom handler for unrecoverable errors. May be null.
* @return null if parsing failed with an unrecoverable error
* (and no throwing exception handler is used), or null
* if a recoverable error occurred or non-null if parsing
* succeeded.
* @since 9.1.8
*/
@Nullable
public static IJson readJson (@Nonnull @WillClose final Reader aReader,
@Nullable final IJsonParserCustomizeCallback aCustomizeCallback,
@Nullable final IJsonParseExceptionCallback aCustomExceptionCallback)
{
final CollectingJsonParserHandler aHandler = new CollectingJsonParserHandler ();
if (parseJson (aReader, aHandler, aCustomizeCallback, aCustomExceptionCallback).isFailure ())
return null;
return aHandler.getJson ();
}
/**
* Read the Json from the passed String using a character stream. An
* eventually contained @charset rule is ignored.
*
* @param sJson
* The source string containing the Json to be parsed. May not be
* null.
* @return null if reading failed, the Json declarations
* otherwise.
*/
@Nullable
public static IJson readFromString (@Nonnull final String sJson)
{
return builder ().setSource (sJson).read ();
}
/**
* Read the Json from the passed String using a character stream.
*
* @param sJson
* The source string containing the Json to be parsed. May not be
* null.
* @param aCustomExceptionHandler
* An optional custom exception handler that can be used to collect the
* unrecoverable parsing errors. May be null.
* @return null if reading failed, the Json declarations
* otherwise.
* @deprecated Since v9.3.3 - use {@link #builder()} instead.
*/
@Nullable
@Deprecated
public static IJson readFromString (@Nonnull final String sJson, @Nullable final IJsonParseExceptionCallback aCustomExceptionHandler)
{
return builder ().setSource (sJson).setCustomExceptionCallback (aCustomExceptionHandler).read ();
}
/**
* Read the Json from the passed File using the default charset.
*
* @param aFile
* The file containing the Json to be parsed. May not be
* null.
* @return null if reading failed, the Json declarations
* otherwise.
* @deprecated Since v9.3.3 - use {@link #builder()} instead.
*/
@Nullable
@Deprecated
public static IJson readFromFile (@Nonnull final File aFile)
{
return builder ().setSource (aFile).read ();
}
/**
* Read the Json from the passed File.
*
* @param aFile
* The file containing the Json to be parsed. May not be
* null.
* @param aFallbackCharset
* The charset to be used in case no is BOM is present. May not be
* null.
* @return null if reading failed, the Json declarations
* otherwise.
* @deprecated Since v9.3.3 - use {@link #builder()} instead.
*/
@Nullable
@Deprecated
public static IJson readFromFile (@Nonnull final File aFile, @Nonnull final Charset aFallbackCharset)
{
return builder ().setSource (aFile, aFallbackCharset).read ();
}
/**
* Read the Json from the passed File.
*
* @param aFile
* The file containing the Json to be parsed. May not be
* null.
* @param aFallbackCharset
* The charset to be used in case no BOM is present. May not be
* null.
* @param aCustomExceptionHandler
* An optional custom exception handler that can be used to collect the
* unrecoverable parsing errors. May be null.
* @return null if reading failed, the Json declarations
* otherwise.
* @deprecated Since v9.3.3 - use {@link #builder()} instead.
*/
@Nullable
@Deprecated
public static IJson readFromFile (@Nonnull final File aFile,
@Nonnull final Charset aFallbackCharset,
@Nullable final IJsonParseExceptionCallback aCustomExceptionHandler)
{
return builder ().setSource (aFile, aFallbackCharset).setCustomExceptionCallback (aCustomExceptionHandler).read ();
}
/**
* Read the Json from the passed Path using the default charset.
*
* @param aPath
* The file containing the Json to be parsed. May not be
* null.
* @return null if reading failed, the Json declarations
* otherwise.
* @deprecated Since v9.3.3 - use {@link #builder()} instead.
*/
@Nullable
@Deprecated
public static IJson readFromPath (@Nonnull final Path aPath)
{
return builder ().setSource (aPath).read ();
}
/**
* Read the Json from the passed Path.
*
* @param aPath
* The file containing the Json to be parsed. May not be
* null.
* @param aFallbackCharset
* The charset to be used in case no is BOM is present. May not be
* null.
* @return null if reading failed, the Json declarations
* otherwise.
* @deprecated Since v9.3.3 - use {@link #builder()} instead.
*/
@Nullable
@Deprecated
public static IJson readFromPath (@Nonnull final Path aPath, @Nonnull final Charset aFallbackCharset)
{
return builder ().setSource (aPath, aFallbackCharset).read ();
}
/**
* Read the Json from the passed Path.
*
* @param aPath
* The file containing the Json to be parsed. May not be
* null.
* @param aFallbackCharset
* The charset to be used in case no BOM is present. May not be
* null.
* @param aCustomExceptionHandler
* An optional custom exception handler that can be used to collect the
* unrecoverable parsing errors. May be null.
* @return null if reading failed, the Json declarations
* otherwise.
* @deprecated Since v9.3.3 - use {@link #builder()} instead.
*/
@Nullable
@Deprecated
public static IJson readFromPath (@Nonnull final Path aPath,
@Nonnull final Charset aFallbackCharset,
@Nullable final IJsonParseExceptionCallback aCustomExceptionHandler)
{
return builder ().setSource (aPath, aFallbackCharset).setCustomExceptionCallback (aCustomExceptionHandler).read ();
}
/**
* Read the Json from the passed {@link IHasInputStream} using the default
* charset.
*
* @param aISP
* The input stream provider to use. May not be null.
* @return null if reading failed, the Json declarations
* otherwise.
* @deprecated Since v9.3.3 - use {@link #builder()} instead.
*/
@Nullable
@Deprecated
public static IJson readFromStream (@Nonnull final IHasInputStream aISP)
{
return builder ().setSource (aISP).read ();
}
/**
* Read the Json from the passed {@link IHasInputStream}.
*
* @param aISP
* The input stream provider to use. May not be null.
* @param aFallbackCharset
* The charset to be used if no BOM is present. May not be
* null.
* @return null if reading failed, the Json declarations
* otherwise.
* @deprecated Since v9.3.3 - use {@link #builder()} instead.
*/
@Nullable
@Deprecated
public static IJson readFromStream (@Nonnull final IHasInputStream aISP, @Nonnull final Charset aFallbackCharset)
{
return builder ().setSource (aISP, aFallbackCharset).read ();
}
/**
* Read the Json from the passed {@link IHasInputStream}.
*
* @param aISP
* The input stream to use. May not be null.
* @param aFallbackCharset
* The charset to be used in case no BOM is present. May not be
* null.
* @param aCustomExceptionHandler
* An optional custom exception handler that can be used to collect the
* unrecoverable parsing errors. May be null.
* @return null if reading failed, the Json declarations
* otherwise.
* @deprecated Since v9.3.3 - use {@link #builder()} instead.
*/
@Nullable
@Deprecated
public static IJson readFromStream (@Nonnull final IHasInputStream aISP,
@Nonnull final Charset aFallbackCharset,
@Nullable final IJsonParseExceptionCallback aCustomExceptionHandler)
{
return builder ().setSource (aISP, aFallbackCharset).setCustomExceptionCallback (aCustomExceptionHandler).read ();
}
/**
* Read the Json from the passed {@link InputStream} using the default
* charset.
*
* @param aIS
* The input stream to use. May not be null.
* @return null if reading failed, the Json declarations
* otherwise.
* @deprecated Since v9.3.3 - use {@link #builder()} instead.
*/
@Nullable
@Deprecated
public static IJson readFromStream (@Nonnull final InputStream aIS)
{
return builder ().setSource (aIS).read ();
}
/**
* Read the Json from the passed {@link InputStream}.
*
* @param aIS
* The input stream to use. May not be null.
* @param aFallbackCharset
* The charset to be used if no BOM is present. May not be
* null.
* @return null if reading failed, the Json declarations
* otherwise.
* @deprecated Since v9.3.3 - use {@link #builder()} instead.
*/
@Nullable
@Deprecated
public static IJson readFromStream (@Nonnull final InputStream aIS, @Nonnull final Charset aFallbackCharset)
{
return builder ().setSource (aIS, aFallbackCharset).read ();
}
/**
* Read the Json from the passed {@link InputStream}.
*
* @param aIS
* The input stream to use. May not be null.
* @param aFallbackCharset
* The charset to be used in case no BOM is present. May not be
* null.
* @param aCustomExceptionCallback
* An optional custom exception handler that can be used to collect the
* unrecoverable parsing errors. May be null.
* @return null if reading failed, the Json declarations
* otherwise.
* @deprecated Since v9.3.3 - use {@link #builder()} instead.
*/
@Nullable
@Deprecated
public static IJson readFromStream (@Nonnull final InputStream aIS,
@Nonnull final Charset aFallbackCharset,
@Nullable final IJsonParseExceptionCallback aCustomExceptionCallback)
{
try
{
return builder ().setSource (aIS, aFallbackCharset).setCustomExceptionCallback (aCustomExceptionCallback).read ();
}
finally
{
StreamHelper.close (aIS);
}
}
/**
* Read the Json from the passed {@link Reader}.
*
* @param aReader
* The reader to use. May not be null.
* @return null if reading failed, the Json declarations
* otherwise.
* @deprecated Since v9.3.3 - use {@link #builder()} instead.
*/
@Nullable
@Deprecated
public static IJson readFromReader (@Nonnull final Reader aReader)
{
return builder ().setSource (aReader).read ();
}
/**
* Read the Json from the passed {@link Reader}.
*
* @param aReader
* The reader to use. May not be null.
* @param aCustomExceptionCallback
* An optional custom exception handler that can be used to collect the
* unrecoverable parsing errors. May be null.
* @return null if reading failed, the Json declarations
* otherwise.
* @deprecated Since v9.3.3 - use {@link #builder()} instead.
*/
@Nullable
@Deprecated
public static IJson readFromReader (@Nonnull final Reader aReader, @Nullable final IJsonParseExceptionCallback aCustomExceptionCallback)
{
return builder ().setSource (aReader).setCustomExceptionCallback (aCustomExceptionCallback).read ();
}
/**
* @return Create a new {@link Builder} instance.
* @since 9.3.3
*/
@Nonnull
public static Builder builder ()
{
return new Builder ();
}
/**
* @return Create a new {@link Builder} instance that is configured to read
* multiple instances. Never null. Use
* {@link Builder#setSource(Reader)} to ensure this works. When using
* {@link InputStream} or the like, there is too much pre read.
* @since 9.3.8
*/
@Nonnull
public static Builder builderMultiObject ()
{
return builder ().setDontCloseSource (true).setUseBufferedReader (false).setCustomizeCallback (p -> p.setCheckForEOI (false));
}
/**
* Factory for JSon reader for different sources. Use {@link #isValidJson()}
* to check if the JSON is syntactically correct and {@link #read()} to
* convert it to a parsed object.
*
* @author Philip Helger
* @since 9.3.3
*/
public static class Builder implements AutoCloseable
{
private boolean m_bDontCloseSource = false;
private boolean m_bUseBufferedReader = true;
private Reader m_aReader;
private IJsonParserCustomizeCallback m_aCustomizeCallback;
private IJsonParseExceptionCallback m_aCustomeExceptionCallback;
public Builder ()
{}
public void close ()
{
StreamHelper.close (m_aReader);
}
/**
* Set avoid closing the source stream. This may be helpful when reading
* multiple objects. Default is false.
*
* @param bDontCloseSource
* true to not close the source
* @return this for chaining
* @since 9.3.8
*/
@Nonnull
public Builder setDontCloseSource (final boolean bDontCloseSource)
{
m_bDontCloseSource = bDontCloseSource;
return this;
}
/**
* Use a buffered reader or not. If you want to read multiple instances from
* a simple {@link InputStream} this should be set to false.
* Default is true.
*
* @param bUseBufferedReader
* true to use it, false to use a
* non-buffered reader.
* @return this for chaining
* @since 9.3.8
*/
@Nonnull
public Builder setUseBufferedReader (final boolean bUseBufferedReader)
{
m_bUseBufferedReader = bUseBufferedReader;
return this;
}
/**
* Use a constant JSON string as source
*
* @param sJson
* The JSON String to be parser. May not be null.
* @return this for chaining
*/
@Nonnull
public Builder setSource (@Nonnull final String sJson)
{
ValueEnforcer.notNull (sJson, "Json");
return setSource (new NonBlockingStringReader (sJson));
}
/**
* Use a {@link File} as JSON source. Assumes UTF-8 as fallback charset.
*
* @param aFile
* The File containing the JSON to be parsed. May not be
* null.
* @return this for chaining
*/
@Nonnull
public Builder setSource (@Nonnull final File aFile)
{
return setSource (aFile, JsonReader.DEFAULT_CHARSET);
}
/**
* Use a {@link File} as JSON source with a custom fallback charset.
*
* @param aFile
* The File containing the JSON to be parsed. May not be
* null.
* @param aFallbackCharset
* The fallback charset to be used. May not be null.
* @return this for chaining
*/
@Nonnull
public Builder setSource (@Nonnull final File aFile, @Nonnull final Charset aFallbackCharset)
{
ValueEnforcer.notNull (aFile, "File");
ValueEnforcer.notNull (aFallbackCharset, "FallbackCharset");
return setSource (new FileSystemResource (aFile), aFallbackCharset);
}
/**
* Use a {@link Path} as JSON source. Assumes UTF-8 as fallback charset.
*
* @param aPath
* The File containing the JSON to be parsed. May not be
* null.
* @return this for chaining
*/
@Nonnull
public Builder setSource (@Nonnull final Path aPath)
{
return setSource (aPath, JsonReader.DEFAULT_CHARSET);
}
/**
* Use a {@link Path} as JSON source with a custom fallback charset.
*
* @param aPath
* The File containing the JSON to be parsed. May not be
* null.
* @param aFallbackCharset
* The fallback charset to be used. May not be null.
* @return this for chaining
*/
@Nonnull
public Builder setSource (@Nonnull final Path aPath, @Nonnull final Charset aFallbackCharset)
{
ValueEnforcer.notNull (aPath, "Path");
ValueEnforcer.notNull (aFallbackCharset, "FallbackCharset");
return setSource (new FileSystemResource (aPath), aFallbackCharset);
}
/**
* Use a byte array as JSON source. Assumes UTF-8 as fallback charset.
*
* @param aBytes
* The byte array containing the JSON to be parsed. May not be
* null.
* @return this for chaining
* @since 9.3.4
*/
@Nonnull
public Builder setSource (@Nonnull final byte [] aBytes)
{
return setSource (aBytes, JsonReader.DEFAULT_CHARSET);
}
/**
* Use a byte array as JSON source with a custom fallback charset.
*
* @param aBytes
* The byte array containing the JSON to be parsed. May not be
* null.
* @param aFallbackCharset
* The fallback charset to be used. May not be null.
* @return this for chaining
* @since 9.3.4
*/
@Nonnull
public Builder setSource (@Nonnull final byte [] aBytes, @Nonnull final Charset aFallbackCharset)
{
ValueEnforcer.notNull (aBytes, "Bytes");
ValueEnforcer.notNull (aFallbackCharset, "FallbackCharset");
return setSource (new NonBlockingByteArrayInputStream (aBytes), aFallbackCharset);
}
/**
* Use an InputStream provider as JSON source. Assumes UTF-8 as fallback
* charset.
*
* @param aISP
* The InputStream provider to be used. May not be null.
* @return this for chaining
*/
@Nonnull
public Builder setSource (@Nonnull final IHasInputStream aISP)
{
return setSource (aISP, JsonReader.DEFAULT_CHARSET);
}
/**
* Use an InputStream provider as JSON source with a custom fallback
* charset.
*
* @param aISP
* The InputStream provider to be used. May not be null.
* @param aFallbackCharset
* The fallback charset to be used. May not be null.
* @return this for chaining
*/
@Nonnull
public Builder setSource (@Nonnull final IHasInputStream aISP, @Nonnull final Charset aFallbackCharset)
{
ValueEnforcer.notNull (aISP, "InputStreamProvider");
ValueEnforcer.notNull (aFallbackCharset, "FallbackCharset");
final InputStream aIS = aISP.getInputStream ();
if (aIS != null)
setSource (aIS, aFallbackCharset);
return this;
}
/**
* Use an {@link InputStream} as JSON source. Assumes UTF-8 as fallback
* charset.
*
* @param aIS
* The InputStream to be used. May not be null.
* @return this for chaining
*/
@Nonnull
public Builder setSource (@Nonnull @WillClose final InputStream aIS)
{
return setSource (aIS, JsonReader.DEFAULT_CHARSET);
}
/**
* Use an {@link InputStream} as JSON source with a custom fallback charset.
*
* @param aIS
* The InputStream to be used. May not be null.
* @param aFallbackCharset
* The fallback charset to be used. May not be null.
* @return this for chaining
*/
@Nonnull
public Builder setSource (@Nonnull @WillClose final InputStream aIS, @Nonnull final Charset aFallbackCharset)
{
ValueEnforcer.notNull (aIS, "InputStream");
ValueEnforcer.notNull (aFallbackCharset, "FallbackCharset");
final Reader aReader = CharsetHelper.getReaderByBOM (aIS, aFallbackCharset);
if (aReader != null)
return setSource (aReader);
return this;
}
/**
* Set a {@link Reader} as JSON source. Internally it is ensured, that it is
* buffered.
*
* @param aReader
* The Reader to be used. May not be null.
* @return this for chaining
*/
@Nonnull
public Builder setSource (@Nonnull @WillClose final Reader aReader)
{
ValueEnforcer.notNull (aReader, "Reader");
if (m_aReader != null)
LOGGER.warn ("Another source is already present - this may cause a resource leak, because the old source is not closed automatically");
m_aReader = aReader;
// Use buffered?
if (m_bUseBufferedReader)
m_aReader = StreamHelper.getBuffered (m_aReader);
// Don't close?
if (m_bDontCloseSource)
m_aReader = new NonClosingReader (m_aReader);
return this;
}
/**
* Set the optional customizing callback.
*
* @param aCustomizeCallback
* The customizing callback to be used. May be null.
* @return this for chaining
*/
@Nonnull
public Builder setCustomizeCallback (@Nullable final IJsonParserCustomizeCallback aCustomizeCallback)
{
m_aCustomizeCallback = aCustomizeCallback;
return this;
}
/**
* Set the optional exception callback.
*
* @param aCustomExceptionCallback
* The exception callback to be used. May be null.
* @return this for chaining
*/
@Nonnull
public Builder setCustomExceptionCallback (@Nullable final IJsonParseExceptionCallback aCustomExceptionCallback)
{
m_aCustomeExceptionCallback = aCustomExceptionCallback;
return this;
}
/**
* @return true if a source is present, false if
* not.
* @since 9.4.0
*/
public boolean hasSource ()
{
return m_aReader != null;
}
/**
* Check if the provided source is syntactically correct JSON or not,
* without building an object structure.
*
* @return true if it is valid JSON, false if not
*/
public boolean isValidJson ()
{
if (m_aReader == null)
throw new IllegalStateException ("No source is set.");
return JsonReader.parseJson (m_aReader, new DoNothingJsonParserHandler (), m_aCustomizeCallback, m_aCustomeExceptionCallback)
.isSuccess ();
}
/**
* @return The parsed JSON from the specified source. May be
* null if parsing fails. This method should be invoked
* only once per instance, because the underlying reader is not
* guaranteed to be re-openable.
*/
@Nullable
public IJson read ()
{
if (m_aReader == null)
throw new IllegalStateException ("No source is set.");
return JsonReader.readJson (m_aReader, m_aCustomizeCallback, m_aCustomeExceptionCallback);
}
/**
* @return The parsed JSON array from the specified source. May be
* null if parsing fails or if the parsed JSON is not
* an array. This method should be invoked only once per instance,
* because the underlying reader is not guaranteed to be
* re-openable.
* @since 9.3.5
*/
@Nullable
public IJsonArray readAsArray ()
{
final IJson aJson = read ();
return aJson == null ? null : aJson.getAsArray ();
}
/**
* @return The parsed JSON array from the specified source. May be
* null if parsing fails or if the parsed JSON is not
* an object. This method should be invoked only once per instance,
* because the underlying reader is not guaranteed to be
* re-openable.
* @since 9.3.5
*/
@Nullable
public IJsonObject readAsObject ()
{
final IJson aJson = read ();
return aJson == null ? null : aJson.getAsObject ();
}
/**
* @return The parsed JSON array from the specified source. May be
* null if parsing fails or if the parsed JSON is not a
* value. This method should be invoked only once per instance,
* because the underlying reader is not guaranteed to be
* re-openable.
* @since 9.3.5
*/
@Nullable
public IJsonValue readAsValue ()
{
final IJson aJson = read ();
return aJson == null ? null : aJson.getAsValue ();
}
}
}