2014-05-08 68 views
6

我已經編寫了一個解析器,它按照一些規則將字符串轉換爲Seq [String]。這將用於圖書館。以類型安全的方式將Seq [String]轉換爲一個case類

我試圖將此Seq [String]轉換爲案例類。案例類將由用戶提供(所以沒有辦法猜測它會是什麼)。

我以爲沒有形狀的圖書館,因爲它似乎實現了良好的功能,它似乎成熟,但我不知道如何進行。

我發現了這個問題with an interesting answer但我找不到如何改變它以滿足我的需求。的確,在答案中只有一種類型需要解析(String),並且庫在String內部進行迭代。這可能需要對事情做出深刻的改變,我不知道如何做。

此外,如果可能的話,我希望爲我的圖書館的用戶儘可能簡化該過程。所以,如果可能的話,不像上面鏈接中的答案,HList類型可以從case類本身猜測(不過根據我的搜索,似乎編譯器需要這些信息)。

我對類型系統和所有這些美麗的東西有點新,如果有人能夠給我一個關於如何做的建議,我會非常高興!

親切的問候

---編輯---

由於ziggystar要求,這裏是一些可能需要的簽名:

//Let's say we are just parsing a CSV. 

@onUserSide 
case class UserClass(i:Int, j:Int, s:String) 
val list = Seq("1,2,toto", "3,4,titi") 

// User transforms his case class to a function with something like: 
val f = UserClass.curried 

// The function created in 1/ is injected in the parser 
val parser = new Parser(f) 

// The Strings to convert to case classes are provided as an argument to the parse() method. 
val finalResult:Seq[UserClass] = parser.parse(list) 
// The transfomation is done in two steps inside the parse() method: 
// 1/ first we have: val list = Seq("1,2,toto", "3,4,titi") 
// 2/ then we have a call to internalParserImplementedSomewhereElse(list) 
// val parseResult is now equal to Seq(Seq("1", "2", "toto"), Seq("3","4", "titi")) 
// 3/ finally Shapeless do its magick trick and we have Seq(UserClass(1,2,"toto"), UserClass(3,4,"titi)) 



@insideTheLibrary 
class Parser[A](function:A) { 

//The internal parser takes each String provided through argument of the method and transforms each String to a Seq[String]. So the Seq[String] provided is changed to Seq[Seq[String]]. 
private def internalParserImplementedSomewhereElse(l:Seq[String]): Seq[Seq[String]] = { 
    ... 
} 

/* 
* Class A and B are both related to the case class provided by the user: 
* - A is the type of the case class as a function, 
* - B is the type of the original case class (can be guessed from type A). 
*/ 
private def convert2CaseClass[B](list:Seq[String]): B { 
    //do something with Shapeless 
    //I don't know what to put inside ??? 
} 

def parse(l:Seq[String]){ 
    val parseResult:Seq[Seq[String]] = internalParserImplementedSomewhereElse(l:Seq[String]) 
    val finalResult = result.map(convert2CaseClass) 
    finalResult // it is a Seq[CaseClassProvidedByUser]  
} 
}  

庫裏面的一些隱性將提供給將字符串轉換爲正確的類型,因爲它們被Shapeless猜出(類似於上面鏈接中提出的回答)。像string.toInt,string.ToDouble等...

可能還有其他方法來設計它。這正是我在幾個小時玩完無形之後所想到的。

+3

你可以發佈代碼來說明你期望的結果嗎?只是方法簽名將會很好。也許用'library'和'user'來註釋它們。 – ziggystar

+0

你可以舉一個調用convert2CaseClass的例子,也可以解析結果應該是什麼? –

+0

@DidierDupont我按照要求在庫中添加了一些可能的實現。結果應該是案例類的列表。 Seq [String] - > Seq [Seq [String]] - > Seq [case class]。第一個轉換已經被編碼。第二個是我需要幫助的那個。 – pommedeterresautee

回答

0

這個答案不會告訴你如何做到你想要的,但它會解決你的問題。我認爲你過於複雜的事情。

你想要做什麼?在我看來,你只是尋找一種方法來serialize反序列化您的案例類 - 即將您的Scala對象轉換爲通用字符串格式,並將通用字符串格式轉換回Scala對象。你的序列化步驟目前是你似乎已經定義的,你在問如何進行反序列化。

有一些可用於Scala的序列化/反序列化選項。你不需要用Shapeless或Scalaz來自己動手。試着看看這些解決方案:

  1. Java serialization/deserialization。 Java環境提供的常規序列化/反序列化工具。需要明確的轉換,並且不能控制序列化格式,但它內置並且不需要太多工作來實現。
  2. JSON序列化:有許多庫爲Java提供JSON生成和解析。例如,看看play-json,spray-jsonArgonaut
  3. Scala Pickling庫是一個更通用的序列化/反序列化庫。開箱即用的是一些二進制和一些JSON格式,但您可以創建自己的格式。

在這些解決方案,至少play-json和Scala酸洗使用宏來的產生在編譯時串行器和解串器爲您服務。這意味着它們都應該是類型安全和高性能的。

+0

你對我想做的事情是正確的:我想將字符串反序列化爲case類,但是我想使它成爲automagick,我不希望我的lib的用戶每次都需要編寫自己的解串器,通過利用Shapeless,我將能夠獲得case類的類型,我可以編寫一些隱式轉換器來反序列化最常見的類型(int,double,long ...)並提供用戶提供自己的轉換(日期,時間,無論)。因爲我真的需要無形。因爲我有一個特定的格式來反序列化,我不能使用現有的Json庫來在這裏列出。 – pommedeterresautee

+1

我想我有點誤解了這個問題 - 但是,斯卡拉皮克林一般應該朝着你想要的方向發展。一探究竟。 – DCKing

+0

我在尋找一些使用Scala Pickling的例子,起初它似乎很有趣,但是我發現您可能需要針對您要使用的每種類型(表示每個案例類)的自定義格式的自定義反序列化器。此外,文件非常薄。 – pommedeterresautee

1

這使用了一個名爲product-collecions

import com.github.marklister.collections.io._ 
case class UserClass(i:Int, j:Int, s:String) 

val csv = Seq("1,2,toto", "3,4,titi").mkString("\n") 
csv: String = 
1,2,toto 
3,4,titi 

CsvParser(UserClass).parse(new java.io.StringReader(csv)) 
res28: Seq[UserClass] = List(UserClass(1,2,toto), UserClass(3,4,titi)) 

而且連載的其他方式很簡單庫:

scala> res28.csvIterator.toList 
res30: List[String] = List(1,2,"toto", 3,4,"titi") 

產品的集合定向向CSV和的java.io.Reader,因此上面的墊片。

相關問題