2016-04-08 26 views
1

Scala genericics'i kullanma Çalma uygulamamdaki bazı genel işlevleri soyutlamaya çalışıyorum. İşlevler, bir REST JSON hizmetinden serileştirilmiş nesnelerle Seq s döndürür.Scala işlev türüne genel bakış

def getPeople(cityName: String): Future[Seq[People]] = { 
    getByEndpoint[People](s"http://localhost/person/$cityName") 
} 

def getPeople(): Future[Seq[Dog]] = { 
    getByEndpoint[Dog]("http://localhost/doge") 
} 

Getirme ve serileştirme mantığı, jenerikler kullanılarak tek bir işlevde toplanır. Sorun

private def getByEndpoint[T](endpoint: String): Future[Seq[T]] = { 

    ws.url(endpoint) 
     .get() 
     .map(rsp => rsp.json) 
     .flatMap { json => 
     json.validate[Seq[T]] match { 
      case s: JsSuccess[Seq[T]] => 
      Future.successful(s.get) 
      case e: JsError => 
      Future.failed(new RuntimeException(s"Get by endpoint JSON match failed: $e")) 
     } 
     } 

} 

ben "No Json deserializer found for type Seq[T]. Try to implement an implicit Reads or Format for this type." alıyorum olduğunu. Eminim T'u Seq[T] (en azından C#/Java hatıralarıma göre) kullanmıyorum, ancak Scala'da nasıl uygun bir şekilde yapılacağına dair bir ipucu bulamıyorum. Her şey jenerik kullanmadan beklendiği gibi çalışır.

+1

'def getByEndpoint [T]' ifadesini 'def getByEndpoint [T: Formatı]' olarak değiştirmeyi deneyin. Bu sizin için işe yararsa, nedenini açıklayan bir cevap yazmaktan mutluluk duyarım. –

+0

Yapıyor! Tahminimce, modellerde belirlediğim Json.format ile bir ilgisi var. Bir cevap yazabilir misiniz, böylece cevap olarak işaretleyebilir miyim? – giannoug

cevap

2

JSON, JSON'a serileştirilebilecek ve nasıl yapılacağı hakkında bilgi edinmek için type classes kullanır. Kapsam içinde Format[Foo] türünde bir örtük değeriniz varsa, Foo için Format tür sınıfının bir örneği olarak adlandırılır.

Bu yaklaşımın avantajı, alt türlere bağlı olmayan genel türlerin (ve derleme zamanında kontrol edilen kısıtlamalara sahip olmasının) kısıtlanması için bir yol sağlamasıdır. Örneğin, standart kitaplığın String'un, Play (veya başka bir kitaplık) tarafından sağlanan Jsonable özelliğinin bir türünü genişletme yolu olmadığından, "String s'yi JSON olarak nasıl kodlandıracağımızı biliyoruz" ifadesine ihtiyacımız var. String'u kendimizi tanımladığımız bir özellik alt türünü oluşturmayı içerir.

Çal JSON size örtülü Format örneklerini tanımlayarak bunu ve kendisi sizin için bu (eğer T için bir tane var ise örneğin, size Seq[T] tane vereceğiz) çoğunu sağlamaktadır oyna edebilirsiniz. JsValue'daki validate yöntemi, bu örneklerden birini (aslında Format, Reads bir alt türü, ancak buradaki tip parametresi için çok önemli değildir) - bu durumda Seq[T] - ve derleyici bu örneği bulamazsa derlenmez.

Kendi jenerik yönteme kısıtlamayı ekleyerek bu örneği sağlayabilir

:

private def getByEndpoint[T: Format](endpoint: String): Future[Seq[T]] = { 
    ... 
} 

Şimdi T: Format sözdizimi ile size (T için Format örneği olmalı belirtti ettik hatta sizin bile don T'u başka herhangi bir yolla kısıtlamamaktadır, dolayısıyla derleyici aramasının gerektirdiği Seq[T] için Format örneğinin nasıl sağlanacağını bilir.

İlgili konular