- Notifications
You must be signed in to change notification settings - Fork0
Alter: rename your case class fields at compile time.
License
teodimoff/alter
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Alter will allow you to rename your case class fileds at compile time.The result is a HList, which has the renamed fields. Later this HList can be passed to thestandard derivation type class pipeline eg. to JSON derivation HTTP derivation etc. with respected fields renamed.After you extract the relevant fields from your source (json,http params etc.) you will have a HList which cannot be converted back to original case class.Alter has a method .from (equivalent to shapeless synthesized LabelledGenric[T].from method), which willrename all the fields back to their original names, and then convert the HList to original case class instance.
Alter aims to provide simple way to rename fields without a lookup from intermediate structure like a Map[String,String].Alter will attempt to provide more uniform way for renaming hlists and leave onlythe derivation to the implementations.
We have hypotetical class Test which we want the field 'name' to be renamed to 'othername' and field 'activity' to 'running':
caseclassTest(name:String,age:Int,activity:Boolean)valalter=Alter[Test].gen .rename("name","othername") .rename("activity","running")//.rename("atcivity","running") a typo - does not compile//alter.Out will have HList with the field names changed.//hypotetical derivation typeclass//val derive = Derive[T /*source*/,alter.Out]//val extracted: alter.Out = derive.apply(t: T)//val instanceTest: Test = alter.from(extracted)
- circe(depends on circe-shapes and circe-generic)
- more to come
importio.generic.Alterimportio.generic.circe._caseclassLevel(advance:String,duration:Int,shockIntensive:Boolean,sets:Int)caseclassRoutine(name:String,creator:String,exercises:Int,intense:Boolean,level:Level)caseclassDiet(source:String,calories:Int,gain:Boolean,routine:Routine)caseclassHuman(name:String,age:Int,weight:Double,height:Double,diet:Diet,training:Training)sealedtraitTrainingcaseclassGym(name:String,isCrowded:Boolean,minMembership:Int,miles:Int)extendsTrainingcaseclassStreetFitness(park:String,equipment:Int,peakHour:Int)extendsTrainingvalalterHuman=Alter[Human].gen .rename("height","feets") .rename("weight","lbs") .rename("training","training_type")//can change the name of adt though .rename("gain","gainOriented") .rename("creator","trainer_creator") .rename("duration","minutes")valdecoder: io.circe.Decoder[Human]= alterHuman.decodervalencoder: io.circe.Encoder[Human]= alterHuman.encodervalhuman=Human("leonardo",32,176.36,5.6,Diet("meat",2500,true,Routine("blackout","Tim",24,true,Level("expert",45,true,3))),StreetFitness("south park",12,1900))valjson= encoder(human)/*val json: io.circe.Json = { "name" : "leonardo", "age" : 32, "lbs" : 176.36, "feets" : 5.6, "diet" : { "source" : "meat", "calories" : 2500, "gainOriented" : true, "routine" : { "name" : "blackout", "trainer_creator" : "Tim", "exercises" : 24, "intense" : true, "level" : { "advance" : "expert", "minutes" : 45, "shockIntensive" : true, "sets" : 3 } } }, "training_type" : { "StreetFitness" : { "park" : "south park", "equipment" : 12, "peakHour" : 1900 } } }*/valfromJsonHuman= decoder.decodeJson(json)/*io.circe.Decoder.Result[io.generic.circe.Human] =Right( Human(leonardo,32,176.36,5.6, Diet(meat,2500,true,Routine(blackout,24,true, Level(expert,45,true,3))), StreetFitness(south park,12,1900)))*/
It is important to notice change order of nested case calsses or you might get implicit not found. In the Human example, the order of changes are from outer to inner:
Human(fields - height, weight, training) -> Diet(field - gain) -> Routine(field - creator) -> Level(field - duration)
For the moment Alter supports only renaming HList fields, as this is the most common use case.There is no direct support (read function to convert them all) for snake case or hyphens names (kebab names),because that would require runtime knowledge of the strings.This can be done explicitly:
testHuman.rename("shockIntensive", "shock_intensive")
or
testHuman.rename("shockIntensive", "shock-intensive")
Future version might provide macro based automatic (camel case , kebab case) renaming.