2017-09-01 1 views
0

私はScalaのアプリケーションを持っているなどの場合のクラスがある - 私は暗黙のリードを提供するなどSRケースクラスのプロパティX、Y、ZのためのJSON形式を記述する必要が今汎用再生JSONフォーマッタ

case class SR(
    systemId: Option[String] = None, 
    x: Map[Timestamp, CaseClass1] = Map.empty, 
    y: Map[Timestamp, CaseClass2] = Map.empty, 
    y: Map[Timestamp, CaseClass3] = Map.empty 
) 

を -

implicit val mapCMPFormat = new Format[Map[Timestamp, CaseClass1]] { 
    def writes(obj: Map[Timestamp, CaseClass1]): JsValue = 
     JsArray(obj.values.toSeq.map(Json.toJson(_))) 
    def reads(jv: JsValue): JsResult[Map[Timestamp, CaseClass1]] = jv.validate[scala.collection.Seq[CaseClass1]] match { 
     case JsSuccess(objs, path) => JsSuccess(objs.map(obj => obj.dataDate.get -> obj).toMap, path) 
     case err: JsError => err 
    } 
    } 

そしてように同様にYとZ、将来的に、私はSR場合クラスのX、Y、Zのようなより多くのプロパティを追加した後formatorsを提供するために必要されるため。

だから、すべてのタイプの世話をするGeneric Formaterを入手できますか?私の知る限りでは、これを達成するための簡単な方法は、オブジェクトごとに「デフォルト」のリーダーを作成するには、しかし、存在しない

+0

? – cchantep

答えて

1

を行うのは難しいことではありません、のようなもの:

case class VehicleColorForAdd(
    name: String, 
    rgb: String 
) 

object VehicleColorForAdd { 
    implicit val jsonFormat: Format[VehicleColorForAdd] = Json.formats[VehicleColorForAdd] 
} 

この方法で、あなた単にオブジェクトを使用して、暗黙的にアクセスを持って、あなたは何の問題もなく、このオブジェクトを含む他のオブジェクトかもしれないので:

悲しいこと
case class BiggerModel(
    vehicleColorForAdd: VehicleColorForAdd 
) 

object BiggerModel{ 
    implicit val jsonFormat: Format[BiggerModel] = Json.format[BiggerModel] 
} 

を、あなたが各クラス型のためにこれを実行する必要がありますが、あなたは「拡張」することができますたとえば、これは私のデフォルトの読者の一部です:

package common.json 

import core.order.Order 
import org.joda.time.{ DateTime, LocalDateTime } 
import org.joda.time.format.DateTimeFormat 
import core.promotion.{ DailySchedule, Period } 
import play.api.libs.functional.syntax._ 
import play.api.libs.json.Reads._ 
import play.api.libs.json._ 
import play.api.libs.json.{ JsError, JsPath, JsSuccess, Reads } 

import scala.language.implicitConversions 

/** 
* General JSon readers and transformations. 
*/ 
object JsonReaders { 

    val dateTimeFormat = "yyyy-MM-dd HH:mm:ss" 

    class JsPathHelper(val path: JsPath) { 
    def readTrimmedString(implicit r: Reads[String]): Reads[String] = Reads.at[String](path)(r).map(_.trim) 

    def readUpperString(implicit r: Reads[String]): Reads[String] = Reads.at[String](path)(r).map(_.toUpperCase) 

    def readNullableTrimmedString(implicit r: Reads[String]): Reads[Option[String]] = Reads.nullable[String](path)(r).map(_.map(_.trim)) 
    } 

    implicit val localDateTimeReader: Reads[LocalDateTime] = Reads[LocalDateTime]((js: JsValue) => 
    js.validate[String].map[LocalDateTime](dtString => 
     LocalDateTime.parse(dtString, DateTimeFormat.forPattern(dateTimeFormat)))) 

    val localDateTimeWriter: Writes[LocalDateTime] = new Writes[LocalDateTime] { 
    def writes(d: LocalDateTime): JsValue = JsString(d.toString(dateTimeFormat)) 
    } 

    implicit val localDateTimeFormat: Format[LocalDateTime] = Format(localDateTimeReader, localDateTimeWriter) 

    implicit val dateTimeReader: Reads[DateTime] = Reads[DateTime]((js: JsValue) => 
    js.validate[String].map[DateTime](dtString => 
     DateTime.parse(dtString, DateTimeFormat.forPattern(dateTimeFormat)))) 

    implicit def toJsPathHelper(path: JsPath): JsPathHelper = new JsPathHelper(path) 

    val defaultStringMax: Reads[String] = maxLength[String](255) 

    val defaultStringMinMax: Reads[String] = minLength[String](1) andKeep defaultStringMax 

    val rgbRegex: Reads[String] = pattern("""^#([\da-fA-F]{2})([\da-fA-F]{2})([\da-fA-F]{2})$""".r, "error.invalidRGBPattern") 

    val plateRegex: Reads[String] = pattern("""^[\d\a-zA-Z]*$""".r, "error.invalidPlatePattern") 

    val minOnlyWordsRegex: Reads[String] = minLength[String](2) keepAnd onlyWordsRegex 

    val positiveInt: Reads[Int] = min[Int](1) 

    val zeroPositiveInt: Reads[Int] = min[Int](0) 

    val zeroPositiveBigDecimal: Reads[BigDecimal] = min[BigDecimal](0) 

    val positiveBigDecimal: Reads[BigDecimal] = min[BigDecimal](1) 

    def validLocalDatePeriod()(implicit reads: Reads[Period]) = 
    Reads[Period](js => reads.reads(js).flatMap { o => 
     if (o.startPeriod isAfter o.endPeriod) 
     JsError("error.startPeriodAfterEndPeriod") 
     else 
     JsSuccess(o) 
    }) 

    def validLocalTimePeriod()(implicit reads: Reads[DailySchedule]) = 
    Reads[DailySchedule](js => reads.reads(js).flatMap { o => 
     if (o.dailyStart isAfter o.dailyEnd) 
     JsError("error.dailyStartAfterDailyEnd") 
     else 
     JsSuccess(o) 
    }) 
} 

次に、あなただけのすべてのこの暗黙のコンバータへのアクセス権を持つようにこのオブジェクトをインポートする必要があります。すでにこの質問の前に試してみましたが何

package common.forms 

import common.json.JsonReaders._ 
import play.api.libs.json._ 

/** 
* Form to add a model with only one string field. 
*/ 
object SimpleCatalogAdd { 

    case class Data(
    name: String 
) 

    implicit val dataReads: Reads[Data] = (__ \ "name").readTrimmedString(defaultStringMinMax).map(Data.apply) 
} 
+0

ええ、私はすでにそれを行っていますが、それでもMap [Timestamp、CaseClass1]のフォーマットが必要です。 –

+0

Editer私の答えは、例がうまくいき、Mapリーダーやライターを達成するためのアイデアを提供してくれることを願っています。詳細はhttps://stackoverflow.com/questions/20029412/scala-play-parse-json-into- map-instead-of-jsobject – rekiem87

関連する問題