Wie kann ich mich verwandeln eine Karte, die zu einem Fall der Klasse in Scala?
Wenn ich eine Map[String,String]("url" -> "xxx", "title" -> "yyy")
, ist es ein Weg, um generisch die Umwandlung in eine case class Image(url:String, title:String)
?
Kann ich schreiben Sie einen Helfer:
object Image{
def fromMap(params:Map[String,String]) = Image(url=params("url"), title=params("title"))
}
aber ist es ein Weg, um generisch zu schreiben, dieses mal für eine Karte auf jeden Fall Klasse?
Du musst angemeldet sein, um einen Kommentar abzugeben.
First off, es gibt einige sichere alternativen, die Sie tun könnten, wenn Sie nur wollen, um den code verkürzen. Die companion-Objekt behandelt werden kann wie eine Funktion, so dass Sie könnte so etwas wie dieses:
Diese Rückkehr wird eine option mit dem Ergebnis. Alternativ könnte man die
ApplicativeBuilder
s in Scalaz, die intern tun fast das gleiche, aber mit einem schöneren syntax:Wenn Sie wirklich brauchen, um dies zu tun, über die Reflexion, dann der einfachste Weg wäre, um Paranamer (wie dem Aufzug-Framework). Paranamer wiederherstellen können die Namen der parameter, indem Sie den bytecode so gibt es einen Leistungseinbruch und es funktioniert nicht in allen Umgebungen aufgrund von classloader Probleme (REPL zum Beispiel). Wenn Sie beschränken Sie sich auf Klassen mit nur
String
Konstruktor Parameter, dann könnte man es so machen:(Beachten Sie, dass dieses Beispiel wählen Sie einen Standard-Konstruktor, wie es wird nicht überprüft, ob die parameter zählen, die Sie möchten, um zu tun)
Hier ist eine Lösung mit eingebauten scala/java reflection:
Verwendet werden:
argument type mismatch
Ausnahmen bei der Instanzierung der Klasse?Nicht eine vollständige Antwort auf deine Frage, aber ein Anfang...
Es kann getan werden, aber es wird wahrscheinlich schwieriger, als Sie dachten. Jeder generierte Scala-Klasse, versehen mit der Java-annotation
ScalaSignature
, derenbytes
Mitglied kann analysiert werden, geben Sie die Metadaten, die Sie benötigen (einschließlich argument-Namen). Das format der Signatur ist keine API, jedoch, so müssen Sie analysieren sich selbst (und wahrscheinlich zu ändern, wie Sie analysiert werden, mit jeder neuen major-Scala-release).Vielleicht der beste Ort zu beginnen ist die lift-json Bibliothek, die hat die Fähigkeit zum erstellen von Instanzen von case-Klassen basierend auf JSON-Daten.
Update: ich denke, lift-json nutzt eigentlich Paranamer um dies zu tun, und können daher nicht analysiert werden die bytes von
ScalaSignature
... Das macht diese Technik funktioniert für nicht-Scala-Klassen.Update 2: Sehen Moritz ' Antwort statt, wer ist besser informiert als ich.
Map[String, String]
als input...Gibt es einen hack, die Sie verwandeln können, die Karte zu json und dann zu Fall Klasse.
Ich verwendet, spray-json
und verwenden Sie diese Abhängigkeit im sbt build:
Kann dies nicht gemacht werden, da würden Sie brauchen, um die companion-Objekt die Methode anwenden die parameter-Namen und-Sie sind einfach nicht verfügbar, über die Reflexion. Wenn Sie eine Menge von diesen Klassen, könnten Sie analysieren, Ihre Deklarationen und generieren die fromMap Methoden.
ScalaSignature
bytes...