SlideShare una empresa de Scribd logo
1 de 19
Descargar para leer sin conexión
JSON OBJECTS RDBMSTO TO
Stephen Kemmerling
@42eng
CONTACTS AS A SERVICE
Should have JSON endpoints for
• Store contact information
• Retrieval by Name
Contacts as a Service
https://github.com/FortyTwoEng/
Contacts-As-A-Service/blob/master/
app/controllers/Application.scala
• OO Representation
• Handle JSON requests and convert to OO
• Save to DB/Load from DB
What do we need?
• OO Representation
• Handle JSON requests and convert to OO
• Save to DB/Load from DB
What do we need?
SCALA REPRESENTATION
case class Email(addr: String)
case class Contact(
name: String,
phone: Option[Int],
email: Option[Email]
)
• OO Representation
• Handle JSON requests and convert to OO
• Save to DB/Load from DB
What do we need?
SENDING JSON RESPONSES
def lookup(name: String) = Action { request =>
val contacts : Seq[Contact] = loadFromDb(name)
val contactsJson : Seq[JsValue] = contacts.map(Json.toJson(_))
Ok(JsArray(contactsJson))
}
TO/FROM JSON
trait Format[T] {
def reads(json: JsValue): JsResult[T]
def writes(obj: T): JsValue
}
MACROS!
object Contact {
implicit val format: Format[Contact] =
Json.format[Contact]
}
Almost, but not quite: Can’t deal with Email
case class Email(addr: String)
case class Contact(
name: String,
phone: Option[Int],
email: Option[Email]
)
MAGIC!
FORMAT BY HAND
object Email {
implicit format : Format[Email] = Json.format[Email]
}
Let’s not be lazy
FORMAT BY HAND
object Email {
implicit val format = new Format[Email]{
def reads(json: JsValue) : JsResult[Email] = {
json match{
case JsString(s) => JsSuccess(Email(s))
case _ => JsError()
}
}
def writes(email: Email) : JsValue = {
JsString(email.addr)
}
}
}
ACCEPTING JSON
REQUESTS
def store(name: String) = Action(parse.tolerantJson)
{ request =>
val phoneJson : JsValue = request.body  "phone"
val phone : Option[Int] = phoneJson.asOpt[Int]
val email = (request.body  "email").asOpt[Email]
val contact = Contact(name, phone, email)
saveToDb(contact)
Ok(“”)
}
ALL TOGETHER NOW
def lookup(name: String) = Action { request =>
val contacts : Seq[Contact] = loadFromDb(name)
val contactsJson : Seq[JsValue] =
contacts.map(Json.toJson(_))
Ok(JsArray(contactsJson))
}
def store(name: String) = Action(parse.tolerantJson)
{ request =>
val phoneJson : JsValue = request.body  "phone"
val phone : Option[Int] = phoneJson.asOpt[Int]
val email = (request.body  "email").asOpt[Email]
val contact = Contact(name, phone, email)
saveToDb(contact)
Ok(“”)
}
• OO Representation
• Handle JSON requests and convert to OO
• Save to DB/Load from DB
What do we need?
SLICK TABLE DEFINITION
object Contacts extends Table[Contact]("contacts") {
def name = column[String]("name", O.PrimaryKey)
def phone = column[Int]("phone", O.Nullable)
def email = column[Email]("email", O.Nullable)
def * = name ~ phone.? ~ email.?
<> (Contact.apply _, Contact.unapply _)
}
INSERTS AND LOOKUPS
def saveToDb(contact: Contact) =
database.withSession{ implicit session: Session =>
Contacts.*.insert(contact)
}
def loadFromDb(name: String) =
database.withSession{ implicit session: Session =>
(for (row <- Contacts if row.name===name) yield row).list
}
SLICK TABLE DEFINITION
object Contacts extends Table[Contact]("contacts") {
def name = column[String]("name", O.PrimaryKey)
def phone = column[Int]("phone", O.Nullable)
def email = column[Email]("email", O.Nullable)
def * = name ~ phone.? ~ email.?
<> (Contact.apply _, Contact.unapply _)
}
def saveToDb(contact: Contact) =
database.withSession{ implicit session: Session =>
Contacts.*.insert(contact)
}
def loadFromDb(name: String) =
database.withSession{ implicit session: Session =>
(for (row <- Contacts if row.name===name) yield row).list
}
TYPE MAPPER
implicit object typeMapper extends BaseTypeMapper[Email] {
def apply(profile: BasicProfile) : TypeMapperDelegate[Email] = {
val delegate = profile.typeMapperDelegates.stringTypeMapperDelegate
new TypeMapperDelegate[Email] {
def sqlType = delegate.sqlType
def setValue(value: Email, p: PositionedParameters) =
delegate.setValue(value.addr, p)
def setOption(valueOpt: Option[Email], p: PositionedParameters) =
delegate.setOption(valueOpt.map(_.addr), p)
def nextValue(r: PositionedResult): Email =
Email(delegate.nextValue(r))
def sqlTypeName = delegate.sqlTypeName
def updateValue(value: Email, r: PositionedResult) =
delegate.updateValue(value.addr, r)
def zero = Email("towel@42go.com")
}
}
}
e class Email(addr: String)
ect Email {mplicit val format = new
mat[Email]{def reads(json: JsValue) :
sult[Email] = {
json match{case JsString(s) =>
cess(Email(s))case _ => JsError()
}
f writes(email: Email) :
e = {sString(email.addr)
p(name: String) =
rse.json) { request =>
acts : Seq[Contact] =
(name)actsJson : Seq[J
ts.map(J
object Contacts extends
Table[Contact]("contacts") {
def name = column[String]
("name", O.PrimaryKey)
def phone = column[Int]
("phone", O.Nullable)
def email = column[Email]
("email", O.Nullable)
def * = name ~ phone.? ~
email.?
<> (Contact.apply _,
Contact.unapply _)
}
def saveToDb(contact:
database.with
session
meters) =
[Email], p:
gate.setOption(valueOpt.map(_.addr),
Value(r: PositionedResult): Email =
delegate.nextValue(r))
def sqlTypeName = delegate.sqlTypeName
def updateValue(value: Email, r: PositionedResult) =
delegate.updateValue(value.addr, r)
def zero = Email("towel@42go.com")
}
}
}
case class Contact(
name: String,
phone: Option[Int],
email: Option[Email]
)
object Contact {
implicit format : Format[Contact] =
}
SOURCE: https://github.com/FortyTwoEng/Contacts-As-A-Service
FOLLOW US: @42ENG
JOIN US: 42GO.COM/JOIN_US.HTML

Más contenido relacionado

La actualidad más candente

Jython: Python para la plataforma Java (EL2009)
Jython: Python para la plataforma Java (EL2009)Jython: Python para la plataforma Java (EL2009)
Jython: Python para la plataforma Java (EL2009)
Leonardo Soto
 
Jython: Python para la plataforma Java (JRSL 09)
Jython: Python para la plataforma Java (JRSL 09)Jython: Python para la plataforma Java (JRSL 09)
Jython: Python para la plataforma Java (JRSL 09)
Leonardo Soto
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
Dmitry Buzdin
 
Poor Man's Functional Programming
Poor Man's Functional ProgrammingPoor Man's Functional Programming
Poor Man's Functional Programming
Dmitry Buzdin
 
Ciklum net sat12112011-alexander fomin-expressions and all, all, all
Ciklum net sat12112011-alexander fomin-expressions and all, all, allCiklum net sat12112011-alexander fomin-expressions and all, all, all
Ciklum net sat12112011-alexander fomin-expressions and all, all, all
Ciklum Ukraine
 

La actualidad más candente (19)

PureScript & Pux
PureScript & PuxPureScript & Pux
PureScript & Pux
 
The Ring programming language version 1.8 book - Part 43 of 202
The Ring programming language version 1.8 book - Part 43 of 202The Ring programming language version 1.8 book - Part 43 of 202
The Ring programming language version 1.8 book - Part 43 of 202
 
The Ring programming language version 1.3 book - Part 33 of 88
The Ring programming language version 1.3 book - Part 33 of 88The Ring programming language version 1.3 book - Part 33 of 88
The Ring programming language version 1.3 book - Part 33 of 88
 
The Ring programming language version 1.5.2 book - Part 35 of 181
The Ring programming language version 1.5.2 book - Part 35 of 181The Ring programming language version 1.5.2 book - Part 35 of 181
The Ring programming language version 1.5.2 book - Part 35 of 181
 
Jython: Python para la plataforma Java (EL2009)
Jython: Python para la plataforma Java (EL2009)Jython: Python para la plataforma Java (EL2009)
Jython: Python para la plataforma Java (EL2009)
 
The Ring programming language version 1.5.3 book - Part 30 of 184
The Ring programming language version 1.5.3 book - Part 30 of 184The Ring programming language version 1.5.3 book - Part 30 of 184
The Ring programming language version 1.5.3 book - Part 30 of 184
 
Enter The Matrix
Enter The MatrixEnter The Matrix
Enter The Matrix
 
Jython: Python para la plataforma Java (JRSL 09)
Jython: Python para la plataforma Java (JRSL 09)Jython: Python para la plataforma Java (JRSL 09)
Jython: Python para la plataforma Java (JRSL 09)
 
The Ring programming language version 1.3 book - Part 14 of 88
The Ring programming language version 1.3 book - Part 14 of 88The Ring programming language version 1.3 book - Part 14 of 88
The Ring programming language version 1.3 book - Part 14 of 88
 
R environment
R environmentR environment
R environment
 
Sparklyr
SparklyrSparklyr
Sparklyr
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
 
The Ring programming language version 1.2 book - Part 19 of 84
The Ring programming language version 1.2 book - Part 19 of 84The Ring programming language version 1.2 book - Part 19 of 84
The Ring programming language version 1.2 book - Part 19 of 84
 
Using spark data frame for sql
Using spark data frame for sqlUsing spark data frame for sql
Using spark data frame for sql
 
From java to kotlin beyond alt+shift+cmd+k - Droidcon italy
From java to kotlin beyond alt+shift+cmd+k - Droidcon italyFrom java to kotlin beyond alt+shift+cmd+k - Droidcon italy
From java to kotlin beyond alt+shift+cmd+k - Droidcon italy
 
Poor Man's Functional Programming
Poor Man's Functional ProgrammingPoor Man's Functional Programming
Poor Man's Functional Programming
 
Scala on Your Phone
Scala on Your PhoneScala on Your Phone
Scala on Your Phone
 
The Ring programming language version 1.7 book - Part 48 of 196
The Ring programming language version 1.7 book - Part 48 of 196The Ring programming language version 1.7 book - Part 48 of 196
The Ring programming language version 1.7 book - Part 48 of 196
 
Ciklum net sat12112011-alexander fomin-expressions and all, all, all
Ciklum net sat12112011-alexander fomin-expressions and all, all, allCiklum net sat12112011-alexander fomin-expressions and all, all, all
Ciklum net sat12112011-alexander fomin-expressions and all, all, all
 

Similar a Json and SQL DB serialization Introduction with Play! and Slick

JSON Data Parsing in Snowflake (By Faysal Shaarani)
JSON Data Parsing in Snowflake (By Faysal Shaarani)JSON Data Parsing in Snowflake (By Faysal Shaarani)
JSON Data Parsing in Snowflake (By Faysal Shaarani)
Faysal Shaarani (MBA)
 
The Death of Final Tagless
The Death of Final TaglessThe Death of Final Tagless
The Death of Final Tagless
John De Goes
 

Similar a Json and SQL DB serialization Introduction with Play! and Slick (20)

Http4s, Doobie and Circe: The Functional Web Stack
Http4s, Doobie and Circe: The Functional Web StackHttp4s, Doobie and Circe: The Functional Web Stack
Http4s, Doobie and Circe: The Functional Web Stack
 
Sql Server 2000
Sql Server 2000Sql Server 2000
Sql Server 2000
 
Scala best practices
Scala best practicesScala best practices
Scala best practices
 
Power of functions in a typed world
Power of functions in a typed worldPower of functions in a typed world
Power of functions in a typed world
 
JSON Data Parsing in Snowflake (By Faysal Shaarani)
JSON Data Parsing in Snowflake (By Faysal Shaarani)JSON Data Parsing in Snowflake (By Faysal Shaarani)
JSON Data Parsing in Snowflake (By Faysal Shaarani)
 
Creating Domain Specific Languages in Python
Creating Domain Specific Languages in PythonCreating Domain Specific Languages in Python
Creating Domain Specific Languages in Python
 
Oracle Database - JSON and the In-Memory Database
Oracle Database - JSON and the In-Memory DatabaseOracle Database - JSON and the In-Memory Database
Oracle Database - JSON and the In-Memory Database
 
Graph Database Query Languages
Graph Database Query LanguagesGraph Database Query Languages
Graph Database Query Languages
 
Python crush course
Python crush coursePython crush course
Python crush course
 
Relational+algebra (1)
Relational+algebra (1)Relational+algebra (1)
Relational+algebra (1)
 
TDC2018SP | Trilha Java - Java SE 8 for Java EE Developers
TDC2018SP | Trilha Java - Java SE 8 for Java EE DevelopersTDC2018SP | Trilha Java - Java SE 8 for Java EE Developers
TDC2018SP | Trilha Java - Java SE 8 for Java EE Developers
 
Ext GWT 3.0 Data Widgets
Ext GWT 3.0 Data WidgetsExt GWT 3.0 Data Widgets
Ext GWT 3.0 Data Widgets
 
The Death of Final Tagless
The Death of Final TaglessThe Death of Final Tagless
The Death of Final Tagless
 
From Java to Parellel Clojure - Clojure South 2019
From Java to Parellel Clojure - Clojure South 2019From Java to Parellel Clojure - Clojure South 2019
From Java to Parellel Clojure - Clojure South 2019
 
Basics of Python programming (part 2)
Basics of Python programming (part 2)Basics of Python programming (part 2)
Basics of Python programming (part 2)
 
Json
JsonJson
Json
 
Introduction To NHibernate
Introduction To NHibernateIntroduction To NHibernate
Introduction To NHibernate
 
ZIO Prelude - ZIO World 2021
ZIO Prelude - ZIO World 2021ZIO Prelude - ZIO World 2021
ZIO Prelude - ZIO World 2021
 
Json
JsonJson
Json
 
CSV JSON and XML files in Python.pptx
CSV JSON and XML files in Python.pptxCSV JSON and XML files in Python.pptx
CSV JSON and XML files in Python.pptx
 

Último

Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Victor Rentea
 

Último (20)

Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontology
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering Developers
 

Json and SQL DB serialization Introduction with Play! and Slick

  • 1. JSON OBJECTS RDBMSTO TO Stephen Kemmerling @42eng
  • 2. CONTACTS AS A SERVICE Should have JSON endpoints for • Store contact information • Retrieval by Name Contacts as a Service https://github.com/FortyTwoEng/ Contacts-As-A-Service/blob/master/ app/controllers/Application.scala
  • 3. • OO Representation • Handle JSON requests and convert to OO • Save to DB/Load from DB What do we need?
  • 4. • OO Representation • Handle JSON requests and convert to OO • Save to DB/Load from DB What do we need?
  • 5. SCALA REPRESENTATION case class Email(addr: String) case class Contact( name: String, phone: Option[Int], email: Option[Email] )
  • 6. • OO Representation • Handle JSON requests and convert to OO • Save to DB/Load from DB What do we need?
  • 7. SENDING JSON RESPONSES def lookup(name: String) = Action { request => val contacts : Seq[Contact] = loadFromDb(name) val contactsJson : Seq[JsValue] = contacts.map(Json.toJson(_)) Ok(JsArray(contactsJson)) }
  • 8. TO/FROM JSON trait Format[T] { def reads(json: JsValue): JsResult[T] def writes(obj: T): JsValue }
  • 9. MACROS! object Contact { implicit val format: Format[Contact] = Json.format[Contact] } Almost, but not quite: Can’t deal with Email case class Email(addr: String) case class Contact( name: String, phone: Option[Int], email: Option[Email] ) MAGIC!
  • 10. FORMAT BY HAND object Email { implicit format : Format[Email] = Json.format[Email] } Let’s not be lazy
  • 11. FORMAT BY HAND object Email { implicit val format = new Format[Email]{ def reads(json: JsValue) : JsResult[Email] = { json match{ case JsString(s) => JsSuccess(Email(s)) case _ => JsError() } } def writes(email: Email) : JsValue = { JsString(email.addr) } } }
  • 12. ACCEPTING JSON REQUESTS def store(name: String) = Action(parse.tolerantJson) { request => val phoneJson : JsValue = request.body "phone" val phone : Option[Int] = phoneJson.asOpt[Int] val email = (request.body "email").asOpt[Email] val contact = Contact(name, phone, email) saveToDb(contact) Ok(“”) }
  • 13. ALL TOGETHER NOW def lookup(name: String) = Action { request => val contacts : Seq[Contact] = loadFromDb(name) val contactsJson : Seq[JsValue] = contacts.map(Json.toJson(_)) Ok(JsArray(contactsJson)) } def store(name: String) = Action(parse.tolerantJson) { request => val phoneJson : JsValue = request.body "phone" val phone : Option[Int] = phoneJson.asOpt[Int] val email = (request.body "email").asOpt[Email] val contact = Contact(name, phone, email) saveToDb(contact) Ok(“”) }
  • 14. • OO Representation • Handle JSON requests and convert to OO • Save to DB/Load from DB What do we need?
  • 15. SLICK TABLE DEFINITION object Contacts extends Table[Contact]("contacts") { def name = column[String]("name", O.PrimaryKey) def phone = column[Int]("phone", O.Nullable) def email = column[Email]("email", O.Nullable) def * = name ~ phone.? ~ email.? <> (Contact.apply _, Contact.unapply _) }
  • 16. INSERTS AND LOOKUPS def saveToDb(contact: Contact) = database.withSession{ implicit session: Session => Contacts.*.insert(contact) } def loadFromDb(name: String) = database.withSession{ implicit session: Session => (for (row <- Contacts if row.name===name) yield row).list }
  • 17. SLICK TABLE DEFINITION object Contacts extends Table[Contact]("contacts") { def name = column[String]("name", O.PrimaryKey) def phone = column[Int]("phone", O.Nullable) def email = column[Email]("email", O.Nullable) def * = name ~ phone.? ~ email.? <> (Contact.apply _, Contact.unapply _) } def saveToDb(contact: Contact) = database.withSession{ implicit session: Session => Contacts.*.insert(contact) } def loadFromDb(name: String) = database.withSession{ implicit session: Session => (for (row <- Contacts if row.name===name) yield row).list }
  • 18. TYPE MAPPER implicit object typeMapper extends BaseTypeMapper[Email] { def apply(profile: BasicProfile) : TypeMapperDelegate[Email] = { val delegate = profile.typeMapperDelegates.stringTypeMapperDelegate new TypeMapperDelegate[Email] { def sqlType = delegate.sqlType def setValue(value: Email, p: PositionedParameters) = delegate.setValue(value.addr, p) def setOption(valueOpt: Option[Email], p: PositionedParameters) = delegate.setOption(valueOpt.map(_.addr), p) def nextValue(r: PositionedResult): Email = Email(delegate.nextValue(r)) def sqlTypeName = delegate.sqlTypeName def updateValue(value: Email, r: PositionedResult) = delegate.updateValue(value.addr, r) def zero = Email("towel@42go.com") } } }
  • 19. e class Email(addr: String) ect Email {mplicit val format = new mat[Email]{def reads(json: JsValue) : sult[Email] = { json match{case JsString(s) => cess(Email(s))case _ => JsError() } f writes(email: Email) : e = {sString(email.addr) p(name: String) = rse.json) { request => acts : Seq[Contact] = (name)actsJson : Seq[J ts.map(J object Contacts extends Table[Contact]("contacts") { def name = column[String] ("name", O.PrimaryKey) def phone = column[Int] ("phone", O.Nullable) def email = column[Email] ("email", O.Nullable) def * = name ~ phone.? ~ email.? <> (Contact.apply _, Contact.unapply _) } def saveToDb(contact: database.with session meters) = [Email], p: gate.setOption(valueOpt.map(_.addr), Value(r: PositionedResult): Email = delegate.nextValue(r)) def sqlTypeName = delegate.sqlTypeName def updateValue(value: Email, r: PositionedResult) = delegate.updateValue(value.addr, r) def zero = Email("towel@42go.com") } } } case class Contact( name: String, phone: Option[Int], email: Option[Email] ) object Contact { implicit format : Format[Contact] = } SOURCE: https://github.com/FortyTwoEng/Contacts-As-A-Service FOLLOW US: @42ENG JOIN US: 42GO.COM/JOIN_US.HTML