All Projects → kailuowang → Henkan

kailuowang / Henkan

Licence: other
A small library for converting between case classes.

Programming Languages

scala
5932 projects

Projects that are alternatives of or similar to Henkan

AudioConverter
Audio Conversion CLI
Stars: ✭ 17 (-93.51%)
Mutual labels:  conversion
GENERIS
Versatile Go code generator.
Stars: ✭ 32 (-87.79%)
Mutual labels:  conversion
php-unit-conversion
A library providing full PSR-4 compatible unit conversions
Stars: ✭ 47 (-82.06%)
Mutual labels:  conversion
prodict
Prodict, what Python dict meant to be.
Stars: ✭ 102 (-61.07%)
Mutual labels:  conversion
money
Crystal shard for dealing with money and currency conversion
Stars: ✭ 26 (-90.08%)
Mutual labels:  conversion
dftools
Tools for Star Wars: Dark Forces assets.
Stars: ✭ 18 (-93.13%)
Mutual labels:  conversion
txstate
An effort to statically type xstate
Stars: ✭ 64 (-75.57%)
Mutual labels:  typelevel
fib-anyon
An implementation of Fibonacci Anyons in Haskell
Stars: ✭ 18 (-93.13%)
Mutual labels:  typelevel
bitsnpicas
Bits'N'Picas - Bitmap & Emoji Font Creation & Conversion Tools
Stars: ✭ 171 (-34.73%)
Mutual labels:  conversion
alphabet-soup
Type calculations at compile time
Stars: ✭ 40 (-84.73%)
Mutual labels:  typelevel
currency-conversion
Convert Money Amounts between currencies.
Stars: ✭ 19 (-92.75%)
Mutual labels:  conversion
darknet2caffe
Conversion of yolo from DarkNet to Caffe
Stars: ✭ 25 (-90.46%)
Mutual labels:  conversion
quill-markdown-toolbar
A Quill.js module for converting markdown text to rich text format
Stars: ✭ 13 (-95.04%)
Mutual labels:  conversion
GeoJSON.Net.Contrib
Repository for all GeoJSON.Net *.Contrib projects
Stars: ✭ 31 (-88.17%)
Mutual labels:  conversion
sublime-atomizr
Convert Sublime Text completions into Atom (or Visual Studio Code) snippets, and vice versa.
Stars: ✭ 12 (-95.42%)
Mutual labels:  conversion
fastnumbers
Super-fast and clean conversions to numbers.
Stars: ✭ 85 (-67.56%)
Mutual labels:  conversion
PHPCoord
PHPCoord is a PHP library to aid in handling coordinates. It can convert coordinates for a point from one system to another and also calculate distance between points
Stars: ✭ 78 (-70.23%)
Mutual labels:  conversion
eloquent-ffmpeg
High-level API for FFmpeg's Command Line Tools
Stars: ✭ 71 (-72.9%)
Mutual labels:  conversion
rocksmithconvert
Simple standalone OSX app to convert Rocksmith 2014 .psarc (CDLC) files between PC and MAC.
Stars: ✭ 45 (-82.82%)
Mutual labels:  conversion
http4s-dom
http4s, in a browser near you
Stars: ✭ 13 (-95.04%)
Mutual labels:  typelevel

Continuous Integration Latest version

Henkan [変換]

A small library for converting between case classes.

Modules

henkan.convert

Transform between case classes, which minimize the need to manually using constructor to transform information from one case class to another.

