2017-07-27 4 views
1

comme indiqué dans le titre, je ne suis pas en mesure de marshall List[A] dans le bon JSON (tableau d'objets). J'utilise AKKA-Http et Spray-Json.Impossible pour JSON Marshal B défini comme Liste [A] en utilisant AKKA-Http et Spray-Json

I définit deux classes de cas:

final case class Item(id: String, pid: String, title: String) 
final case class Items(items: List[Item]) 

Et cet appel GET http://localhost:8080/item REÇUES:

class ItemEndpoint extends Directives with ItemJsonSupport { 

    val route: Route = { 
    path("item") { 
     get { 
     parameters("page".?, "size".?) { 
      (page, size) => (page, size) match { 
      case (_, _) => 
       onSuccess(Server.requestHandler ? GetItemsRequest){ 
       case response: Items => 
        complete(response) 
       case _ => 
        complete(StatusCodes.InternalServerError) 
       } 
      } 
     } 
     } 
    } 
    }  

} 

GetItemsRequest est appelé. Ce dernier est défini comme

case class GetItemsRequest 

Et le RequestHandler comme

class RequestHandler extends Actor with ActorLogging { 

    var items : Items = _ 

    def receive: Receive = { 
    case GetItemsRequest => 
     items = itemFactory.getItems 
     sender() ! items 
    } 

} 

Lorsque getItems effectue une recherche sur les Cassandra via Spark

def getItems() : Items = { 
    val query = sc.sql("SELECT * FROM mydb") 
    Items(query.map(row => Item(row.getAs[String]("item"), 
          row.getAs[String]("pid"), row.getAs[String]("title") 
    )).collect().toList) 
} 

retour Items contenant List[Item]. Tous les objets sont imprimés correctement (certains d'entre eux ont des champs nuls).

En utilisant ItemJsonFormatter

trait ItemJsonSupport extends SprayJsonSupport with DefaultJsonProtocol { 
    implicit val itemFormat: RootJsonFormat[Item] = jsonFormat3(Item) 
    implicit val itemsFormat: RootJsonFormat[Items] = jsonFormat1(Items) 
} 

conduit à l'erreur suivante:

[simple-rest-system-akka.actor.default-dispatcher-9] [akka.actor.ActorSystemImpl(simple-rest-system)] Error during processing of request: 'requirement failed'. Completing with 500 Internal Server Error response. To change default exception handling behavior, provide a custom ExceptionHandler. java.lang.IllegalArgumentException: requirement failed

J'ai essayé attraper l'exception et le travail sur elle, mais je n'ai pas obtenu plus intel sur le problème.

J'ai suivi AKKA DOCS lors d'un marshalling. En faisant la même chose, mais en obtenant seulement 1 article, cela fonctionne très bien, j'obtiens un json contenant tous les paramètres de Item bien formatés.

{ 
    "id": "78289232389", 
    "pid": "B007ILCQ8I", 
    "title": "" 
} 

Même regarder d'autres Q/A connexe, je n'ai pas pu trouver une réponse, si Qu'est-ce qui cause cela? Comment puis-je le réparer?

Répondre

1

All the objects are printed correctly (some of them have null fields).

L'exception pourrait être jeté parce que getItems est de retour Item objets qui ont une ou plusieurs valeurs de champ nul.

Une façon de gérer cela est de remplacer par des valeurs nulles des chaînes vides:

def rowToItem(row: Row): Item = { 
    Item(Option(row.getAs[String]("item")).getOrElse(""), 
     Option(row.getAs[String]("pid")).getOrElse(""), 
     Option(row.getAs[String]("title")).getOrElse("")) 
} 

def getItems(): Items = { 
    val query = sc.sql("SELECT * FROM mydb") 
    Items(query.map(row => rowToItem(row)).collect().toList) 
} 
+0

Je ne peux pas tester car j'ai des problèmes de version avec dépendances. Acceptera bientôt si cela fonctionne. Quoi qu'il en soit, je ne comprends pas pourquoi avec un seul élément ce problème ne se produit pas. Même si j'ai des champs vides, quand je le fais avec un seul, je n'ai pas d'erreurs. Une idée? – AndreaM16

+0

Dans votre exemple avec le seul élément 'Item', la valeur du champ' "title" 'apparaît être une chaîne vide, pas une valeur nulle. – chunjef