2017-09-10 2 views
1

Nous avons une API qui a toujours un total-count et entities dans la réponse, mais les entities sont de types différents. Ce que j'essaye de faire est de rendre l'analyse & convertissant en cas-classes plus générique.Comment définir une hiérarchie pour un analyseur générique json-spray?

donc essayer avec les types suivants

case class StandardReturn[A](
    `total-count`: Double, 
    entities: List[A] 
) 

case class System(
    id: String, 
    name: String 
) 

Et l'exemple suivant:

object SystemProtocol extends DefaultJsonProtocol { 
    implicit val systemFormat: RootJsonFormat[System] = 
    jsonFormat2(System) 
    implicit def entityFormat[A: JsonFormat] = 
    jsonFormat(StandardReturn.apply[A], "total-count", "entities") 
} 
import SystemProtocol._ 

val response = """{ 
    "total-count": 10, 
    "entities": [ 
    { "id": "1", "name": "me" } 
    ] 
}""" 

class Example { 
    def transform[A: JsonReader](entityString: String) = 
    entityString.parseJson 
     .convertTo[A] 
     .entities // Where I'm running into trouble 
} 
object Example { 
    val transformed = new Example().transform[StandardReturn[System]](response) 
} 
Example.transformed 

Ce qui me donne naturellement

Error:(34, 42) value entities is not a member of type parameter A 
entityString.parseJson.convertTo[A].entities // Where I'm running into trouble 
            ^

Comment puis-je mettre en place les classes de cas/types de sorte que transform pourrait être assuré que entities sera toujours s existe après la conversion au type A (où A est StandardReturn[A])? Je ne connais pas trop le système de type de scala, merci de votre aide.

Répondre

0

Dans votre code, le paramètre de type A n'a pas de limite sauf le contexte lié à JsonReader (un paramètre implicite de type JsonReader[A]). Par conséquent, comme vous l'avez déjà mentionné, A peut être n'importe quoi, donc vous ne pouvez pas appeler la méthode entities. Si vous convertissez en StandardReturn[A] au lieu de seulement A, ce problème est résolu.

def transform[A: JsonReader](entityString: String) = 
    entityString.parseJson 
    .convertTo[StandardReturn[A]] <- just convert to what you actually want 
    .entities 

De plus, vous devez remplacer le paramètre de type dans new Example().transform[StandardReturn[System]](response) par juste System au lieu de StandardReturn[System], comme la méthode ci-dessus a été modifiée.

Le compilateur a maintenant besoin d'un paramètre implicite de type JsonReader[StandardFormat[System]]. Mais dans la portée implicite, il n'y a que le systemFormat de type JsonReader[System] (en SystemProtocol). Le compilateur n'abandonne pas encore: il essaie de trouver une conversion implicite de JsonReader[System] à JsonReader[StandardFormat[System]], et c'est juste la méthode entityFormat que vous avez définie. Ouais!

Une dernière remarque: Vous pouvez simplifier encore la méthode entityFormat si vous remplacez jsonFormat(StandardReturn.apply[A], "total-count", "entities") par jsonFormat2(StandardReturn.apply[A]), comme il est indiqué dans le documentation.