Features:

  1. quick transformation when the source case class has all the fields the target case class has: e.g. a.to[B]()

  2. supplement (if source case class doesn't have a field) or override field values. e.g. a.to[B].set(foo = "bar")

  3. use the default values of the target case classes if needed

henkan.optional

Conversion between case classes with optional fields and case class with required fields. One of the use cases for such conversions is conversion between scalaPB generated classes where most fields are Options and internal case classes where you have required fields.

Get started

Henkan is available on Scala 2.12, 2.13 as well as Scala.js

 libraryDependencies += "com.kailuowang" %% "henkan-convert" % "0.6.5"

 libraryDependencies += "com.kailuowang" %% "henkan-optional" % "0.6.5"

Examples

Transform between case classes

import java.time.LocalDate

case class Employee(name: String, address: String, dateOfBirth: LocalDate, salary: Double = 50000d)

case class UnionMember(name: String, address: String, dateOfBirth: LocalDate)

val employee = Employee("George", "123 E 86 St", LocalDate.of(1963, 3, 12), 54000)

val unionMember = UnionMember("Micheal", "41 Dunwoody St", LocalDate.of(1994, 7, 29))

Now use the henkan magic to transform between UnionMember and Employee

import henkan.convert.Syntax._
// import henkan.convert.Syntax._

employee.to[UnionMember]()
// res0: UnionMember = UnionMember(George,123 E 86 St,1963-03-12)

unionMember.to[Employee]()
// res1: Employee = Employee(Micheal,41 Dunwoody St,1994-07-29,50000.0)

unionMember.to[Employee].set(salary = 60000.0)
// res2: Employee = Employee(Micheal,41 Dunwoody St,1994-07-29,60000.0)

Missing fields will fail the compilation

case class People(name: String, address: String)
// defined class People

val people = People("John", "49 Wall St.")
// people: People = People(John,49 Wall St.)
scala> people.to[Employee]() //missing DoB
<console>:20: error: 
    You have not provided enough arguments to convert from People to Employee.
    shapeless.HNil

       people.to[Employee]() //missing DoB
                          ^

Wrong argument types will fail the compilation

scala> unionMember.to[Employee].set(salary = 60) //salary was input as Int rather than Double
<console>:20: error: 
    You have not provided enough arguments to convert from UnionMember to Employee.
    shapeless.labelled.FieldType[Symbol @@ String("salary"),Int] :: shapeless.HNil

error after rewriting to henkan.convert.Syntax.henkanSyntaxConvert[UnionMember](unionMember).to[Employee].set.applyDynamicNamed("apply")(scala.Tuple2("salary", 60))
possible cause: maybe a wrong Dynamic method signature?
       unionMember.to[Employee].set(salary = 60) //salary was input as Int rather than Double
                                   ^

Transform between case classes with optional field

cats.optional provides some facility to transform between case classes with optional fields and ones with required fields. Suppose you have two case classes: Message whose fields are optional and Domain whose fields are required

case class Message(a: Option[String], b: Option[Int])
case class Domain(a: String, b: Int)

You can validate an instance of Message to a Validated Domain

import cats.data.Validated
import cats.implicits._
import henkan.optional.all._
validate(Message(Some("a"), Some(2))).to[Domain]
// res0: henkan.optional.ValidateFromOptional.Result[Domain] = Valid(Domain(a,2))

validate(Message(Some("a"), None)).to[Domain]
// res1: henkan.optional.ValidateFromOptional.Result[Domain] = Invalid(NonEmptyList(RequiredFieldMissing(b)))

The compilation will fail if the from case class doesn't have all fields the target case class needs

case class MessageWithMissingField(a: Option[String])
scala> validate(MessageWithMissingField(Some("a"))).to[Domain]
<console>:24: error: Cannot build validate function from MessageWithMissingField to Domain, possibly due to missing fields in MessageWithMissingField or missing cats instances (`Traverse` instances are needed to convert fields in containers)
       validate(MessageWithMissingField(Some("a"))).to[Domain]
                                                      ^

You can convert in the opposite direction as well

from(Domain("a", 2)).toOptional[Message]
// res3: Message = Message(Some(a),Some(2))

Note that if you from case class does not have all the fields the target class has, they will be set as None

case class DomainWithMissingField(a: String)
scala> from(DomainWithMissingField("a")).toOptional[Message]
res4: Message = Message(Some(a),None)

henkan.optional supports nested case classes as well.

Note that if you are converting scalaPB generated case class, it generates Seq for repeated items, although the underlying implementation is actually List. henkan.optional.all has a Traverse instance for Seq but only works fine when the underlying implementation is either a List or Vector

Other examples can be found in examples including a typesafe config transformer

Contributors and participation

henkan is currently maintained by Kailuo Wang.

Any form of contribution (issue report, PR, etc) is more than welcome.

The henkan project supports the Typelevel code of conduct and wants all of its channels (Gitter, GitHub, etc.) to be welcoming environments for everyone.

License

henkan is licensed under the Apache License, Version 2.0 (the "License"); you may not use this software except in compliance with the License.

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.

Special Thanks

The convert was originally adapted from this gist by @joprice.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].