اكتب قيمة عشوائية غير موجودة في فئة الحالة باستخدام مجمعات Scala JSON الخاصة بـ Play (2.2)

StackOverflow https://stackoverflow.com//questions/23019485

سؤال

أرغب في تنفيذ أ Writes الذي يصدر كائن JSON غير موجود في الفئة التي يتم إجراء تسلسل لها.

لفئة الحالة:

case class Foo(i:Int, s:String)

أنا أتطلع لإنتاج:

{
  "i": <int>,
  "s": "<string>",
  "other": "Some value."
}

المحاولة الأولى الساذجة كانت:

val writes: Writes[Foo] = ((
  (__ \ "i").write[Int] and
    (__ \ "s").write[String] and
    (__ \ "other").write("Some value.")
  )(unlift(Foo.unapply))

وبطبيعة الحال، لن يتم تجميع ذلك كالتالي and المكالمات تنتج أ CanBuild3 و Foounapply ينتج أ Tuple2.لقد بحثت في إلحاق قيمة بالنتيجة، مما أدى إلى إنتاج Tuple3, ، ولكن ما وجدته تبدو سيئة للغاية و ال لن يقوم مشرفو اللغة بتنفيذه.

هناك طرق للتغلب على هذا الأمر، لكنني أفضل عدم تلويث فئات النماذج الخاصة بي بقيم الديكور هذه التي أرغب في إضافتها إلى JSON الناتج.

أي اقتراحات؟

ومن الجدير بالذكر لك يستطيع اذهب في الاتجاه الآخر، مع توفير القيم Reads.pure للحالات التي لا توجد فيها قيمة في JSON ولكن يتم تحديدها بواسطة الكائن الناتج.

هل كانت مفيدة؟

المحلول

يمكنك القيام بذلك بشكل مباشر جدًا عن طريق إزالة السكر قليلاً:

val writes: Writes[Foo] = (
  (__ \ "i").write[Int] and
  (__ \ "s").write[String] and
  (__ \ "other").write[String]
)(foo => (foo.i, foo.s, "Some value."))

ال unlift(Foo.unapply) هي مجرد طريقة رائعة للحصول على وظيفة من ملف Foo إلى صف من النوع الذي يتطلبه تعبير المنشئ التطبيقي السابق، ويمكنك استبداله بوظيفتك الخاصة التي يمكنها إضافة ما تريد.

اذا أنت حقًا أردت بناء جملة أكثر نظافة، يمكنك استخدامه بشع:

import shapeless.syntax.std.tuple._

val writes: Writes[Foo] = (
  (__ \ "i").write[Int] and
  (__ \ "s").write[String] and
  (__ \ "other").write[String]
)(_ :+ "Some value.")

انها جميلة، ولكن قد تكون مبالغة.

نصائح أخرى

هناك خيار آخر وهو استخدام منشئ الكائنات الذي يقوم بتنفيذ unapply التي ترجع القيم الإضافية.وهذا يجعل عملية الكتابة أكثر نظافة، ولكنه يضيف كائنًا جديدًا.لقد وجدت هذا مفيدًا على الرغم من أنه يمكن استخدام كل من الطريقة application و unapply للتدليك الإضافي للبيانات في الكائن النهائي (على سبيل المثال: https://stackoverflow.com/a/22504468/1085606)

مثال:

case class Foo(i: Int, s: String)

object FooBuilder {
  def unapply(foo: Foo): Option[(Int, String, String)] = {
    Some((foo.i, foo.s, "Some extra value"))
  }
}

val writes: Writes[Foo] = ((
  (__ \ "i").write[Int] and
    (__ \ "s").write[String] and
    (__ \ "other").write[String]
  )(unlift(FooBuilder.unapply))
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top