scalaplay-json

Scala Play JSON trouble converting List[CaseClass] to Json String


Not sure where I am going wrong with this it is returning error:

No Json serializer as JsObject found for type List[QM_Category].

Try to implement an implicit OWrites or OFormat for this type.

[error] Json.stringify(Json.toJsObject(a.categories))

Is there a way to define a format for just List[QM_Category]? I thought the format for QM_Category would handle the case class and play is supposed to handle Lists... All I really want to do is take my List and convert it to json string. Pretty straight forward but I am not sure why Play Json doesnt like my format.

Here is my code:

case class QM_Answer (
    answerid: String,
    answerstring: String,
    answerscore: Int
);

case class QM_Question (
    questionid: String,
    questionscore: Int,
    questiongoal: Int,
    questionstring: String,
    questiontype: String,
    questioncomments: String,
    questionisna: Boolean,
    questionishidden: Boolean,
    failcategory: Boolean,
    failform: Boolean,
    answers: List[QM_Answer]
);

case class QM_Category (
    categoryid: String,
    categoryname: String,
    categoryscore: Int,
    categorygoal: Int,
    categorycomments: String,
    categoryishidden: Boolean,
    failcategory: Boolean,
    questions: List[QM_Question]
);

case class SurveySourceRaw (
    ownerid: String,
    formid: String,
    formname: String,
    sessionid: String,
    evaluator: String,
    userid: String,
    timelinekey: Long,
    surveyid: String,
    submitteddate: Long,
    month: String,
    channel: String,
    categories: List[QM_Category]
);

case class SurveySource (
    ownerid: String,
    formid: String,
    formname: String,
    sessionid: String,
    evaluator: String,
    userid: String,
    timelinekey: Long,
    surveyid: String,
    submitteddate: Long,
    month: String,
    channel: String,
    categories: String
);

implicit val qmAnswerFormat = Json.format[QM_Answer];
implicit val qmQuestionFormat = Json.format[QM_Question];
implicit val qmCategoryFormat = Json.format[QM_Category];
implicit val surveySourceRawFormat = Json.format[SurveySourceRaw];

var surveySourceRaw = sc
    .cassandraTable[SurveySourceRaw]("mykeyspace", "mytablename") 
    .select("ownerid",
            "formid",
            "formname",
            "sessionid",
            "evaluator",
            "userid",
            "timelinekey",
            "surveyid",
            "submitteddate",
            "month",
            "channel",
            "categories")

var surveyRelational = surveySourceRaw
        .map(a => SurveySource
            (
                a.ownerid,
                a.formid,
                a.formname,
                a.sessionid,
                a.evaluator,
                a.userid,
                a.timelinekey,
                a.surveyid,
                a.submitteddate,
                a.month,
                a.channel,
                Json.stringify(Json.toJsObject(a.categories))
            )) 



Solution

  • I'm almost embarresed to answer this but sometimes I make it overly complicated. The answer was to just read the column from cassandra as a string instead of a List[QM_Category]. The column in cassandra was defined as:

    categories list<FROZEN<qm.category>>,
    

    I wrongfully assumed I would need to read it in from Cassandra as a list of custom objects. I would then need to use play json to format that class into JSON and then stringify it.

    case class SurveySourceRaw (
        ownerid: String,
        formid: String,
        formname: String,
        sessionid: String,
        evaluator: String,
        userid: String,
        timelinekey: Long,
        surveyid: String,
        submitteddate: Long,
        month: String,
        channel: String,
        categories: List[QM_Category]
    );
    

    When in reality, all I needed to do was read it from cassandra as a type String and it came in as a stringified json. Well played spark cassandra connector, well played.

    case class SurveySourceRaw (
        ownerid: String,
        formid: String,
        formname: String,
        sessionid: String,
        evaluator: String,
        userid: String,
        timelinekey: Long,
        surveyid: String,
        submitteddate: Long,
        month: String,
        channel: String,
        categories: String
    );