1

I am fairly new to scala , play framework and argonaut. Following is my case class which contains a variable of type List[Remedy] My aim is to generate a json response of the PredictionModel object which contains JsonArray of List[Remedy].

package models

import scala.collection.mutable.ListBuffer
import argonaut._, Argonaut._


/**
 * Created by abhishek on 15/01/16.
 */
    case class PredictionModel() {

  var aboutKundali: AboutKundli = new AboutKundli()
  var planetStatus = new ListBuffer[PlanetStatus].toList
  var donate = ""
  var notToDonate = ""
  var colorNotToWear = ""
  var favouredGod = ""
  var aboutEducationAndOccupation = ""
  var mixMahaDashaCurrent = ""
  var mixMahaDashaNotCurrent = ""
  var category = ""
  var rinnPitri = ""
  var lifeHead = ""
  var disease = ""
  var occupation = ""
  var marriedLife = ""
  var santan = ""
  var parents = ""
  var nature = ""
  var remedyList = new ListBuffer[Remedy].toList
  var importantInformation = ""

}

Implicit for PredictionModel is written like :-

implicit def predicationEncodeJson: EncodeJson[PredictionModel] =
    EncodeJson((prediction: PredictionModel) =>
      ("about_kundali" := argonaut.Json(
        "birth_rashi" := prediction.aboutKundali.birthRashi,
        "lagan_rashi" := prediction.aboutKundali.laganRashi,
        "birth_day_planet" := prediction.aboutKundali.birthDayPlanet,
        "birth_time_planet" := prediction.aboutKundali.birthTimePlanet,
        "current_maha_dasha" := prediction.aboutKundali.currentMahaDasha,
        "lucky_day" := prediction.aboutKundali.luckyDay,
        "lucky_number" := prediction.aboutKundali.luckyNumber
      )) ->:
        ("important_information" := prediction.importantInformation) ->:
        ("rinnPitri" := prediction.rinnPitri) ->:
        ("category" := prediction.category) ->:
        ("mix_mahadasha_not_current" := prediction.mixMahaDashaNotCurrent) ->:
        ("mix_mahadasha_current" := prediction.mixMahaDashaCurrent) ->:
        ("about_education_and_occupation" := prediction.aboutEducationAndOccupation) ->:
        ("favored_god" := prediction.favouredGod) ->:
        ("color_not_to_wear" := prediction.colorNotToWear) ->:
        ("donate" := prediction.donate) ->:
        ("not_to_donate" := prediction.notToDonate) ->: jEmptyObject)

Everything about runs just fine, but what should i do to add JsonArray in prodiction Json object

Edit 1 As suggested here is my test case class

import argonaut._, Argonaut._

case class TestModel(id: Int, name: String) {

}

object TestModel{
  implicit def PredictionModelCodecJson = CodecJson[TestModel] =
    casecodec20(TestModel.apply, TestModel.unapply)("id", "name")
}

While declaring casecodec20 i have an error in apply and unapply method. Do i need to over-ride them ? Also how to call this implicit value ?

Edit 2

So here is what needs to be done. Create case class with all the parameters in constrcutor and a subsequent object class which contains CodecJson like below

case class Remedy(no: Int, description: String) {

}

object Remedy{

  implicit def RemedyCodecJson: CodecJson[Remedy] =
    casecodec2(Remedy.apply, Remedy.unapply)("number", "description")
}

In my case i had more complex models inside models so i just created implicit CodecJson for all. How to use it ?

 remedy.asJson
2
  • 1
    what should i do to add JsonArray in prodiction Json object You want to add the remedyList to the outputted JSON? Commented Jan 25, 2016 at 9:46
  • @YuvalItzchakov Yes that is what i am looking for Commented Jan 25, 2016 at 10:36

1 Answer 1

1

When you have a case class it is much easier because you can use casecodec:

implicit def PredictionModel CodecJson: CodecJson[PredictionModel] =
    casecodec20(PredictionModel.apply, PredictionModel.unapply)("aboutKundali", "planetStatus", "donate", .....)

And now you have a JSON codec for your PredictionModel which will encode and decode your case class from/to json.

In order to make it work you can define your AboutKundli, PlanetStatus and Remedy as case classes and create casecodecs for them in a similar way.

Note that it is highly recommended to declare case classes in a way where all the paramerers are defined in their constructors and not how you show in your example. A better way would be:

case class PredictionModel(
  aboutKundali: AboutKundli,
  planetStatus: List[PlanetStatus],
  donate: String,
  notToDonate: String
  colorNotToWear: String
  favouredGod: String,
  aboutEducationAndOccupation: String,
  mixMahaDashaCurrent: String,
  mixMahaDashaNotCurrent: String,
  category: String,
  rinnPitri: String,
  lifeHead: String,
  disease: String,
  occupation: String,
  marriedLife: String,
  santan: String,
  parents: String,
  nature: String,
  remedyList: List[Remedy],
  importantInformation: String)

It is not only stylistic and there are technical reasons to do so (related to how apply/unapply/equality are generated for the case class) so it is better to follow this practice.

In general you should follow the rule that case classes are immutable and all the values are declared as their constructor parameters.

Once you have declared codecs for your case classes you have codecs for lists "for free" because Argonaut can encode List[A] if it can see that it can encode that A, so you don't need to do anything special here.

Sign up to request clarification or add additional context in comments.

3 Comments

Couple of questions 1) do i need to overload / override apply & unapply method ? Where do i implicitly declare the codec in subsequent object of the case class ? import argonaut._, Argonaut._ case class TestModel(id: Int, name: String) { } object TestModel{ implicit def PredictionModelCodecJson = CodecJson[TestModel] = casecodec20(TestModel.apply, TestModel.unapply)("") }
You don't need to override apply/unapply. Scala compiler generates them for case classes automatically. You can declare implicit codecs in companion objects, yes, that would be the simplest. Or you can do it in some other object, but then you will need to import it: import myCodecsPackage._.
You have a problem in your code because you use casecodec20. The number should correspond to the number of constructor parameters. Your PredictionModel has 20 parameters so you must use casecodec20, your TestModel only has 2 so use casecodec2 instead.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.