All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.dylemma.spac.json.JacksonSource.scala Maven / Gradle / Ivy

The newest version!
package io.dylemma.spac
package json

import com.fasterxml.jackson.core.{JsonFactory, JsonParser => JacksonParser}
import io.dylemma.spac.json.impl.JsonStackFixer

import java.io.{File, InputStream, Reader}

/** Provides helpers for creating `fs2.Stream` and `Iterator` instances of `JsonEvent` from various underlying event sources,
  * using the Jackson library as the underlying event parser.
  *
  * The helpers in this object operate in terms of the `IntoJacksonJsonParser` typeclass, which defines logic for
  * using a `source` value to construct a Jackson JsonParser in a Resource. From there, the helpers take care of
  * converting the jackson parser/event model to the spac JsonEvent model.
  *
  * For example:
  * {{{
  *    val file = new File("./stuff.json")
  *    val jsonStream: Stream[IO, JsonEvent] = JacksonSource[IO](file)
  * }}}
  *
  * @group support */
object JacksonSource {

	/** Default `JsonFactory` used by the helpers in this object when interfacing with the `IntoJacksonJsonParser` typeclass
	  * to create the underlying Jackson JsonParsers.
	  *
	  * This is a `new JsonFactory` with no additional modifications.
	  */
	lazy val defaultFactory: JsonFactory = new JsonFactory

	/** Wrap an existing Jackson JsonParser as a single-use source of JsonEvents.
	  *
	  * The source will *not* attempt to close the underlying parser.
	  *
	  * @param jacksonParser A Jackson JsonParser
	  * @return A single-use JSON event source
	  */
	def apply(jacksonParser: JacksonParser): Source[JsonEvent] = {
		Source.singleUse(JsonStackFixer.transform(new WrappedJacksonParser(jacksonParser)))
	}

	/** Wrap a string of raw JSON as a source of JsonEvents
	  *
	  * @param rawJson A string containing raw JSON
	  * @param factory A Jackson JsonFactory used to construct the underlying JsonParser for the string
	  * @return A reusable JSON event source
	  */
	def fromString(rawJson: String, factory: JsonFactory = defaultFactory): Source[JsonEvent] = Source.defer {
		apply(factory.createParser(rawJson).disable(JacksonParser.Feature.AUTO_CLOSE_SOURCE))
	}

	/** Wrap a `Reader` as a single-use source of JsonEvents.
	  *
	  * The Source will *not* attempt to close the reader.
	  *
	  * @param reader A Reader over characters of raw JSON
	  * @param factory A Jackson JsonFactory used to construct the underlying JsonParser for the string
	  * @return A single-use JSON event source
	  */
	def fromReader(reader: Reader, factory: JsonFactory = defaultFactory): Source[JsonEvent] = {
		apply(factory.createParser(reader).disable(JacksonParser.Feature.AUTO_CLOSE_SOURCE))
	}

	/** Wrap an InputStream as a single-use source of JsonEvents.
	  *
	  * The Source will *not* attempt to close the input stream.
	  *
	  * @param stream An InputStream over raw JSON bytes
	  * @param factory A Jackson JsonFactory used to construct the underlying JsonParser for the string
	  * @return A single-use JSON event source
	  */
	def fromInputStream(stream: InputStream, factory: JsonFactory = defaultFactory): Source[JsonEvent] = {
		apply(factory.createParser(stream).disable(JacksonParser.Feature.AUTO_CLOSE_SOURCE))
	}

	/** Creates a new Source that reads JsonEvents from the given file.
	  *
	  * @param file A JSON file
	  * @param factory A Jackson JsonFactory used to construct the underlying JsonParser for the string
	  * @return A reusable JSON event source
	  */
	def fromFile(file: File, factory: JsonFactory = defaultFactory): Source[JsonEvent] = () => {
		val parser = factory.createParser(file)
		val (itr, _) = apply(parser).open() // underlying source's close is a no-op, so don't bother capturing it
		val close = () => parser.close()
		itr -> close
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy