Skip to content
Dylan Halperin edited this page May 9, 2021 · 6 revisions

A lot changed in 0.9. Some huge features were implemented, but doing so required rewriting most of the library from the ground up. Some classes/methods are gone, some are refactored, some are renamed. I tried to ease the pain by providing old values/aliases as deprecated versions of themselves, but coverage isn't 100%.

The Most Influential Changes

These are the changes that will almost-certainly break something for you.

  • Any XML-prefixed class or value has been renamed to use Xml (with lower-case "ml")
  • XMLSplitter(...) becomes Splitter.xml(...)
  • JsonSplitter(...) becomes Splitter.json(...)
  • Combining parsers is no longer done via (p1 and p2 and p3).as(f). Instead, import cats.syntax.apply._ and do (p1, p2, p3).mapN(f). The and and ~ methods on Parser are completely gone. The ParserCombination classes are completely gone.

XML/JSON Renames and Refactors

  • All of the XML-prefixed classes and type aliases now use Xml as the prefix instead. The old aliases are available but deprecated.
    • XMLParser renamed to XmlParser
    • XMLTransformer renamed to `XmlTransformer
    • XMLSplitter renamed to XmlSplitter
    • XMLContextMatcher renamed to XmlContextMatcher
  • SingleElementContextMatcher renamed to ElemContextMatcher
  • Most of the XML* and Json* classes are now only type aliases; their member methods have been moved to *Ops implicit classes defined in the respective xml and json package objects.
  • The "companion" objects for XMLParser and XMLSplitter no longer exist. The functionality from those objects has moved to implicit classes that wrap the new ParserApplyWithBoundInput and SplitterApplyWithBoundInput classes, which are intermediate objects that you get from Parser.apply[In] and Splitter.apply[In] respectively. At a source level, it should be pretty much the same as before, aside from the XML->Xml rename (i.e. you still call XmlParser.forText).
    • XMLSplitter.apply replaced with Splitter.xml
    • JsonSplitter.apply replaced with Splitter.json
  • The xml and json package objects are now the only source of implicits that you used to be able to import individually from objects like Implicits or ContextMatcherSyntax. The scaladoc for those packages breaks things down into categories so it should be relatively easy to follow when reading the docs.
  • XMLSplitter#asText renamed to text. asText is still available, but deprecated.
  • Removed the first, firstOption, firstNotNull, asListOf helpers from the Splitter classes. They existed as a convenience which allowed you to express "how many" of the substreams you wanted to consume, before attaching a parser to those substreams. This ended up being confusing since it allowed you to do the same thing in multiple ways, without really removing any meaningful amount of boilerplate. If you had code like XMLSplitter(...).first.as[T], rearrange it to Splitter.xml(...).as[T].parseFirst.
  • XmlParser.forMandatoryAttribute is still available, but now there's a shorter alternative alias: XmlParser.attr.
  • XmlParser.forOptionalAttribute is still available, but now there's a shorter alternative alias: XmlParser.attrOpt.
  • The XmlParser attribute-parser constructors now accept a generic [N: AsQName] instead of having overloads for String and javax's QName class.

Splitter Changes

  • Splitter's as now takes specifically a Parser[In, Out] instead of a Context => Parser[In, Out]. Parser is no longer a function that returns itself.
  • Splitter's map now takes specifically a Context => Parser[In, Out]. If you were passing a Parser instead of a function, use the new joinBy method.

Transformer Changes

  • Transformer's parseForeach renamed to parseTap
  • Transformer's parseFirstOption renamed to parseFirstOpt
  • Transformer's parallel renamed to merge
  • Transformer's parallelEither renamed to mergeEither
  • Transformer's parseWith renamed to into.
    • Removed the parseWith signature that took a "debug name" - use .into(...).withName(...) instead
    • Deprecated the >> operator version of this method
  • Transformer's andThen renamed to through
    • Deprecated the >> operator version of this method
  • Transformer's sink renamed to drain
  • Some of the less-common Transformer member methods have been removed in favor of using .through(Transformer.thatKindOfMethod)
    • .drop(n) becomes .through(Transformer.drop(n))
    • .dropWhile(f) becomes .through(Transformer.dropWhile(f))
    • .take(n) becomes .through(Transformer.take(n))
    • .takeWhile(f) becomes .through(Transformer.takeWhile(f))
    • .withSideEffect(f) becomes .through(Transformer.tap(f))
  • Transformer's flatten removed (from both the trait and the companion object). Use mapFlatten(identity) instead
  • Transformer's wrapSafe and unwrapSafe are removed (from both the trait and the companion object). Catching errors should be the responsibility of the underlying Parser, not the Transformer.
  • Transformer's transform method now only accepts an Iterator[In] instead of a ConsumableLike[*, In]. Opening and closing the underlying iterator is not the Transformer's responsibility. You can use the "parser backend" to obtain an Iterator wrapped in a Resource, e.g. JavaxSource.syncIO.iteratorResource(source)
  • Transformer.parallel removed from the companion object; use the merge member method on Transformer instead
  • Transformer.parallelEither removed removed from the companion object; use the mergeEither member method on Transformer instead
  • Transformer.sideEffect renamed to Transformer.tap

Parser Changes

  • Parser.constant renamed to Parser.pure
  • Parser.foreach renamed to Parser.tap
  • Parser.firstOption renamed to Parser.firstOpt
  • A handful of new Parser constructor methods are available on the Parser companion object
  • The and and ~ methods are removed entirely. Now that Parser is Applicative, you can create a tuple of Parsers and use mapN (which comes from cats.syntax.apply) to combine parsers.
  • Parser[In, Out] no longer extends Any => Parser[In, Out]
  • Parser's parse method now operates in terms of the new Parsable typeclass. ConsumableLike has been removed.
    • Parser now also has a parseF method which lifts execution into a given F[_] effect context
    • One major consequence of this change is that you can no longer directly call parse on an InputStream or Reader; you must first wrap that stream/reader in a cats.effect.Resource to encapsulate the open/close semantics.

Import Changes

  • Previously, XML and JSON support was entirely done via an import to io.dylemma.spac.xml._ or io.dylemma.spac.json._. Now, you need to additionally import a "parser backend" to provide the necessary implicits to let you do things like parser.parse(someFile). To get the old behavior, you'll need to add your choice of dependency and import from its respective *Support object:
    • For XML, add the xml-spac-javax library, and import io.dylemma.spac.xml.JavaxSupport._
    • For JSON, add the json-spac-jackson library, and import io.dylemma.spac.json.JacksonSupport._
  • You may instead choose to import the new fs2-data based parser backends:
    • For XML, add the xml-spac-fs2-data library, and import io.dylemma.spac.xml.Fs2DataSupport._
    • For JSON, add the json-spac-fs2-data library, and import io.dylemma.spac.json.Fs2DataSupport._