stringifiers

A standardized way of moving types to and from strings

License

License

GroupId

GroupId

com.olvind
ArtifactId

ArtifactId

stringifiers_2.10
Last Version

Last Version

0.3
Release Date

Release Date

Type

Type

jar
Description

Description

stringifiers
A standardized way of moving types to and from strings
Project URL

Project URL

http://github.com/oyvindberg/stringifiers
Project Organization

Project Organization

com.olvind
Source Code Management

Source Code Management

https://github.com/oyvindberg/stringifiers

Download stringifiers_2.10

How to add to project

<!-- https://jarcasting.com/artifacts/com.olvind/stringifiers_2.10/ -->
<dependency>
    <groupId>com.olvind</groupId>
    <artifactId>stringifiers_2.10</artifactId>
    <version>0.3</version>
</dependency>
// https://jarcasting.com/artifacts/com.olvind/stringifiers_2.10/
implementation 'com.olvind:stringifiers_2.10:0.3'
// https://jarcasting.com/artifacts/com.olvind/stringifiers_2.10/
implementation ("com.olvind:stringifiers_2.10:0.3")
'com.olvind:stringifiers_2.10:jar:0.3'
<dependency org="com.olvind" name="stringifiers_2.10" rev="0.3">
  <artifact name="stringifiers_2.10" type="jar" />
</dependency>
@Grapes(
@Grab(group='com.olvind', module='stringifiers_2.10', version='0.3')
)
libraryDependencies += "com.olvind" % "stringifiers_2.10" % "0.3"
[com.olvind/stringifiers_2.10 "0.3"]

Dependencies

compile (1)

Group / Artifact Type Version
org.scala-lang : scala-library jar 2.10.6

test (2)

Group / Artifact Type Version
org.scalatest : scalatest_2.10 jar 3.0.0
io.argonaut : argonaut_2.10 jar 6.2-RC2

Project Modules

There are no modules declared in this project.

Stringifiers

A Scala micro library for moving values to and from strings, with error handling and abstraction possibilities.

Analogue to Read and Show type classes, but a bit simpler and more specialized. The library aims to be a comfortable introduction to type class-based programming.

In the simplest of cases, these Stringifiers can be used to DRY code which otherwise would ad hoc parse the same types everywhere.

A bit more elaborate use can see them used to derive Json or Xml codecs, for parsing Http parameters, for sql, /etc/.

Example

scala> import com.olvind.stringifiers._
import com.olvind.stringifiers._

scala> case class UserId(value: Int) extends AnyVal
defined class UserId

/* This picks up the bundled instance for `Int`,
    and uses that to construct one for UserId */
scala> implicit val S = Stringifier.instance(UserId)(_.value)
S: Stringifier[UserId] = ...

/* encoding is modelled as not failing */
scala> Stringifier encode UserId(2)
res0: String = 2

/* while parsing, of course, can fail */
scala> Stringifier decode[UserId] "2"
res0: Either[DecodeFail,UserId] = Right(UserId(2))

/* can also use the instance directly */
scala> S decode "zxc"
res0: Either[DecodeFail,UserId] = Left(ValueNotValid(zxc,Typename(UserId),Some(NumberFormatException: For input string: "zxc")))

/* supports optional values */
scala> Stringifier decode[Option[UserId]] ""
res0: Either[com.olvind.stringifiers.DecodeFail,Option[UserId]] = Right(None)

Setup (sbt)

Available for Scala 2.10/2.11:

libraryDependencies += "com.olvind" %% "stringifiers" % "0.2"

And for Scala.js (not compiled for 2.10 because of a scaladoc issue)

libraryDependencies += "com.olvind" %%% "stringifiers" % "0.2"

Type class instance derivation

A lot of operations naturally work for String. By having defined a way to map back and forth, we can provide loads of type class instances with just a few lines of glue code.

So by providing these once:

object ArgonautSupport {
  import scala.language.implicitConversions

  implicit def toEncoder[T](implicit S: Stringifier[T]): EncodeJson[T] =
    EncodeJson[T](S.encode andThen Argonaut.jString)

  implicit def toDecoder[T](implicit S: Stringifier[T]): DecodeJson[T] =
    DecodeJson[T](
      c => c.as[String](DecodeJson.StringDecodeJson) map S.decode flatMap {
        case Right(t) =>
          DecodeResult ok t
        case Left(ValueNotValid(v, t, oe)) =>
          DecodeResult fail (s"«$v» is not a valid ${t.value}${oe.fold("")(": " + _)}", c.history)
        case Left(ValueNotInSet(v, t, ss)) =>
          DecodeResult fail (s"«$v» is not a valid ${t.value}. Not among ${ss.mkString("", "», «", "»]")}", c.history)
      }
    )
}

You can have these implicits automagically:

  case class Secrets(value: Long)
  implicit val S: Stringifier[Secrets] = (Stringifier instance Secrets)(_.value)

  implicitly[EncodeJson[Secrets]]
  implicitly[DecodeJson[Secrets]]

That can naturally be extended to database mapping, rendering for web, etc

Versions

Version
0.3
0.2
0.1